Skip to content

Commit b3e0a11

Browse files
authored
[Flight] Allow <anonymous> stack frames to be serialized if opt-in (facebook#31329)
Normally we filter out stack frames with missing `filename` because they can be noisy and not ignore listed. However, it's up to the filterStackFrame function to determine whether to do it. This lets us match `<anonymous>` stack frames in V8 parsing (they don't have line numbers).
1 parent 2dc5beb commit b3e0a11

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

packages/react-client/src/ReactFlightClient.js

+2
Original file line numberDiff line numberDiff line change
@@ -2281,6 +2281,8 @@ function createFakeFunction<T>(
22812281
code += '\n//# sourceMappingURL=' + sourceMap;
22822282
} else if (filename) {
22832283
code += '\n//# sourceURL=' + filename;
2284+
} else {
2285+
code += '\n//# sourceURL=<anonymous>';
22842286
}
22852287

22862288
let fn: FakeFunction<T>;

packages/react-client/src/__tests__/ReactFlight-test.js

+17-2
Original file line numberDiff line numberDiff line change
@@ -1282,6 +1282,8 @@ describe('ReactFlight', () => {
12821282
' at file:///testing.js:42:3',
12831283
// async anon function (https://github.com/ChromeDevTools/devtools-frontend/blob/831be28facb4e85de5ee8c1acc4d98dfeda7a73b/test/unittests/front_end/panels/console/ErrorStackParser_test.ts#L130C9-L130C41)
12841284
' at async file:///testing.js:42:3',
1285+
// host component in parent stack
1286+
' at div (<anonymous>)',
12851287
...originalStackLines.slice(2),
12861288
].join('\n');
12871289
throw error;
@@ -1328,6 +1330,15 @@ describe('ReactFlight', () => {
13281330
}
13291331
return `digest(${String(x)})`;
13301332
},
1333+
filterStackFrame(filename, functionName) {
1334+
if (!filename) {
1335+
// Allow anonymous
1336+
return functionName === 'div';
1337+
}
1338+
return (
1339+
!filename.startsWith('node:') && !filename.includes('node_modules')
1340+
);
1341+
},
13311342
});
13321343

13331344
await act(() => {
@@ -1355,14 +1366,16 @@ describe('ReactFlight', () => {
13551366
' at eval (eval at testFunction (eval at createFakeFunction (**), <anonymous>:1:35)\n' +
13561367
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
13571368
' at <anonymous> (file:///testing.js:42:3)\n' +
1358-
' at <anonymous> (file:///testing.js:42:3)\n',
1369+
' at <anonymous> (file:///testing.js:42:3)\n' +
1370+
' at div (<anonymous>',
13591371
)
13601372
: expect.stringContaining(
13611373
'Error: This is an error\n' +
13621374
' at eval (eval at testFunction (inspected-page.html:29:11), <anonymous>:1:10)\n' +
13631375
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
13641376
' at file:///testing.js:42:3\n' +
1365-
' at file:///testing.js:42:3',
1377+
' at file:///testing.js:42:3\n' +
1378+
' at div (<anonymous>',
13661379
),
13671380
digest: 'a dev digest',
13681381
environmentName: 'Server',
@@ -1379,6 +1392,7 @@ describe('ReactFlight', () => {
13791392
'Server',
13801393
],
13811394
['file:///testing.js', 'Server'],
1395+
['', 'Server'],
13821396
[__filename, 'Server'],
13831397
]
13841398
: gate(flags => flags.enableServerComponentLogs)
@@ -1390,6 +1404,7 @@ describe('ReactFlight', () => {
13901404
'Server',
13911405
],
13921406
['file:///testing.js', 'Server'],
1407+
['', 'Server'],
13931408
]
13941409
: [],
13951410
});

packages/react-server/src/ReactFlightStackConfigV8.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ function getStack(error: Error): string {
4444
// at filename:0:0
4545
// at async filename:0:0
4646
const frameRegExp =
47-
/^ {3} at (?:(.+) \((.+):(\d+):(\d+)\)|(?:async )?(.+):(\d+):(\d+))$/;
47+
/^ {3} at (?:(.+) \((?:(.+):(\d+):(\d+)|\<anonymous\>)\)|(?:async )?(.+):(\d+):(\d+)|\<anonymous\>)$/;
4848

4949
export function parseStackTrace(
5050
error: Error,

0 commit comments

Comments
 (0)