diff --git a/packages/react-server/src/ReactFizzServer.js b/packages/react-server/src/ReactFizzServer.js index cd34e285b1e74..fe9d7b283b2db 100644 --- a/packages/react-server/src/ReactFizzServer.js +++ b/packages/react-server/src/ReactFizzServer.js @@ -769,8 +769,17 @@ export type PostponeInfo = ThrownInfo; // during prerender in Prod. The reason for this is that the stack is useful for prerender where the timeliness // of the request is less critical than the observability of the execution. For renders and resumes however we // prioritize speed of the request. -function getThrownInfo(node: null | ComponentStackNode): ThrownInfo { - if (node) { +function getThrownInfo( + request: Request, + node: null | ComponentStackNode, +): ThrownInfo { + if ( + node && + // Always produce a stack in dev + (__DEV__ || + // Produce a stack in prod if we're in a prerender + request.trackedPostpones !== null) + ) { return { componentStack: getStackFromNode(node), }; @@ -968,7 +977,7 @@ function renderSuspenseBoundary( } catch (error: mixed) { contentRootSegment.status = ERRORED; newBoundary.status = CLIENT_RENDERED; - const thrownInfo = getThrownInfo(task.componentStack); + const thrownInfo = getThrownInfo(request, task.componentStack); let errorDigest; if ( enablePostpone && @@ -1117,7 +1126,7 @@ function replaySuspenseBoundary( } } catch (error: mixed) { resumedBoundary.status = CLIENT_RENDERED; - const thrownInfo = getThrownInfo(task.componentStack); + const thrownInfo = getThrownInfo(request, task.componentStack); let errorDigest; if ( enablePostpone && @@ -2088,7 +2097,7 @@ function replayElement( // in the original prerender. What's unable to complete is the child // replay nodes which might be Suspense boundaries which are able to // absorb the error and we can still continue with siblings. - const thrownInfo = getThrownInfo(task.componentStack); + const thrownInfo = getThrownInfo(request, task.componentStack); erroredReplay( request, task.blockedBoundary, @@ -2424,7 +2433,7 @@ function replayFragment( // replay nodes which might be Suspense boundaries which are able to // absorb the error and we can still continue with siblings. // This is an error, stash the component stack if it is null. - const thrownInfo = getThrownInfo(task.componentStack); + const thrownInfo = getThrownInfo(request, task.componentStack); erroredReplay( request, task.blockedBoundary, @@ -2888,7 +2897,7 @@ function renderNode( const trackedPostpones = request.trackedPostpones; const postponeInstance: Postpone = (x: any); - const thrownInfo = getThrownInfo(task.componentStack); + const thrownInfo = getThrownInfo(request, task.componentStack); const postponedSegment = injectPostponedHole( request, ((task: any): RenderTask), // We don't use ReplayTasks in prerenders. @@ -3168,7 +3177,7 @@ function abortTask(task: Task, request: Request, error: mixed): void { boundary.status = CLIENT_RENDERED; // 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); + const errorInfo = getThrownInfo(request, task.componentStack); const errorDigest = logRecoverableError(request, error, errorInfo); let errorMessage = error; if (__DEV__) { @@ -3470,7 +3479,7 @@ function retryRenderTask( task.abortSet.delete(task); const postponeInstance: Postpone = (x: any); - const postponeInfo = getThrownInfo(task.componentStack); + const postponeInfo = getThrownInfo(request, task.componentStack); logPostpone(request, postponeInstance.message, postponeInfo); trackPostpone(request, trackedPostpones, task, segment); finishedTask(request, task.blockedBoundary, segment); @@ -3478,7 +3487,7 @@ function retryRenderTask( } } - const errorInfo = getThrownInfo(task.componentStack); + const errorInfo = getThrownInfo(request, task.componentStack); task.abortSet.delete(task); segment.status = ERRORED; erroredTask(request, task.blockedBoundary, x, errorInfo); @@ -3562,7 +3571,7 @@ function retryReplayTask(request: Request, task: ReplayTask): void { } task.replay.pendingTasks--; task.abortSet.delete(task); - const errorInfo = getThrownInfo(task.componentStack); + const errorInfo = getThrownInfo(request, task.componentStack); erroredReplay( request, task.blockedBoundary,