@@ -176,6 +176,7 @@ type ReplaySuspenseBoundary = [
176176 string | number /* key */ ,
177177 Array < ResumableNode > /* children */ ,
178178 SuspenseBoundaryID /* id */ ,
179+ number /* rootSegmentID */ ,
179180] ;
180181
181182type ReplayNode =
@@ -1957,6 +1958,7 @@ function trackPostpone(
19571958 request . renderState ,
19581959 request . resumableState ,
19591960 ) ;
1961+ boundary . rootSegmentID = request . nextSegmentId ++ ;
19601962
19611963 const boundaryKeyPath = boundary . keyPath ;
19621964 if ( boundaryKeyPath === null ) {
@@ -1971,6 +1973,7 @@ function trackPostpone(
19711973 boundaryKeyPath [ 2 ] ,
19721974 children ,
19731975 boundary . id ,
1976+ boundary . rootSegmentID ,
19741977 ] ;
19751978 trackedPostpones . workingMap . set ( boundaryKeyPath , boundaryNode ) ;
19761979 addToReplayParent ( boundaryNode , boundaryKeyPath [ 0 ] , trackedPostpones ) ;
@@ -2021,7 +2024,7 @@ function injectPostponedHole(
20212024 segment . children . push ( newSegment ) ;
20222025 // Reset lastPushedText for current Segment since the new Segment "consumed" it
20232026 segment . lastPushedText = false ;
2024- return segment ;
2027+ return newSegment ;
20252028}
20262029
20272030function spawnNewSuspendedTask (
@@ -2316,7 +2319,9 @@ function queueCompletedSegment(
23162319 if (
23172320 segment . chunks . length === 0 &&
23182321 segment . children . length === 1 &&
2319- segment . children [ 0 ] . boundary === null
2322+ segment . children [ 0 ] . boundary === null &&
2323+ // Typically the id would not be assigned yet but if it's a postponed segment it might be.
2324+ segment . children [ 0 ] . id === - 1
23202325 ) {
23212326 // This is an empty segment. There's nothing to write, so we can instead transfer the ID
23222327 // to the child. That way any existing references point to the child.
@@ -2668,20 +2673,22 @@ function flushSegment(
26682673 ) ;
26692674 } else if ( boundary . status !== COMPLETED ) {
26702675 if ( boundary . status === PENDING ) {
2676+ // For pending boundaries we lazily assign an ID to the boundary
2677+ // and root segment.
26712678 boundary . id = assignSuspenseBoundaryID (
26722679 request . renderState ,
26732680 request . resumableState ,
26742681 ) ;
2682+ boundary . rootSegmentID = request . nextSegmentId ++ ;
26752683 }
2676- // This boundary is still loading. Emit a pending suspense boundary wrapper.
26772684
2678- // Assign an ID to refer to the future content by.
2679- boundary . rootSegmentID = request . nextSegmentId ++ ;
26802685 if ( boundary . completedSegments . length > 0 ) {
26812686 // If this is at least partially complete, we can queue it to be partially emitted early.
26822687 request . partialBoundaries . push ( boundary ) ;
26832688 }
26842689
2690+ // This boundary is still loading. Emit a pending suspense boundary wrapper.
2691+
26852692 /// This is the first time we should have referenced this ID.
26862693 const id = boundary . id ;
26872694
@@ -2868,6 +2875,10 @@ function flushPartiallyCompletedSegment(
28682875 ) ;
28692876 }
28702877
2878+ return flushSegmentContainer ( request , destination , segment ) ;
2879+ } else if ( segmentID === boundary . rootSegmentID ) {
2880+ // When we emit postponed boundaries, we might have assigned the ID already
2881+ // but it's still the root segment so we can't inject it into the parent yet.
28712882 return flushSegmentContainer ( request , destination , segment ) ;
28722883 } else {
28732884 flushSegmentContainer ( request , destination , segment ) ;
0 commit comments