@@ -18,6 +18,7 @@ var emptyObject = require('emptyObject');
1818var invariant = require ( 'invariant' ) ;
1919var {
2020 getComponentName,
21+ isFiberMounted,
2122} = require ( 'ReactFiberTreeReflection' ) ;
2223var {
2324 ClassComponent,
@@ -64,45 +65,58 @@ exports.hasContextChanged = function() : boolean {
6465 return index > - 1 && didPerformWorkStack [ index ] ;
6566} ;
6667
67- exports . isContextProvider = function ( fiber : Fiber ) : boolean {
68+ function isContextProvider ( fiber : Fiber ) : boolean {
6869 return (
6970 fiber . tag === ClassComponent &&
7071 typeof fiber . stateNode . getChildContext === 'function'
7172 ) ;
72- } ;
73+ }
74+ exports . isContextProvider = isContextProvider ;
7375
7476exports . popContextProvider = function ( ) : void {
7577 contextStack [ index ] = emptyObject ;
7678 didPerformWorkStack [ index ] = false ;
7779 index -- ;
7880} ;
7981
80- exports . pushContextProvider = function ( fiber : Fiber , didPerformWork : boolean ) : void {
82+ exports . pushTopLevelContextObject = function ( context : Object , didChange : boolean ) : void {
83+ invariant ( index === - 1 , 'Unexpected context found on stack' ) ;
84+ index ++ ;
85+ contextStack [ index ] = context ;
86+ didPerformWorkStack [ index ] = didChange ;
87+ } ;
88+
89+ function processChildContext ( fiber : Fiber , parentContext : Object ) : Object {
8190 const instance = fiber . stateNode ;
8291 const childContextTypes = fiber . type . childContextTypes ;
92+ const childContext = instance . getChildContext ( ) ;
93+ for ( let contextKey in childContext ) {
94+ invariant (
95+ contextKey in childContextTypes ,
96+ '%s.getChildContext(): key "%s" is not defined in childContextTypes.' ,
97+ getComponentName ( fiber ) ,
98+ contextKey
99+ ) ;
100+ }
101+ if ( __DEV__ ) {
102+ const name = getComponentName ( fiber ) ;
103+ const debugID = 0 ; // TODO: pass a real ID
104+ checkReactTypeSpec ( childContextTypes , childContext , 'childContext' , name , null , debugID ) ;
105+ }
106+ return { ...parentContext , ...childContext } ;
107+ }
108+ exports . processChildContext = processChildContext ;
83109
110+ exports . pushContextProvider = function ( fiber : Fiber , didPerformWork : boolean ) : void {
111+ const instance = fiber . stateNode ;
84112 const memoizedMergedChildContext = instance . __reactInternalMemoizedMergedChildContext ;
85113 const canReuseMergedChildContext = ! didPerformWork && memoizedMergedChildContext != null ;
86114
87115 let mergedContext = null ;
88116 if ( canReuseMergedChildContext ) {
89117 mergedContext = memoizedMergedChildContext ;
90118 } else {
91- const childContext = instance . getChildContext ( ) ;
92- for ( let contextKey in childContext ) {
93- invariant (
94- contextKey in childContextTypes ,
95- '%s.getChildContext(): key "%s" is not defined in childContextTypes.' ,
96- getComponentName ( fiber ) ,
97- contextKey
98- ) ;
99- }
100- if ( __DEV__ ) {
101- const name = getComponentName ( fiber ) ;
102- const debugID = 0 ; // TODO: pass a real ID
103- checkReactTypeSpec ( childContextTypes , childContext , 'childContext' , name , null , debugID ) ;
104- }
105- mergedContext = { ...getUnmaskedContext ( ) , ...childContext } ;
119+ mergedContext = processChildContext ( fiber , getUnmaskedContext ( ) ) ;
106120 instance . __reactInternalMemoizedMergedChildContext = mergedContext ;
107121 }
108122
@@ -115,3 +129,20 @@ exports.resetContext = function() : void {
115129 index = - 1 ;
116130} ;
117131
132+ exports . findCurrentUnmaskedContext = function ( fiber : Fiber ) : Object {
133+ // Currently this is only used with renderSubtreeIntoContainer; not sure if it
134+ // makes sense elsewhere
135+ invariant (
136+ isFiberMounted ( fiber ) && fiber . tag === ClassComponent ,
137+ 'Expected subtree parent to be a mounted class component'
138+ ) ;
139+
140+ let node : ?Fiber = parent ;
141+ while ( node ) {
142+ if ( isContextProvider ( fiber ) ) {
143+ return fiber . stateNode . __reactInternalMemoizedMergedChildContext ;
144+ }
145+ node = node . return ;
146+ }
147+ return emptyObject ;
148+ } ;
0 commit comments