Skip to content

Commit

Permalink
[Flight] Allow parens in filenames when parsing stackframes
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon committed Jul 24, 2024
1 parent 68ab934 commit 2bbfc8a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 12 deletions.
47 changes: 36 additions & 11 deletions packages/react-client/src/__tests__/ReactFlight-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

'use strict';

const path = require('path');

if (typeof Blob === 'undefined') {
global.Blob = require('buffer').Blob;
}
Expand Down Expand Up @@ -41,15 +43,23 @@ function formatV8Stack(stack) {
return v8StyleStack;
}

const repoRoot = path.resolve(__dirname, '../../../../');
function normalizeReactCodeLocInfo(str) {
const repoRootForRegexp = repoRoot.replace(/\//g, '\\/');
const repoFileLocMatch = new RegExp(`${repoRootForRegexp}.+?:\\d+:\\d+`, 'g');
return str && str.replace(repoFileLocMatch, '**');
}

// If we just use the original Error prototype, Jest will only display the error message if assertions fail.
// But we usually want to also assert on our expando properties or even the stack.
// By hiding the fact from Jest that this is an error, it will show all enumerable properties on mismatch.

function getErrorForJestMatcher(error) {
return {
...error,
// non-enumerable properties that are still relevant for testing
message: error.message,
stack: error.stack,
stack: normalizeReactCodeLocInfo(error.stack),
};
}

Expand Down Expand Up @@ -1211,7 +1221,7 @@ describe('ReactFlight', () => {
throw error;
}

const findSourceMapURL = jest.fn();
const findSourceMapURL = jest.fn(() => null);
const errors = [];
class MyErrorBoundary extends React.Component {
state = {error: null};
Expand Down Expand Up @@ -1270,19 +1280,34 @@ describe('ReactFlight', () => {
errors: [
{
message: 'This is an error',
stack: expect.stringContaining(
'Error: This is an error\n' +
' at (anonymous) (file:///testing.js:42:3)\n' +
' at (anonymous) (file:///testing.js:42:3)\n',
),
stack: gate(flags => flags.enableOwnerStacks)
? expect.stringContaining(
'Error: This is an error\n' +
' at eval (eval at testFunction (eval at createFakeFunction (**), <anonymous>:1:35)\n' +
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
' at (anonymous) (file:///testing.js:42:3)\n' +
' at (anonymous) (file:///testing.js:42:3)\n',
)
: expect.stringContaining(
'Error: This is an error\n' +
' at eval (eval at testFunction (inspected-page.html:29:11), <anonymous>:1:10)\n' +
' at ServerComponentError (file://~/(some)(really)(exotic-directory)/ReactFlight-test.js:1166:19)\n' +
' at file:///testing.js:42:3\n' +
' at async file:///testing.js:42:3\n',
),
digest: 'a dev digest',
environmentName: 'Server',
},
],
findSourceMapURLCalls: expect.arrayContaining([
['file:///testing.js'],
['file:///testing.js'],
]),
findSourceMapURLCalls: gate(flags => flags.enableOwnerStacks)
? expect.arrayContaining([
// TODO: What should we request here? The outer (<anonymous>) or the inner (inspected-page.html)?
['inspected-page.html:29:11), <anonymous>'],
['file://~/(some)(really)(exotic-directory)/ReactFlight-test.js'],
['file:///testing.js'],
['file:///testing.js'],
])
: [],
});
} else {
expect(errors.map(getErrorForJestMatcher)).toEqual([
Expand Down
2 changes: 1 addition & 1 deletion packages/react-server/src/ReactFlightStackConfigV8.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function getStack(error: Error): string {
// at filename:0:0
// at async filename:0:0
const frameRegExp =
/^ {3} at (?:(.+) \(([^\)]+):(\d+):(\d+)\)|(?:async )?([^\)]+):(\d+):(\d+))$/;
/^ {3} at (?:(.+) \((.+):(\d+):(\d+)\)|(?:async )?(.+):(\d+):(\d+))$/;

export function parseStackTrace(
error: Error,
Expand Down

0 comments on commit 2bbfc8a

Please sign in to comment.