Skip to content

Commit 104f0ab

Browse files
committed
Untrack a boundary after it errors
If we have already added resumable slots to a boundary we need to undo that when it errors later. Ideally, we'd remove the whole parent path in this case. If this is the only thing that postpones, we incorrectly think there's resumable slots.
1 parent 7af755e commit 104f0ab

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

packages/react-server/src/ReactFizzServer.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -994,6 +994,8 @@ function renderSuspenseBoundary(
994994
}
995995
encodeErrorForBoundary(newBoundary, errorDigest, error, thrownInfo);
996996

997+
untrackBoundary(request, newBoundary);
998+
997999
// We don't need to decrement any task numbers because we didn't spawn any new task.
9981000
// We don't need to schedule any task because we know the parent has written yet.
9991001
// We do need to fallthrough to create the fallback though.
@@ -2672,6 +2674,33 @@ function trackPostpone(
26722674
}
26732675
}
26742676

2677+
// In case a boundary errors, we need to stop tracking it because we won't
2678+
// resume it.
2679+
function untrackBoundary(request: Request, boundary: SuspenseBoundary) {
2680+
const trackedPostpones = request.trackedPostpones;
2681+
if (trackedPostpones === null) {
2682+
return;
2683+
}
2684+
const boundaryKeyPath = boundary.trackedContentKeyPath;
2685+
if (boundaryKeyPath === null) {
2686+
return;
2687+
}
2688+
const boundaryNode: void | ReplayNode =
2689+
trackedPostpones.workingMap.get(boundaryKeyPath);
2690+
if (boundaryNode === undefined) {
2691+
return;
2692+
}
2693+
2694+
// Downgrade to plain ReplayNode since we won't replay through it.
2695+
boundaryNode.length = 4;
2696+
// Remove any resumable slots.
2697+
boundaryNode[2] = [];
2698+
boundaryNode[3] = null;
2699+
2700+
// TODO: We should really just remove the boundary from all parent paths too so
2701+
// we don't replay the path to it.
2702+
}
2703+
26752704
function injectPostponedHole(
26762705
request: Request,
26772706
task: RenderTask,
@@ -3007,6 +3036,7 @@ function erroredTask(
30073036
if (boundary.status !== CLIENT_RENDERED) {
30083037
boundary.status = CLIENT_RENDERED;
30093038
encodeErrorForBoundary(boundary, errorDigest, error, errorInfo);
3039+
untrackBoundary(request, boundary);
30103040

30113041
// Regardless of what happens next, this boundary won't be displayed,
30123042
// so we can flush it, if the parent already flushed.
@@ -3192,6 +3222,8 @@ function abortTask(task: Task, request: Request, error: mixed): void {
31923222
}
31933223
encodeErrorForBoundary(boundary, errorDigest, errorMessage, errorInfo);
31943224

3225+
untrackBoundary(request, boundary);
3226+
31953227
if (boundary.parentFlushed) {
31963228
request.clientRenderedBoundaries.push(boundary);
31973229
}

0 commit comments

Comments
 (0)