@@ -512,6 +512,25 @@ function wakeChunk<T>(
512512      fulfillReference ( listener ,  value ,  chunk ) ; 
513513    } 
514514  } 
515+ 
516+   if  ( __DEV__  &&  chunk . status  ===  INITIALIZED  &&  chunk . _debugInfo  !==  null )  { 
517+     value =  resolveLazy ( value ) ; 
518+     if  ( isReactElementOrArrayLike ( value )  ||  isLazy ( value ) )  { 
519+       const  debugInfo =  chunk . _debugInfo . splice ( 0 ) ; 
520+       chunk . _debugInfo  =  null ; 
521+       if  ( value . _debugInfo )  { 
522+         // $FlowFixMe[method-unbinding] 
523+         value. _debugInfo . push . apply ( value . _debugInfo ,  debugInfo ) ; 
524+       }  else  { 
525+         Object. defineProperty ( value ,  '_debugInfo' ,  { 
526+           configurable : false , 
527+           enumerable : false , 
528+           writable : true , 
529+           value : debugInfo , 
530+         } ) ; 
531+       } 
532+     } 
533+   } 
515534} 
516535
517536function rejectChunk(
@@ -1052,11 +1071,7 @@ function getTaskName(type: mixed): string {
10521071    // the client. There should only be one for any given owner chain. 
10531072    return  '"use client"' ; 
10541073  } 
1055-   if (
1056-     typeof type === 'object' && 
1057-     type  !==  null  && 
1058-     type . $$typeof  ===  REACT_LAZY_TYPE 
1059-   )  { 
1074+   if (isLazy(type)) { 
10601075    if  ( type . _init  ===  readChunk ) { 
10611076      // This is a lazy node created by Flight. It is probably a client reference. 
10621077      // We use the "use client" string to indicate that this is the boundary into 
@@ -1168,7 +1183,6 @@ function initializeElement(
11681183
11691184function  createElement ( 
11701185  response : Response , 
1171-   isRoot : boolean , 
11721186  type : mixed , 
11731187  key : mixed , 
11741188  props : mixed , 
@@ -1277,19 +1291,10 @@ function createElement(
12771291      // a Lazy node referencing this Element to let everything around it proceed. 
12781292      const  blockedChunk : BlockedChunk < React$Element < any >>  = 
12791293        createBlockedChunk ( response ) ; 
1280-       if  ( __DEV__ )  { 
1281-         // If this is the root element, forward the live debug info of the 
1282-         // initializing chunk to the blocked chunk. 
1283-         if  ( isRoot  &&  initializingChunk  !==  null )  { 
1284-           blockedChunk . _debugInfo  =  initializingChunk . _debugInfo ; 
1285-         } 
1286-       } 
12871294      handler . value  =  element ; 
12881295      handler . chunk  =  blockedChunk ; 
12891296      const  lazyNode  =  createLazyChunkWrapper ( blockedChunk ,  validated ) ; 
12901297      if  ( __DEV__ )  { 
1291-         // Forward the live debug info of the lazy node to the element. 
1292-         element. _debugInfo  =  lazyNode . _debugInfo ; 
12931298        // After we have initialized any blocked references, initialize stack etc. 
12941299        const init  =  initializeElement . bind ( null ,  response ,  element ,  lazyNode ) ; 
12951300        blockedChunk . then ( init ,  init ) ; 
@@ -1346,11 +1351,7 @@ function fulfillReference(
13461351  const { response ,  handler ,  parentObject ,  key ,  map ,  path }  = reference;
13471352
13481353  for (let i = 1; i <  path . length ;  i ++ )  { 
1349-     while  ( 
1350-       typeof  value  ===  'object'  && 
1351-       value  !==  null  && 
1352-       value . $$typeof  ===  REACT_LAZY_TYPE 
1353-     ) { 
1354+     while  ( isLazy ( value ) ) { 
13541355      // We never expect to see a Lazy node on this path because we encode those as 
13551356      // separate models. This must mean that we have inserted an extra lazy node 
13561357      // e.g. to replace a blocked element. We must instead look for it inside. 
@@ -1422,11 +1423,7 @@ function fulfillReference(
14221423    value  =  value [ path [ i ] ] ; 
14231424  } 
14241425
1425-   while  ( 
1426-     typeof  value  ===  'object ' && 
1427-     value  !==  null  && 
1428-     value . $$typeof  ===  REACT_LAZY_TYPE 
1429-   )  { 
1426+   while  ( isLazy ( value ) )  { 
14301427    // If what we're referencing is a Lazy it must be because we inserted one as a virtual node 
14311428    // while it was blocked by other data. If it's no longer blocked, we can unwrap it. 
14321429    const  referencedChunk : SomeChunk < any >  =  value . _payload ; 
@@ -1475,7 +1472,7 @@ function fulfillReference(
14751472    const  element : any  =  handler . value ; 
14761473    switch  ( key ) { 
14771474      case  '3' :
1478-         transferReferencedDebugInfo ( handler . chunk ,  fulfilledChunk ,   mappedValue ) ; 
1475+         transferReferencedDebugInfo ( handler . chunk ,  fulfilledChunk ) ; 
14791476        element . props  =  mappedValue ; 
14801477        break ; 
14811478      case  '4' :
@@ -1491,11 +1488,11 @@ function fulfillReference(
14911488        } 
14921489        break;
14931490      default:
1494-         transferReferencedDebugInfo(handler.chunk, fulfilledChunk, mappedValue );
1491+         transferReferencedDebugInfo(handler.chunk, fulfilledChunk);
14951492        break;
14961493    } 
14971494  }  else  if  ( __DEV__  &&  ! reference . isDebug )  { 
1498-     transferReferencedDebugInfo ( handler . chunk ,  fulfilledChunk ,   mappedValue ) ; 
1495+     transferReferencedDebugInfo ( handler . chunk ,  fulfilledChunk ) ; 
14991496  } 
15001497
15011498  handler.deps--;
@@ -1817,49 +1814,63 @@ function loadServerReference<A: Iterable<any>, T>(
18171814  return  ( null : any ) ; 
18181815} 
18191816
1817+ function  isReactElementOrArrayLike ( 
1818+   value : any , 
1819+   // eslint-disable-next-line no-undef 
1820+ ) : value  is  { _debugInfo : null  |  ReactDebugInfo ,  ...}  { 
1821+   return  ( 
1822+     typeof  value  ===  'object'  && 
1823+     value  !==  null  && 
1824+     ( isArray ( value )  || 
1825+       typeof  value [ ASYNC_ITERATOR ]  ===  'function'  || 
1826+       value . $$typeof  ===  REACT_ELEMENT_TYPE ) 
1827+   ) ; 
1828+ } 
1829+ 
1830+ function isLazy(
1831+   value: any,
1832+   // eslint-disable-next-line no-undef
1833+ ): value is { _debugInfo : null  |  ReactDebugInfo ,  ...}  { 
1834+   return  ( 
1835+     typeof  value  ===  'object'  && 
1836+     value  !==  null  && 
1837+     value . $$typeof  ===  REACT_LAZY_TYPE 
1838+   ) ; 
1839+ } 
1840+ 
1841+ function resolveLazy(value: mixed): mixed { 
1842+   while  ( isLazy ( value ) ) { 
1843+     const  payload : SomeChunk < any >  =  value . _payload ; 
1844+     if  ( payload . status  ===  INITIALIZED )  { 
1845+       value =  payload . value ; 
1846+       continue ; 
1847+     } 
1848+     break ; 
1849+   } 
1850+ 
1851+   return value;
1852+ } 
1853+ 
18201854function  transferReferencedDebugInfo ( 
18211855  parentChunk : null  |  SomeChunk < any > ,
18221856  referencedChunk: SomeChunk< any > ,
1823-   referencedValue: mixed,
18241857): void { 
18251858  if  ( __DEV__ ) { 
1826-     const  referencedDebugInfo  =  referencedChunk . _debugInfo ; 
1827-     // If we have a direct reference to an object that was rendered by a synchronous 
1828-     // server component, it might have some debug info about how it was rendered. 
1829-     // We forward this to the underlying object. This might be a React Element or 
1830-     // an Array fragment. 
1831-     // If this was a string / number return value we lose the debug info. We choose 
1832-     // that tradeoff to allow sync server components to return plain values and not 
1833-     // use them as React Nodes necessarily. We could otherwise wrap them in a Lazy. 
1834-     if  ( 
1835-       typeof  referencedValue  ===  'object'  && 
1836-       referencedValue  !==  null  && 
1837-       ( isArray ( referencedValue )  || 
1838-         typeof  referencedValue [ ASYNC_ITERATOR ]  ===  'function'  || 
1839-         referencedValue . $$typeof  ===  REACT_ELEMENT_TYPE ) 
1840-     ) { 
1841-       // We should maybe use a unique symbol for arrays but this is a React owned array. 
1842-       // $FlowFixMe[prop-missing]: This should be added to elements. 
1843-       const  existingDebugInfo : ?ReactDebugInfo  = 
1844-         ( referencedValue . _debugInfo : any ) ; 
1845-       if  ( existingDebugInfo  ==  null )  { 
1846-         Object . defineProperty ( ( referencedValue : any ) ,  '_debugInfo' ,  { 
1847-           configurable : false , 
1848-           enumerable : false , 
1849-           writable : true , 
1850-           value : referencedDebugInfo . slice ( 0 ) ,  // Clone so that pushing later isn't going into the original 
1851-         } ) ; 
1852-       }  else { 
1853-         // $FlowFixMe[method-unbinding] 
1854-         existingDebugInfo . push . apply ( existingDebugInfo ,  referencedDebugInfo ) ; 
1855-       } 
1856-     } 
1857-     // We also add the debug info to the initializing chunk since the resolution of that promise is 
1858-     // also blocked by the referenced debug info. By adding it to both we can track it even if the array/element 
1859-     // is extracted, or if the root is rendered as is. 
1859+     // We add the debug info to the initializing chunk since the resolution of 
1860+     // that promise is also blocked by the referenced debug info. By adding it 
1861+     // to both we can track it even if the array/element/lazy is extracted, or 
1862+     // if the root is rendered as is. 
18601863    if  ( parentChunk  !==  null ) { 
1861-       const  parentDebugInfo  =  parentChunk . _debugInfo ; 
1862-       if  ( parentDebugInfo  !==  referencedDebugInfo )  { 
1864+       let  referencedDebugInfo  =  referencedChunk . _debugInfo ; 
1865+       if  ( referencedDebugInfo  ===  null )  { 
1866+         const value  =  resolveLazy ( referencedChunk . value ) ; 
1867+         if  ( isReactElementOrArrayLike ( value ) )  { 
1868+           // The debug info was already transferred from the chunk to the value. 
1869+           referencedDebugInfo =  value . _debugInfo ; 
1870+         } 
1871+       } 
1872+       if  ( referencedDebugInfo  !==  null )  { 
1873+         const  parentDebugInfo =  parentChunk . _debugInfo ; 
18631874        for  ( let  i  =  0 ;  i  <  referencedDebugInfo . length ;  ++ i )  { 
18641875          const  debugInfoEntry =  referencedDebugInfo [ i ] ; 
18651876          if  ( debugInfoEntry . name  !=  null )  { 
@@ -1903,11 +1914,7 @@ function getOutlinedModel<T>(
19031914    case  INITIALIZED :
19041915      let  value  =  chunk . value ; 
19051916      for  ( let  i  =  1 ;  i  <  path . length ;  i ++ )  { 
1906-         while  ( 
1907-           typeof  value  ===  'object'  && 
1908-           value  !==  null  && 
1909-           value . $$typeof  ===  REACT_LAZY_TYPE 
1910-         )  { 
1917+         while  ( isLazy ( value ) )  { 
19111918          const  referencedChunk : SomeChunk < any >  = value._payload;
19121919          switch (referencedChunk.status) { 
19131920            case  RESOLVED_MODEL :
@@ -1977,11 +1984,7 @@ function getOutlinedModel<T>(
19771984        value  =  value [ path [ i ] ] ; 
19781985      } 
19791986
1980-       while  ( 
1981-         typeof  value  ===  'object ' && 
1982-         value  !==  null  && 
1983-         value . $$typeof  ===  REACT_LAZY_TYPE 
1984-       )  { 
1987+       while  ( isLazy ( value ) )  { 
19851988        // If what we're referencing is a Lazy it must be because we inserted one as a virtual node 
19861989        // while it was blocked by other data. If it's no longer blocked, we can unwrap it. 
19871990        const  referencedChunk : SomeChunk < any >  =  value . _payload ; 
@@ -2010,7 +2013,7 @@ function getOutlinedModel<T>(
20102013        // If we're resolving the "owner" or "stack" slot of an Element array, we don't call 
20112014        // transferReferencedDebugInfo because this reference is to a debug chunk. 
20122015      }  else { 
2013-         transferReferencedDebugInfo ( initializingChunk ,  chunk ,   chunkValue ) ; 
2016+         transferReferencedDebugInfo ( initializingChunk ,  chunk ) ; 
20142017      } 
20152018      return chunkValue;
20162019    case PENDING:
@@ -2468,7 +2471,6 @@ function parseModelString(
24682471function  parseModelTuple ( 
24692472  response : Response , 
24702473  value : { + [ key : string ] : JSONValue }  |  $ReadOnlyArray < JSONValue > , 
2471-   isRoot : boolean , 
24722474) : any  { 
24732475  const  tuple : [ mixed ,  mixed ,  mixed ,  mixed ]  =  ( value : any ) ; 
24742476
@@ -2477,7 +2479,6 @@ function parseModelTuple(
24772479    // Or even change the ReactElement type to be an array. 
24782480    return  createElement ( 
24792481      response , 
2480-       isRoot , 
24812482      tuple [ 1 ] , 
24822483      tuple [ 2 ] , 
24832484      tuple [ 3 ] , 
@@ -2727,18 +2728,34 @@ function resolveChunkDebugInfo(
27272728  chunk : SomeChunk < any > , 
27282729) : void  { 
27292730  if  ( __DEV__  &&  enableAsyncDebugInfo )  { 
2730-     // Push the currently resolving chunk's debug info representing the stream 
2731-     // on the Promise that was waiting on the stream. 
2732-     const  ioInfo  =  streamState . _debugInfo ; 
2733-     const  debugChunk  =  chunk . _debugChunk ; 
2734-     if  ( debugChunk  !=  null )  { 
2735-       // If there's a debug chunk, then we wait for it to resolve before adding 
2736-       // the stream info as the last entry. 
2737-       debugChunk . then ( ( )  =>  { 
2738-         chunk . _debugInfo . push ( { awaited : ioInfo } ) ; 
2739-       } ) ; 
2731+     // Add the currently resolving chunk's debug info representing the stream 
2732+     // to the Promise that was waiting on the stream, or its underlying value. 
2733+     const  debugInfoEntry : ReactAsyncInfo  =  { awaited : streamState . _debugInfo } ; 
2734+ 
2735+     const  addDebugInfo  =  ( )  = >  { 
2736+       const  value =  resolveLazy ( chunk . value ) ; 
2737+       if  ( isReactElementOrArrayLike ( value ) )  { 
2738+         const  debugInfo : ReactDebugInfo  =  [ debugInfoEntry ] ; 
2739+         if  ( value . _debugInfo )  { 
2740+           // $FlowFixMe[method-unbinding] 
2741+           value . _debugInfo . push . apply ( value . _debugInfo ,  debugInfo ) ; 
2742+         }  else  { 
2743+           Object . defineProperty ( value ,  '_debugInfo' ,  { 
2744+             configurable : false , 
2745+             enumerable : false , 
2746+             writable : true , 
2747+             value : debugInfo , 
2748+           } ) ; 
2749+         } 
2750+       }  else  if  ( chunk . _debugInfo  !==  null )  { 
2751+         chunk . _debugInfo . push ( debugInfoEntry ) ; 
2752+       } 
2753+     } ;
2754+ 
2755+     if (chunk.status === PENDING || chunk.status === BLOCKED) { 
2756+       chunk . then ( addDebugInfo ,  addDebugInfo ) ; 
27402757    }  else { 
2741-       chunk . _debugInfo . push ( { awaited :  ioInfo } ) ; 
2758+       addDebugInfo ( ) ; 
27422759    } 
27432760  } 
27442761} 
@@ -4749,6 +4766,7 @@ export function processBinaryChunk(
47494766  streamState : StreamState , 
47504767  chunk : Uint8Array , 
47514768) : void  { 
4769+   // console.log(new TextDecoder().decode(chunk)); 
47524770  if  ( hasGCedResponse ( weakResponse ) )  { 
47534771    // Ignore more chunks if we've already GC:ed all listeners. 
47544772    return ; 
@@ -5044,8 +5062,7 @@ function createFromJSONCallback(response: Response) {
50445062      return  parseModelString ( response ,  this ,  key ,  value ) ; 
50455063    } 
50465064    if  ( typeof  value  ===  'object'  &&  value  !==  null )  { 
5047-       const  isRoot  =  key  ===  '' ; 
5048-       return  parseModelTuple ( response ,  value ,  isRoot ) ; 
5065+       return  parseModelTuple ( response ,  value ) ; 
50495066    } 
50505067    return  value ; 
50515068  } ; 
0 commit comments