@@ -83,33 +83,25 @@ export function diff(
8383 ( isHydrating = oldVNode . _flags & MODE_HYDRATE ) &&
8484 oldVNode . _component . _excess
8585 ) {
86- let startMarker = oldVNode . _component . _excess [ 0 ] ;
87- if (
88- startMarker &&
89- startMarker . nodeType == 8 &&
90- startMarker . data . startsWith ( '$s' )
91- ) {
92- // Deferred restoration: re-scan current DOM from the stored start marker.
93- // This ensures we always hydrate against the most up-to-date DOM state,
94- // even if a streaming SSR patcher replaced the content between markers.
95- excessDomChildren = [ ] ;
96- let depth = 1 ;
97- let node = startMarker . nextSibling ;
98- while ( node && depth > 0 ) {
86+ let excess = oldVNode . _component . _excess ;
87+ excessDomChildren = [ ] ;
88+ if ( excess . nodeType == 8 ) {
89+ // Re-scan DOM from stored start marker for streamed hydration
90+ for (
91+ let depth = 1 , node = excess . nextSibling ;
92+ node && depth > 0 ;
93+ node = node . nextSibling
94+ ) {
9995 if ( node . nodeType == 8 ) {
10096 if ( node . data . startsWith ( '$s' ) ) depth ++ ;
101- else if ( node . data . startsWith ( '/$s' ) ) {
102- if ( -- depth == 0 ) break ;
103- }
97+ else if ( node . data . startsWith ( '/$s' ) && ! -- depth ) break ;
10498 }
10599 excessDomChildren . push ( node ) ;
106- node = node . nextSibling ;
107100 }
108- oldDom = excessDomChildren [ 0 ] ;
109101 } else {
110- excessDomChildren = oldVNode . _component . _excess ;
111- oldDom = excessDomChildren [ 0 ] ;
102+ excessDomChildren . push ( excess ) ;
112103 }
104+ oldDom = excessDomChildren [ 0 ] ;
113105 oldVNode . _component . _excess = NULL ;
114106 }
115107
@@ -336,7 +328,6 @@ export function diff(
336328 if ( isHydrating || excessDomChildren != NULL ) {
337329 if ( e . then ) {
338330 let commentMarkersToFind = 0 ,
339- done ,
340331 startMarker ;
341332
342333 newVNode . _flags |= isHydrating
@@ -345,24 +336,17 @@ export function diff(
345336
346337 for ( let i = 0 ; i < excessDomChildren . length ; i ++ ) {
347338 let child = excessDomChildren [ i ] ;
348- if ( child == NULL || done ) continue ;
339+ if ( child == NULL ) continue ;
349340
350- // When we encounter a $s boundary marker we are opening a
351- // suspended region. Track nesting depth to find the matching
352- // close marker. We null out ALL nodes in the region so the
353- // parent diff doesn't try to remove them; the children will be
354- // re-scanned from the stored start marker on resume.
355341 if ( child . nodeType == 8 ) {
356342 if ( child . data . startsWith ( '$s' ) ) {
357- if ( ! commentMarkersToFind ) {
358- // Store outermost start marker for deferred restoration
359- startMarker = child ;
360- }
343+ if ( ! commentMarkersToFind ) startMarker = child ;
361344 commentMarkersToFind ++ ;
362345 } else if ( child . data . startsWith ( '/$s' ) ) {
363346 if ( -- commentMarkersToFind == 0 ) {
364- done = true ;
365- oldDom = excessDomChildren [ i ] ;
347+ oldDom = child ;
348+ excessDomChildren [ i ] = NULL ;
349+ break ;
366350 }
367351 }
368352 excessDomChildren [ i ] = NULL ;
@@ -371,18 +355,16 @@ export function diff(
371355 }
372356 }
373357
374- if ( done ) {
375- // Store only the start marker; children are re-scanned on resume
376- // so we always hydrate against the current DOM state.
377- // TODO: consider just storing in _dom and getting rid of _excess altogether?
378- newVNode . _component . _excess = [ startMarker ] ;
358+ if ( startMarker ) {
359+ // Store start marker directly; children re-scanned on resume
360+ newVNode . _component . _excess = startMarker ;
379361 } else {
380362 while ( oldDom && oldDom . nodeType == 8 && oldDom . nextSibling ) {
381363 oldDom = oldDom . nextSibling ;
382364 }
383365
384366 excessDomChildren [ excessDomChildren . indexOf ( oldDom ) ] = NULL ;
385- newVNode . _component . _excess = [ oldDom ] ;
367+ newVNode . _component . _excess = oldDom ;
386368 }
387369
388370 newVNode . _dom = oldDom ;
0 commit comments