@@ -496,13 +496,14 @@ function createErrorChunk<T>(
496496function wakeChunk< T > (
497497 listeners: Array< InitializationReference | ( T = > mixed)> ,
498498 value : T ,
499+ chunk : SomeChunk < T > ,
499500): void {
500501 for ( let i = 0 ; i < listeners . length ; i ++ ) {
501502 const listener = listeners [ i ] ;
502503 if ( typeof listener === 'function' ) {
503504 listener ( value ) ;
504505 } else {
505- fulfillReference ( listener , value ) ;
506+ fulfillReference ( listener , value , chunk ) ;
506507 }
507508 }
508509}
@@ -555,7 +556,7 @@ function wakeChunkIfInitialized<T>(
555556) : void {
556557 switch ( chunk . status ) {
557558 case INITIALIZED :
558- wakeChunk ( resolveListeners , chunk . value ) ;
559+ wakeChunk ( resolveListeners , chunk . value , chunk ) ;
559560 break ;
560561 case BLOCKED :
561562 // It is possible that we're blocked on our own chunk if it's a cycle.
@@ -569,7 +570,7 @@ function wakeChunkIfInitialized<T>(
569570 if ( cyclicHandler !== null ) {
570571 // This reference points back to this chunk. We can resolve the cycle by
571572 // using the value from that handler.
572- fulfillReference ( reference , cyclicHandler . value ) ;
573+ fulfillReference ( reference , cyclicHandler . value , chunk ) ;
573574 resolveListeners . splice ( i , 1 ) ;
574575 i -- ;
575576 if ( rejectListeners !== null ) {
@@ -637,7 +638,7 @@ function triggerErrorOnChunk<T>(
637638 cyclicChunk . status = BLOCKED ;
638639 cyclicChunk . value = null ;
639640 cyclicChunk . reason = null ;
640- if ( enableProfilerTimer && enableComponentPerformanceTrack ) {
641+ if ( ( enableProfilerTimer && enableComponentPerformanceTrack ) || __DEV__ ) {
641642 initializingChunk = cyclicChunk ;
642643 }
643644 try {
@@ -919,7 +920,7 @@ function initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {
919920 cyclicChunk . value = null ;
920921 cyclicChunk . reason = null ;
921922
922- if ( enableProfilerTimer && enableComponentPerformanceTrack ) {
923+ if ( ( enableProfilerTimer && enableComponentPerformanceTrack ) || __DEV__ ) {
923924 initializingChunk = cyclicChunk ;
924925 }
925926
@@ -938,7 +939,7 @@ function initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {
938939 if ( resolveListeners !== null ) {
939940 cyclicChunk . value = null ;
940941 cyclicChunk . reason = null ;
941- wakeChunk ( resolveListeners , value ) ;
942+ wakeChunk ( resolveListeners , value , cyclicChunk ) ;
942943 }
943944 if (initializingHandler !== null) {
944945 if ( initializingHandler . errored ) {
@@ -961,7 +962,7 @@ function initializeModelChunk<T>(chunk: ResolvedModelChunk<T>): void {
961962 erroredChunk . reason = error ;
962963 } finally {
963964 initializingHandler = prevHandler ;
964- if ( enableProfilerTimer && enableComponentPerformanceTrack ) {
965+ if ( ( enableProfilerTimer && enableComponentPerformanceTrack ) || __DEV__ ) {
965966 initializingChunk = prevChunk ;
966967 }
967968 }
@@ -1298,6 +1299,7 @@ function getChunk(response: Response, id: number): SomeChunk<any> {
12981299function fulfillReference(
12991300 reference: InitializationReference,
13001301 value: any,
1302+ fulfilledChunk: SomeChunk< any > ,
13011303): void {
13021304 const { response , handler , parentObject , key , map , path } = reference;
13031305
@@ -1376,6 +1378,8 @@ function fulfillReference(
13761378 const mappedValue = map ( response , value , parentObject , key ) ;
13771379 parentObject [ key ] = mappedValue ;
13781380
1381+ transferReferencedDebugInfo ( handler . chunk , fulfilledChunk , mappedValue ) ;
1382+
13791383 // If this is the root object for a model reference, where `handler.value`
13801384 // is a stale `null`, the resolved value can be used directly.
13811385 if ( key === '' && handler . value === null ) {
@@ -1422,7 +1426,7 @@ function fulfillReference(
14221426 initializedChunk . value = handler . value ;
14231427 initializedChunk . reason = handler . reason ; // Used by streaming chunks
14241428 if ( resolveListeners !== null ) {
1425- wakeChunk ( resolveListeners , handler . value ) ;
1429+ wakeChunk ( resolveListeners , handler . value , initializedChunk ) ;
14261430 }
14271431 }
14281432}
@@ -1669,7 +1673,7 @@ function loadServerReference<A: Iterable<any>, T>(
16691673 initializedChunk . status = INITIALIZED ;
16701674 initializedChunk . value = handler . value ;
16711675 if ( resolveListeners !== null ) {
1672- wakeChunk ( resolveListeners , handler . value ) ;
1676+ wakeChunk ( resolveListeners , handler . value , initializedChunk ) ;
16731677 }
16741678 }
16751679 }
@@ -1728,6 +1732,49 @@ function loadServerReference<A: Iterable<any>, T>(
17281732 return ( null : any ) ;
17291733}
17301734
1735+ function transferReferencedDebugInfo (
1736+ parentChunk : null | SomeChunk < any > ,
1737+ referencedChunk: SomeChunk< any > ,
1738+ referencedValue: mixed,
1739+ ): void {
1740+ if ( __DEV__ && referencedChunk . _debugInfo ) {
1741+ const referencedDebugInfo = referencedChunk . _debugInfo ;
1742+ // If we have a direct reference to an object that was rendered by a synchronous
1743+ // server component, it might have some debug info about how it was rendered.
1744+ // We forward this to the underlying object. This might be a React Element or
1745+ // an Array fragment.
1746+ // If this was a string / number return value we lose the debug info. We choose
1747+ // that tradeoff to allow sync server components to return plain values and not
1748+ // use them as React Nodes necessarily. We could otherwise wrap them in a Lazy.
1749+ if (
1750+ typeof referencedValue === 'object' &&
1751+ referencedValue !== null &&
1752+ ( isArray ( referencedValue ) ||
1753+ typeof referencedValue [ ASYNC_ITERATOR ] === 'function' ||
1754+ referencedValue . $$typeof === REACT_ELEMENT_TYPE ) &&
1755+ ! referencedValue . _debugInfo
1756+ ) {
1757+ // We should maybe use a unique symbol for arrays but this is a React owned array.
1758+ // $FlowFixMe[prop-missing]: This should be added to elements.
1759+ Object . defineProperty ( ( referencedValue : any ) , '_debugInfo' , {
1760+ configurable : false ,
1761+ enumerable : false ,
1762+ writable : true ,
1763+ value : referencedDebugInfo ,
1764+ } ) ;
1765+ }
1766+ // We also add it to the initializing chunk since the resolution of that promise is
1767+ // also blocked by these. By adding it to both we can track it even if the array/element
1768+ // is extracted, or if the root is rendered as is.
1769+ if (parentChunk !== null) {
1770+ const parentDebugInfo =
1771+ parentChunk . _debugInfo || ( parentChunk . _debugInfo = [ ] ) ;
1772+ // $FlowFixMe[method-unbinding]
1773+ parentDebugInfo . push . apply ( parentDebugInfo , referencedDebugInfo ) ;
1774+ }
1775+ }
1776+ }
1777+
17311778function getOutlinedModel < T > (
17321779 response: Response,
17331780 reference: string,
@@ -1825,32 +1872,7 @@ function getOutlinedModel<T>(
18251872 value = value [ path [ i ] ] ;
18261873 }
18271874 const chunkValue = map ( response , value , parentObject , key ) ;
1828- if ( __DEV__ && chunk . _debugInfo ) {
1829- // If we have a direct reference to an object that was rendered by a synchronous
1830- // server component, it might have some debug info about how it was rendered.
1831- // We forward this to the underlying object. This might be a React Element or
1832- // an Array fragment.
1833- // If this was a string / number return value we lose the debug info. We choose
1834- // that tradeoff to allow sync server components to return plain values and not
1835- // use them as React Nodes necessarily. We could otherwise wrap them in a Lazy.
1836- if (
1837- typeof chunkValue === 'object' &&
1838- chunkValue !== null &&
1839- ( isArray ( chunkValue ) ||
1840- typeof chunkValue [ ASYNC_ITERATOR ] === 'function' ||
1841- chunkValue . $$typeof === REACT_ELEMENT_TYPE ) &&
1842- ! chunkValue . _debugInfo
1843- ) {
1844- // We should maybe use a unique symbol for arrays but this is a React owned array.
1845- // $FlowFixMe[prop-missing]: This should be added to elements.
1846- Object . defineProperty ( ( chunkValue : any ) , '_debugInfo' , {
1847- configurable : false ,
1848- enumerable : false ,
1849- writable : true ,
1850- value : chunk . _debugInfo ,
1851- } ) ;
1852- }
1853- }
1875+ transferReferencedDebugInfo ( initializingChunk , chunk , chunkValue ) ;
18541876 return chunkValue ;
18551877 case PENDING :
18561878 case BLOCKED :
@@ -2621,7 +2643,7 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
26212643 cyclicChunk . status = BLOCKED ;
26222644 cyclicChunk . value = null ;
26232645 cyclicChunk . reason = null ;
2624- if ( enableProfilerTimer && enableComponentPerformanceTrack ) {
2646+ if ( ( enableProfilerTimer && enableComponentPerformanceTrack ) || __DEV__ ) {
26252647 initializingChunk = cyclicChunk ;
26262648 }
26272649 try {
@@ -2650,7 +2672,7 @@ function resolveStream<T: ReadableStream | $AsyncIterable<any, any, void>>(
26502672 resolvedChunk . value = stream ;
26512673 resolvedChunk . reason = controller ;
26522674 if ( resolveListeners !== null ) {
2653- wakeChunk ( resolveListeners , chunk . value ) ;
2675+ wakeChunk ( resolveListeners , chunk . value , chunk ) ;
26542676 }
26552677}
26562678
0 commit comments