[Fizz] Only compute component stacks in DEV and prerenders (#27850)
If you have a lot of intentional throws (or postpones) from client-only rendering then computing the stack is too much.
Sebastian Markbåge committed
Dec 19, 2023 at 18:04 UTC
c5b9375767e2c4102d7e5559d383523736f1c902
1 file changed
+20
-11
packages/react-server/src/ReactFizzServer.js
+20
-11
@@ -769,8 +769,17 @@ export type PostponeInfo = ThrownInfo;
769
// during prerender in Prod. The reason for this is that the stack is useful for prerender where the timeliness
770
// of the request is less critical than the observability of the execution. For renders and resumes however we
771
// prioritize speed of the request.
772
-function getThrownInfo(node: null | ComponentStackNode): ThrownInfo {
773
- if (node) {
772
+function getThrownInfo(
773
+ request: Request,
774
+ node: null | ComponentStackNode,
775
+): ThrownInfo {
776
+ if (
777
+ node &&
778
+ // Always produce a stack in dev
779
+ (__DEV__ ||
780
+ // Produce a stack in prod if we're in a prerender
781
+ request.trackedPostpones !== null)
782
+ ) {
783
return {
784
componentStack: getStackFromNode(node),
785
};
@@ -968,7 +977,7 @@ function renderSuspenseBoundary(
977
} catch (error: mixed) {
978
contentRootSegment.status = ERRORED;
979
newBoundary.status = CLIENT_RENDERED;
971
- const thrownInfo = getThrownInfo(task.componentStack);
980
+ const thrownInfo = getThrownInfo(request, task.componentStack);
981
let errorDigest;
982
if (
983
enablePostpone &&
@@ -1117,7 +1126,7 @@ function replaySuspenseBoundary(
1126
}
1127
} catch (error: mixed) {
1128
resumedBoundary.status = CLIENT_RENDERED;
1120
- const thrownInfo = getThrownInfo(task.componentStack);
1129
+ const thrownInfo = getThrownInfo(request, task.componentStack);
1130
let errorDigest;
1131
if (
1132
enablePostpone &&
@@ -2088,7 +2097,7 @@ function replayElement(
2097
// in the original prerender. What's unable to complete is the child
2098
// replay nodes which might be Suspense boundaries which are able to
2099
// absorb the error and we can still continue with siblings.
2091
- const thrownInfo = getThrownInfo(task.componentStack);
2100
+ const thrownInfo = getThrownInfo(request, task.componentStack);
2101
erroredReplay(
2102
request,
2103
task.blockedBoundary,
@@ -2424,7 +2433,7 @@ function replayFragment(
2433
// replay nodes which might be Suspense boundaries which are able to
2434
// absorb the error and we can still continue with siblings.
2435
// This is an error, stash the component stack if it is null.
2427
- const thrownInfo = getThrownInfo(task.componentStack);
2436
+ const thrownInfo = getThrownInfo(request, task.componentStack);
2437
erroredReplay(
2438
request,
2439
task.blockedBoundary,
@@ -2888,7 +2897,7 @@ function renderNode(
2897
const trackedPostpones = request.trackedPostpones;
2898
2899
const postponeInstance: Postpone = (x: any);
2891
- const thrownInfo = getThrownInfo(task.componentStack);
2900
+ const thrownInfo = getThrownInfo(request, task.componentStack);
2901
const postponedSegment = injectPostponedHole(
2902
request,
2903
((task: any): RenderTask), // We don't use ReplayTasks in prerenders.
@@ -3168,7 +3177,7 @@ function abortTask(task: Task, request: Request, error: mixed): void {
3177
boundary.status = CLIENT_RENDERED;
3178
// We construct an errorInfo from the boundary's componentStack so the error in dev will indicate which
3179
// boundary the message is referring to
3171
- const errorInfo = getThrownInfo(task.componentStack);
3180
+ const errorInfo = getThrownInfo(request, task.componentStack);
3181
const errorDigest = logRecoverableError(request, error, errorInfo);
3182
let errorMessage = error;
3183
if (__DEV__) {
@@ -3470,7 +3479,7 @@ function retryRenderTask(
3479
task.abortSet.delete(task);
3480
const postponeInstance: Postpone = (x: any);
3481
3473
- const postponeInfo = getThrownInfo(task.componentStack);
3482
+ const postponeInfo = getThrownInfo(request, task.componentStack);
3483
logPostpone(request, postponeInstance.message, postponeInfo);
3484
trackPostpone(request, trackedPostpones, task, segment);
3485
finishedTask(request, task.blockedBoundary, segment);
@@ -3478,7 +3487,7 @@ function retryRenderTask(
3487
}
3488
}
3489
3481
- const errorInfo = getThrownInfo(task.componentStack);
3490
+ const errorInfo = getThrownInfo(request, task.componentStack);
3491
task.abortSet.delete(task);
3492
segment.status = ERRORED;
3493
erroredTask(request, task.blockedBoundary, x, errorInfo);
@@ -3562,7 +3571,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void {
3571
}
3572
task.replay.pendingTasks--;
3573
task.abortSet.delete(task);
3565
- const errorInfo = getThrownInfo(task.componentStack);
3574
+ const errorInfo = getThrownInfo(request, task.componentStack);
3575
erroredReplay(
3576
request,
3577
task.blockedBoundary,