Skip to content

Commit e6de05f

Browse files
committed
When forwarding debug info we need to parse the debugStack if one exists
In this case of creating a stack in the client, we won't already have the parsed form.
1 parent 8bc7c51 commit e6de05f

File tree

2 files changed

+46
-13
lines changed

2 files changed

+46
-13
lines changed

packages/react-client/src/ReactFlightClient.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,9 @@ function resolveDebugInfo(
26792679
// was created on the server isn't very useful but where the request was made is.
26802680
// $FlowFixMe[cannot-write]
26812681
componentInfoOrAsyncInfo.debugStack = response._debugRootStack;
2682+
// We clear the parsed stack frames to indicate that it needs to be re-parsed from debugStack.
2683+
// $FlowFixMe[cannot-write]
2684+
componentInfoOrAsyncInfo.stack = null;
26822685
} else if (debugInfo.stack !== undefined) {
26832686
const componentInfoOrAsyncInfo: ReactComponentInfo | ReactAsyncInfo =
26842687
// $FlowFixMe[incompatible-type]

packages/react-server/src/ReactFlightServer.js

Lines changed: 43 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3591,8 +3591,17 @@ function outlineComponentInfo(
35913591
key: componentInfo.key,
35923592
owner: componentInfo.owner,
35933593
};
3594-
// $FlowFixMe[cannot-write]
3595-
componentDebugInfo.stack = componentInfo.stack;
3594+
if (componentInfo.stack == null && componentInfo.debugStack != null) {
3595+
// If we have a debugStack but no parsed stack we should parse it.
3596+
// $FlowFixMe[cannot-write]
3597+
componentDebugInfo.stack = filterStackTrace(
3598+
request,
3599+
parseStackTrace(componentInfo.debugStack, 1),
3600+
);
3601+
} else {
3602+
// $FlowFixMe[cannot-write]
3603+
componentDebugInfo.stack = componentInfo.stack;
3604+
}
35963605
// Ensure we serialize props after the stack to favor the stack being complete.
35973606
// $FlowFixMe[cannot-write]
35983607
componentDebugInfo.props = componentInfo.props;
@@ -3679,6 +3688,16 @@ function outlineIOInfo(request: Request, ioInfo: ReactIOInfo): void {
36793688
if (owner != null) {
36803689
outlineComponentInfo(request, owner);
36813690
}
3691+
let debugStack;
3692+
if (ioInfo.stack == null && ioInfo.debugStack != null) {
3693+
// If we have a debugStack but no parsed stack we should parse it.
3694+
debugStack = filterStackTrace(
3695+
request,
3696+
parseStackTrace(ioInfo.debugStack, 1),
3697+
);
3698+
} else {
3699+
debugStack = ioInfo.stack;
3700+
}
36823701
emitIOInfoChunk(
36833702
request,
36843703
id,
@@ -3687,7 +3706,7 @@ function outlineIOInfo(request: Request, ioInfo: ReactIOInfo): void {
36873706
ioInfo.end,
36883707
ioInfo.env,
36893708
owner,
3690-
ioInfo.stack,
3709+
debugStack,
36913710
);
36923711
request.writtenObjects.set(ioInfo, serializeByValueID(id));
36933712
}
@@ -4243,29 +4262,40 @@ function forwardDebugInfo(
42434262
debugInfo: ReactDebugInfo,
42444263
) {
42454264
for (let i = 0; i < debugInfo.length; i++) {
4246-
if (typeof debugInfo[i].time === 'number') {
4265+
const info = debugInfo[i];
4266+
if (typeof info.time === 'number') {
42474267
// When forwarding time we need to ensure to convert it to the time space of the payload.
4248-
emitTimingChunk(request, id, debugInfo[i].time);
4268+
emitTimingChunk(request, id, info.time);
42494269
} else {
42504270
request.pendingChunks++;
4251-
if (typeof debugInfo[i].name === 'string') {
4271+
if (typeof info.name === 'string') {
42524272
// We outline this model eagerly so that we can refer to by reference as an owner.
42534273
// If we had a smarter way to dedupe we might not have to do this if there ends up
42544274
// being no references to this as an owner.
4255-
outlineComponentInfo(request, (debugInfo[i]: any));
4275+
outlineComponentInfo(request, (info: any));
42564276
// Emit a reference to the outlined one.
4257-
emitDebugChunk(request, id, debugInfo[i]);
4258-
} else if (debugInfo[i].awaited) {
4259-
const ioInfo = debugInfo[i].awaited;
4277+
emitDebugChunk(request, id, info);
4278+
} else if (info.awaited) {
4279+
const ioInfo = info.awaited;
42604280
// Outline the IO info in case the same I/O is awaited in more than one place.
42614281
outlineIOInfo(request, ioInfo);
42624282
// We can't serialize the ConsoleTask/Error objects so we need to omit them before serializing.
4283+
let debugStack;
4284+
if (info.stack == null && info.debugStack != null) {
4285+
// If we have a debugStack but no parsed stack we should parse it.
4286+
debugStack = filterStackTrace(
4287+
request,
4288+
parseStackTrace(info.debugStack, 1),
4289+
);
4290+
} else {
4291+
debugStack = info.stack;
4292+
}
42634293
const debugAsyncInfo: Omit<ReactAsyncInfo, 'debugTask' | 'debugStack'> =
42644294
{
42654295
awaited: ioInfo,
4266-
env: debugInfo[i].env,
4267-
owner: debugInfo[i].owner,
4268-
stack: debugInfo[i].stack,
4296+
env: info.env,
4297+
owner: info.owner,
4298+
stack: debugStack,
42694299
};
42704300
emitDebugChunk(request, id, debugAsyncInfo);
42714301
} else {

0 commit comments

Comments
 (0)