Skip to content

Commit f619f24

Browse files
committed
[Flight] Allow parens in filenames when parsing stackframes
1 parent 34e4410 commit f619f24

File tree

2 files changed

+26
-4
lines changed

2 files changed

+26
-4
lines changed

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

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
'use strict';
1212

13+
const path = require('path');
14+
1315
if (typeof Blob === 'undefined') {
1416
global.Blob = require('buffer').Blob;
1517
}
@@ -41,15 +43,23 @@ function formatV8Stack(stack) {
4143
return v8StyleStack;
4244
}
4345

46+
const repoRoot = path.resolve(__dirname, '../../../../');
47+
function normalizeReactCodeLocInfo(str) {
48+
const repoRootForRegexp = repoRoot.replace(/\//g, '\\/');
49+
const repoFileLocMatch = new RegExp(`${repoRootForRegexp}.+?:\\d+:\\d+`, 'g');
50+
return str && str.replace(repoFileLocMatch, '**');
51+
}
52+
4453
// If we just use the original Error prototype, Jest will only display the error message if assertions fail.
4554
// But we usually want to also assert on our expando properties or even the stack.
4655
// By hiding the fact from Jest that this is an error, it will show all enumerable properties on mismatch.
56+
4757
function getErrorForJestMatcher(error) {
4858
return {
4959
...error,
5060
// non-enumerable properties that are still relevant for testing
5161
message: error.message,
52-
stack: error.stack,
62+
stack: normalizeReactCodeLocInfo(error.stack),
5363
};
5464
}
5565

@@ -1211,7 +1221,7 @@ describe('ReactFlight', () => {
12111221
throw error;
12121222
}
12131223

1214-
const findSourceMapURL = jest.fn();
1224+
const findSourceMapURL = jest.fn(() => null);
12151225
const errors = [];
12161226
class MyErrorBoundary extends React.Component {
12171227
state = {error: null};
@@ -1273,11 +1283,15 @@ describe('ReactFlight', () => {
12731283
stack: gate(flags => flags.enableOwnerStacks)
12741284
? expect.stringContaining(
12751285
'Error: This is an error\n' +
1286+
' at eval (eval at testFunction (eval at createFakeFunction (**), <anonymous>:1:35)\n' +
1287+
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
12761288
' at (anonymous) (file:///testing.js:42:3)\n' +
12771289
' at (anonymous) (file:///testing.js:42:3)\n',
12781290
)
12791291
: expect.stringContaining(
12801292
'Error: This is an error\n' +
1293+
' at eval (eval at testFunction (inspected-page.html:29:11), <anonymous>:1:10)\n' +
1294+
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
12811295
' at file:///testing.js:42:3\n' +
12821296
' at file:///testing.js:42:3',
12831297
),
@@ -1286,7 +1300,15 @@ describe('ReactFlight', () => {
12861300
},
12871301
],
12881302
findSourceMapURLCalls: gate(flags => flags.enableOwnerStacks)
1289-
? [[__filename], [__filename], ['file:///testing.js'], [__filename]]
1303+
? [
1304+
[__filename],
1305+
[__filename],
1306+
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
1307+
['inspected-page.html:29:11), <anonymous>'],
1308+
['file://~/(some)(really)(exotic-directory)/ReactFlight-test.js'],
1309+
['file:///testing.js'],
1310+
[__filename],
1311+
]
12901312
: [],
12911313
});
12921314
} else {

packages/react-server/src/ReactFlightStackConfigV8.js

Lines changed: 1 addition & 1 deletion
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+)\)|(?:async )?(.+):(\d+):(\d+))$/;
4848

4949
export function parseStackTrace(
5050
error: Error,

0 commit comments

Comments
 (0)