Skip to content

Commit

Permalink
[Flight] Dedupe suspense boundaries when it has already been found ea…
Browse files Browse the repository at this point in the history
…rlier (#27408)

If we track a postponed SuspenseBoundary parent that we have to replay
through before it has postponed and it postpones itself later, we need
to upgrade it to a postponed replay boundary instead of adding two.
  • Loading branch information
sebmarkbage authored Sep 23, 2023
1 parent 7f62018 commit 69728fd
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 9 deletions.
47 changes: 47 additions & 0 deletions packages/react-dom/src/__tests__/ReactDOMFizzStaticBrowser-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -840,4 +840,51 @@ describe('ReactDOMFizzStaticBrowser', () => {
</div>,
]);
});

// @gate enablePostpone
it('can postpone a boundary after it has already been added', async () => {
let prerendering = true;
function Postpone() {
if (prerendering) {
React.unstable_postpone();
}
return 'Hello';
}

function App() {
return (
<div>
<Suspense fallback="Loading...">
<Suspense fallback="Loading...">
<Postpone />
</Suspense>
<Postpone />
<Postpone />
</Suspense>
</div>
);
}

const prerendered = await ReactDOMFizzStatic.prerender(<App />);
expect(prerendered.postponed).not.toBe(null);

prerendering = false;

console.log(JSON.stringify(prerendered.postponed, null, 2));

const resumed = await ReactDOMFizzServer.resume(
<App />,
JSON.parse(JSON.stringify(prerendered.postponed)),
);

await readIntoContainer(prerendered.prelude);

expect(getVisibleChildren(container)).toEqual(<div>Loading...</div>);

await readIntoContainer(resumed);

expect(getVisibleChildren(container)).toEqual(
<div>{['Hello', 'Hello', 'Hello']}</div>,
);
});
});
26 changes: 17 additions & 9 deletions packages/react-server/src/ReactFizzServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2490,15 +2490,23 @@ function trackPostpone(
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
return;
} else {
const boundaryNode: ReplaySuspenseBoundary = [
boundaryKeyPath[1],
boundaryKeyPath[2],
children,
null,
boundary.rootSegmentID,
];
trackedPostpones.workingMap.set(boundaryKeyPath, boundaryNode);
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
let boundaryNode: void | ReplayNode =
trackedPostpones.workingMap.get(boundaryKeyPath);
if (boundaryNode === undefined) {
boundaryNode = [
boundaryKeyPath[1],
boundaryKeyPath[2],
children,
null,
boundary.rootSegmentID,
];
trackedPostpones.workingMap.set(boundaryKeyPath, boundaryNode);
addToReplayParent(boundaryNode, boundaryKeyPath[0], trackedPostpones);
} else {
// Upgrade to ReplaySuspenseBoundary.
((boundaryNode: any): ReplaySuspenseBoundary)[4] =
boundary.rootSegmentID;
}
// Fall through to add the child node.
}
}
Expand Down

0 comments on commit 69728fd

Please sign in to comment.