Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fizz] track postpones when aborting boundaries with a postpone #30751

Merged
merged 1 commit into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7727,7 +7727,6 @@ describe('ReactDOMFizzServer', () => {

const prerendered = await pendingPrerender;

expect(prerendered.postponed).toBe(null);
expect(errors).toEqual([]);
expect(postpones).toEqual(['manufactured', 'manufactured']);

Expand Down
14 changes: 13 additions & 1 deletion packages/react-server/src/ReactFizzServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3857,7 +3857,6 @@ function abortTask(task: Task, request: Request, error: mixed): void {
} else {
boundary.pendingTasks--;
if (boundary.status !== CLIENT_RENDERED) {
boundary.status = CLIENT_RENDERED;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The point of setting this right away is to avoid a situation where something throws below and we're not in this status.

We really shouldn't throw below though.

// We construct an errorInfo from the boundary's componentStack so the error in dev will indicate which
// boundary the message is referring to
const errorInfo = getThrownInfo(task.componentStack);
Expand All @@ -3870,11 +3869,24 @@ function abortTask(task: Task, request: Request, error: mixed): void {
) {
const postponeInstance: Postpone = (error: any);
logPostpone(request, postponeInstance.message, errorInfo, null);
if (request.trackedPostpones !== null && segment !== null) {
trackPostpone(request, request.trackedPostpones, task, segment);
finishedTask(request, task.blockedBoundary, segment);

// If this boundary was still pending then we haven't already cancelled its fallbacks.
// We'll need to abort the fallbacks, which will also error that parent boundary.
boundary.fallbackAbortableTasks.forEach(fallbackTask =>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the unfortunate case where we hadn't finished the fallback yet which should only be the case if it suspends or has too many awaits.

abortTask(fallbackTask, request, error),
);
boundary.fallbackAbortableTasks.clear();
return;
}
// TODO: Figure out a better signal than a magic digest value.
errorDigest = 'POSTPONE';
} else {
errorDigest = logRecoverableError(request, error, errorInfo, null);
}
boundary.status = CLIENT_RENDERED;
encodeErrorForBoundary(boundary, errorDigest, error, errorInfo, true);

untrackBoundary(request, boundary);
Expand Down
Loading