@@ -1967,6 +1967,7 @@ function replayElement(
19671967 }
19681968 const childNodes = node [ 2 ] ;
19691969 const childSlots = node [ 3 ] ;
1970+ const currentNode = task . node ;
19701971 task . replay = { nodes : childNodes , slots : childSlots , pendingTasks : 1 } ;
19711972 try {
19721973 renderElement (
@@ -1988,25 +1989,29 @@ function replayElement(
19881989 "The tree doesn't match so React will fallback to client rendering." ,
19891990 ) ;
19901991 }
1992+ task . replay . pendingTasks -- ;
19911993 } catch ( x ) {
19921994 if (
19931995 typeof x === 'object' &&
19941996 x !== null &&
19951997 ( x === SuspenseException || typeof x . then === 'function' )
19961998 ) {
19971999 // Suspend
2000+ if ( task . node === currentNode ) {
2001+ // This same element suspended so we need to pop the replay we just added.
2002+ task . replay = replay ;
2003+ }
19982004 throw x ;
19992005 }
2006+ task . replay . pendingTasks -- ;
20002007 // Unlike regular render, we don't terminate the siblings if we error
20012008 // during a replay. That's because this component didn't actually error
20022009 // in the original prerender. What's unable to complete is the child
20032010 // replay nodes which might be Suspense boundaries which are able to
20042011 // absorb the error and we can still continue with siblings.
20052012 erroredReplay ( request , task . blockedBoundary , x , childNodes , childSlots ) ;
2006- } finally {
2007- task . replay . pendingTasks -- ;
2008- task . replay = replay ;
20092013 }
2014+ task . replay = replay ;
20102015 } else {
20112016 // Let's double check that the component type matches.
20122017 if ( type !== REACT_SUSPENSE_TYPE ) {
@@ -2370,6 +2375,7 @@ function replayFragment(
23702375 "The tree doesn't match so React will fallback to client rendering." ,
23712376 ) ;
23722377 }
2378+ task . replay . pendingTasks -- ;
23732379 } catch ( x ) {
23742380 if (
23752381 typeof x === 'object' &&
@@ -2379,17 +2385,16 @@ function replayFragment(
23792385 // Suspend
23802386 throw x ;
23812387 }
2388+ task . replay . pendingTasks -- ;
23822389 // Unlike regular render, we don't terminate the siblings if we error
23832390 // during a replay. That's because this component didn't actually error
23842391 // in the original prerender. What's unable to complete is the child
23852392 // replay nodes which might be Suspense boundaries which are able to
23862393 // absorb the error and we can still continue with siblings.
23872394 // This is an error, stash the component stack if it is null.
23882395 erroredReplay ( request , task . blockedBoundary , x , childNodes , childSlots ) ;
2389- } finally {
2390- task . replay . pendingTasks -- ;
2391- task . replay = replay ;
23922396 }
2397+ task . replay = replay ;
23932398 // We finished rendering this node, so now we can consume this
23942399 // slot. This must happen after in case we rerender this task.
23952400 replayNodes . splice ( j , 1 ) ;
@@ -2432,6 +2437,7 @@ function renderChildrenArray(
24322437 // We need to use the non-destructive form so that we can safely pop back
24332438 // up and render the sibling if something suspends.
24342439 const resumeSegmentID = resumeSlots [ i ] ;
2440+ // TODO: If this errors we should still continue with the next sibling.
24352441 if ( typeof resumeSegmentID === 'number' ) {
24362442 resumeNode ( request , task , resumeSegmentID , node , i ) ;
24372443 // We finished rendering this node, so now we can consume this
0 commit comments