[Fizz] Reset the segent id assignment when postponing the root (#33755)

When postponing the root we encode the segment Id into the postponed
state but we should really be reseting it to zero so we can restart the
counter from the beginning when the resume is actually just a re-render.

This also no longer assigns the root segment id based on the postponed
state when resuming the root for the same reason. In the future we may
use the embedded replay segment id if we implement resuming the root
without re-rendering everything but that is not yet implemented or
planned.
This commit is contained in:
Josh Story 2025-07-10 12:12:09 -07:00 committed by GitHub
parent 96c61b7f1f
commit 463b808176
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 12 additions and 9 deletions

View File

@ -1623,7 +1623,7 @@ describe('ReactDOMFizzStaticBrowser', () => {
expect(result).toBe(
'<!DOCTYPE html><html><head><link rel="expect" href="#_R_" blocking="render"/></head>' +
'<body>hello<!--$?--><template id="B:1"></template><!--/$--><script id="_R_">requestAnimationFrame(function(){$RT=performance.now()});</script>',
'<body>hello<!--$?--><template id="B:0"></template><!--/$--><script id="_R_">requestAnimationFrame(function(){$RT=performance.now()});</script>',
);
await 1;
@ -1648,8 +1648,8 @@ describe('ReactDOMFizzStaticBrowser', () => {
expect(slice).toBe(
'<!DOCTYPE html><html><head><link rel="expect" href="#_R_" blocking="render"/></head>' +
'<body>hello<!--$?--><template id="B:1"></template><!--/$--><script id="_R_">requestAnimationFrame(function(){$RT=performance.now()});</script>' +
'<div hidden id="S:1">world<!-- --></div><script>$RX',
'<body>hello<!--$?--><template id="B:0"></template><!--/$--><script id="_R_">requestAnimationFrame(function(){$RT=performance.now()});</script>' +
'<div hidden id="S:0">world<!-- --></div><script>$RX',
);
});

View File

@ -666,7 +666,6 @@ export function resumeRequest(
request.nextSegmentId = postponedState.nextSegmentId;
if (typeof postponedState.replaySlots === 'number') {
const resumedId = postponedState.replaySlots;
// We have a resume slot at the very root. This is effectively just a full rerender.
const rootSegment = createPendingSegment(
request,
@ -677,7 +676,6 @@ export function resumeRequest(
false,
false,
);
rootSegment.id = resumedId;
// There is no parent so conceptually, we're unblocked to flush this segment.
rootSegment.parentFlushed = true;
const rootTask = createRenderTask(
@ -6326,6 +6324,7 @@ export function getPostponedState(request: Request): null | PostponedState {
return null;
}
let replaySlots: ResumeSlots;
let nextSegmentId: number;
if (
request.completedRootSegment !== null &&
// The Root postponed
@ -6333,17 +6332,21 @@ export function getPostponedState(request: Request): null | PostponedState {
// Or the Preamble was not available
request.completedPreambleSegments === null)
) {
// This is necessary for the pending preamble case and is idempotent for the
// postponed root case
replaySlots = request.completedRootSegment.id;
nextSegmentId = 0;
// We need to ensure that on resume we retry the root. We use a number
// type for the replaySlots to signify this (see resumeRequest).
// The value -1 represents an unassigned ID but is not functionally meaningful
// for resuming at the root.
replaySlots = -1;
// We either postponed the root or we did not have a preamble to flush
resetResumableState(request.resumableState, request.renderState);
} else {
nextSegmentId = request.nextSegmentId;
replaySlots = trackedPostpones.rootSlots;
completeResumableState(request.resumableState);
}
return {
nextSegmentId: request.nextSegmentId,
nextSegmentId,
rootFormatContext: request.rootFormatContext,
progressiveChunkSize: request.progressiveChunkSize,
resumableState: request.resumableState,