77 * @flow
88 */
99
10+ import type { ThreadID } from './ReactThreadIDAllocator' ;
1011import type { ReactElement } from 'shared/ReactElementType' ;
1112import type { ReactProvider , ReactContext } from 'shared/ReactTypes' ;
1213
@@ -16,7 +17,6 @@ import getComponentName from 'shared/getComponentName';
1617import lowPriorityWarning from 'shared/lowPriorityWarning' ;
1718import warning from 'shared/warning' ;
1819import warningWithoutStack from 'shared/warningWithoutStack' ;
19- import checkPropTypes from 'prop-types/checkPropTypes' ;
2020import describeComponentFrame from 'shared/describeComponentFrame' ;
2121import ReactSharedInternals from 'shared/ReactSharedInternals' ;
2222import {
@@ -39,6 +39,12 @@ import {
3939 REACT_MEMO_TYPE ,
4040} from 'shared/ReactSymbols' ;
4141
42+ import {
43+ emptyObject ,
44+ processContext ,
45+ validateContextBounds ,
46+ } from './ReactPartialRendererContext' ;
47+ import { allocThreadID , freeThreadID } from './ReactThreadIDAllocator' ;
4248import {
4349 createMarkupForCustomAttribute ,
4450 createMarkupForProperty ,
@@ -50,6 +56,8 @@ import {
5056 finishHooks ,
5157 Dispatcher ,
5258 DispatcherWithoutHooks ,
59+ currentThreadID ,
60+ setCurrentThreadID ,
5361} from './ReactPartialRendererHooks' ;
5462import {
5563 Namespaces ,
@@ -176,7 +184,6 @@ const didWarnAboutBadClass = {};
176184const didWarnAboutDeprecatedWillMount = { } ;
177185const didWarnAboutUndefinedDerivedState = { } ;
178186const didWarnAboutUninitializedState = { } ;
179- const didWarnAboutInvalidateContextType = { } ;
180187const valuePropNames = [ 'value' , 'defaultValue' ] ;
181188const newlineEatingTags = {
182189 listing : true ,
@@ -324,65 +331,6 @@ function flattenOptionChildren(children: mixed): ?string {
324331 return content ;
325332}
326333
327- const emptyObject = { } ;
328- if ( __DEV__ ) {
329- Object . freeze ( emptyObject ) ;
330- }
331-
332- function maskContext ( type , context ) {
333- const contextTypes = type . contextTypes ;
334- if ( ! contextTypes ) {
335- return emptyObject ;
336- }
337- const maskedContext = { } ;
338- for ( const contextName in contextTypes ) {
339- maskedContext [ contextName ] = context [ contextName ] ;
340- }
341- return maskedContext ;
342- }
343-
344- function checkContextTypes ( typeSpecs , values , location : string ) {
345- if ( __DEV__ ) {
346- checkPropTypes (
347- typeSpecs ,
348- values ,
349- location ,
350- 'Component' ,
351- getCurrentServerStackImpl ,
352- ) ;
353- }
354- }
355-
356- function processContext ( type , context ) {
357- const contextType = type . contextType ;
358- if ( typeof contextType === 'object' && contextType !== null ) {
359- if ( __DEV__ ) {
360- if ( contextType . $$typeof !== REACT_CONTEXT_TYPE ) {
361- let name = getComponentName ( type ) || 'Component' ;
362- if ( ! didWarnAboutInvalidateContextType [ name ] ) {
363- didWarnAboutInvalidateContextType [ type ] = true ;
364- warningWithoutStack (
365- false ,
366- '%s defines an invalid contextType. ' +
367- 'contextType should point to the Context object returned by React.createContext(). ' +
368- 'Did you accidentally pass the Context.Provider instead?' ,
369- name ,
370- ) ;
371- }
372- }
373- }
374- return contextType . _currentValue ;
375- } else {
376- const maskedContext = maskContext ( type , context ) ;
377- if ( __DEV__ ) {
378- if ( type . contextTypes ) {
379- checkContextTypes ( type . contextTypes , maskedContext , 'context' ) ;
380- }
381- }
382- return maskedContext ;
383- }
384- }
385-
386334const hasOwnProperty = Object . prototype . hasOwnProperty ;
387335const STYLE = 'style' ;
388336const RESERVED_PROPS = {
@@ -453,6 +401,7 @@ function validateRenderResult(child, type) {
453401function resolve (
454402 child : mixed ,
455403 context : Object ,
404+ threadID : ThreadID ,
456405) : { |
457406 child: mixed ,
458407 context : Object ,
@@ -472,7 +421,7 @@ function resolve(
472421
473422 // Extra closure so queue and replace can be captured properly
474423 function processChild ( element , Component ) {
475- let publicContext = processContext ( Component , context ) ;
424+ let publicContext = processContext ( Component , context , threadID ) ;
476425
477426 let queue = [ ] ;
478427 let replace = false ;
@@ -718,6 +667,7 @@ type FrameDev = Frame & {
718667} ;
719668
720669class ReactDOMServerRenderer {
670+ threadID : ThreadID ;
721671 stack : Array < Frame > ;
722672 exhausted : boolean ;
723673 // TODO: type this more strictly:
@@ -747,6 +697,7 @@ class ReactDOMServerRenderer {
747697 if ( __DEV__ ) {
748698 ( ( topFrame : any ) : FrameDev ) . debugElementStack = [ ] ;
749699 }
700+ this . threadID = allocThreadID ( ) ;
750701 this . stack = [ topFrame ] ;
751702 this . exhausted = false ;
752703 this . currentSelectValue = null ;
@@ -763,6 +714,13 @@ class ReactDOMServerRenderer {
763714 }
764715 }
765716
717+ destroy ( ) {
718+ if ( ! this . exhausted ) {
719+ this . exhausted = true ;
720+ freeThreadID ( this . threadID ) ;
721+ }
722+ }
723+
766724 /**
767725 * Note: We use just two stacks regardless of how many context providers you have.
768726 * Providers are always popped in the reverse order to how they were pushed
@@ -776,7 +734,9 @@ class ReactDOMServerRenderer {
776734 pushProvider < T > ( provider : ReactProvider < T > ) : void {
777735 const index = ++ this . contextIndex ;
778736 const context : ReactContext < any > = provider . type . _context ;
779- const previousValue = context . _currentValue ;
737+ const threadID = this . threadID ;
738+ validateContextBounds ( context , threadID ) ;
739+ const previousValue = context [ threadID ] ;
780740
781741 // Remember which value to restore this context to on our way up.
782742 this . contextStack [ index ] = context ;
@@ -787,7 +747,7 @@ class ReactDOMServerRenderer {
787747 }
788748
789749 // Mutate the current value.
790- context . _currentValue = provider . props . value ;
750+ context [ threadID ] = provider . props . value ;
791751 }
792752
793753 popProvider < T > ( provider : ReactProvider < T > ) : void {
@@ -813,14 +773,18 @@ class ReactDOMServerRenderer {
813773 this . contextIndex -- ;
814774
815775 // Restore to the previous value we stored as we were walking down.
816- context . _currentValue = previousValue ;
776+ // We've already verified that this context has been expanded to accommodate
777+ // this thread id, so we don't need to do it again.
778+ context [ this . threadID ] = previousValue ;
817779 }
818780
819781 read ( bytes : number ) : string | null {
820782 if ( this . exhausted ) {
821783 return null ;
822784 }
823785
786+ const prevThreadID = currentThreadID ;
787+ setCurrentThreadID ( this . threadID ) ;
824788 const prevDispatcher = ReactCurrentOwner . currentDispatcher ;
825789 if ( enableHooks ) {
826790 ReactCurrentOwner . currentDispatcher = Dispatcher ;
@@ -835,6 +799,7 @@ class ReactDOMServerRenderer {
835799 while ( out [ 0 ] . length < bytes ) {
836800 if ( this . stack . length === 0 ) {
837801 this . exhausted = true ;
802+ freeThreadID ( this . threadID ) ;
838803 break ;
839804 }
840805 const frame : Frame = this . stack [ this . stack . length - 1 ] ;
@@ -906,6 +871,7 @@ class ReactDOMServerRenderer {
906871 return out [ 0 ] ;
907872 } finally {
908873 ReactCurrentOwner . currentDispatcher = prevDispatcher ;
874+ setCurrentThreadID ( prevThreadID ) ;
909875 }
910876 }
911877
@@ -929,7 +895,7 @@ class ReactDOMServerRenderer {
929895 return escapeTextForBrowser ( text ) ;
930896 } else {
931897 let nextChild ;
932- ( { child : nextChild , context} = resolve ( child , context ) ) ;
898+ ( { child : nextChild , context} = resolve ( child , context , this . threadID ) ) ;
933899 if ( nextChild === null || nextChild === false ) {
934900 return '';
935901 } else if ( ! React . isValidElement ( nextChild ) ) {
@@ -1136,7 +1102,9 @@ class ReactDOMServerRenderer {
11361102 }
11371103 }
11381104 const nextProps : any = ( nextChild : any ) . props ;
1139- const nextValue = reactContext . _currentValue ;
1105+ const threadID = this . threadID ;
1106+ validateContextBounds ( reactContext , threadID ) ;
1107+ const nextValue = reactContext [ threadID ] ;
11401108
11411109 const nextChildren = toArray ( nextProps . children ( nextValue ) ) ;
11421110 const frame : Frame = {
0 commit comments