Skip to content

Commit e45f8a6

Browse files
Luca Forstnertimfish
andauthored
fix(browser): Fix parenthesis parsing logic for chromium (#12373)
Co-authored-by: Tim Fish <[email protected]>
1 parent da59f96 commit e45f8a6

File tree

5 files changed

+95
-2
lines changed

5 files changed

+95
-2
lines changed

.size-limit.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ module.exports = [
2222
path: 'packages/browser/build/npm/esm/index.js',
2323
import: createImport('init', 'browserTracingIntegration', 'replayIntegration'),
2424
gzip: true,
25-
limit: '70 KB',
25+
limit: '71 KB',
2626
},
2727
{
2828
name: '@sentry/browser (incl. Tracing, Replay) - with treeshaking flags',

packages/browser/src/stack-parsers.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,29 @@ function createFrame(filename: string, func: string, lineno?: number, colno?: nu
5050
return frame;
5151
}
5252

53-
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
53+
// This regex matches frames that have no function name (ie. are at the top level of a module).
54+
// For example "at http://localhost:5000//script.js:1:126"
55+
// Frames _with_ function names usually look as follows: "at commitLayoutEffects (react-dom.development.js:23426:1)"
56+
const chromeRegexNoFnName = /^\s*at (\S+?)(?::(\d+))(?::(\d+))\s*$/i;
57+
58+
// This regex matches all the frames that have a function name.
5459
const chromeRegex =
5560
/^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
61+
5662
const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
5763

64+
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
5865
// We cannot call this variable `chrome` because it can conflict with global `chrome` variable in certain environments
5966
// See: https://github.com/getsentry/sentry-javascript/issues/6880
6067
const chromeStackParserFn: StackLineParserFn = line => {
68+
// If the stack line has no function name, we need to parse it differently
69+
const noFnParts = chromeRegexNoFnName.exec(line);
70+
71+
if (noFnParts) {
72+
const [, filename, line, col] = noFnParts;
73+
return createFrame(filename, UNKNOWN_FUNCTION, +line, +col);
74+
}
75+
6176
const parts = chromeRegex.exec(line);
6277

6378
if (parts) {

packages/browser/test/unit/tracekit/chromium.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,7 @@ describe('Tracekit - Chrome Tests', () => {
579579
name: 'Error',
580580
stack: `Error: bad
581581
at something (http://localhost:5000/(some)/(thing)/index.html:20:16)
582+
at http://localhost:5000/(group)/[route]/script.js:1:126
582583
at more (http://localhost:5000/(some)/(thing)/index.html:25:7)`,
583584
};
584585

@@ -596,6 +597,13 @@ describe('Tracekit - Chrome Tests', () => {
596597
colno: 7,
597598
in_app: true,
598599
},
600+
{
601+
filename: 'http://localhost:5000/(group)/[route]/script.js',
602+
function: '?',
603+
lineno: 1,
604+
colno: 126,
605+
in_app: true,
606+
},
599607
{
600608
filename: 'http://localhost:5000/(some)/(thing)/index.html',
601609
function: 'something',

packages/browser/test/unit/tracekit/firefox.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,41 @@ describe('Tracekit - Firefox Tests', () => {
311311
});
312312
});
313313

314+
it('should correctly parse parentheses', () => {
315+
const PARENTHESIS_FRAME_EXCEPTION = {
316+
message: 'aha',
317+
name: 'Error',
318+
stack:
319+
'onClick@http://localhost:3002/_next/static/chunks/app/(group)/[route]/script.js:1:644\n' +
320+
'@http://localhost:3002/_next/static/chunks/app/(group)/[route]/script.js:1:126',
321+
};
322+
323+
const stacktrace = exceptionFromError(parser, PARENTHESIS_FRAME_EXCEPTION);
324+
325+
expect(stacktrace).toEqual({
326+
value: 'aha',
327+
type: 'Error',
328+
stacktrace: {
329+
frames: [
330+
{
331+
colno: 126,
332+
filename: 'http://localhost:3002/_next/static/chunks/app/(group)/[route]/script.js',
333+
function: '?',
334+
in_app: true,
335+
lineno: 1,
336+
},
337+
{
338+
colno: 644,
339+
filename: 'http://localhost:3002/_next/static/chunks/app/(group)/[route]/script.js',
340+
function: 'onClick',
341+
in_app: true,
342+
lineno: 1,
343+
},
344+
],
345+
},
346+
});
347+
});
348+
314349
it('should parse Firefox errors with `file` inside an identifier', () => {
315350
const FIREFOX_FILE_IN_IDENTIFIER = {
316351
stack:

packages/browser/test/unit/tracekit/safari.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,4 +320,39 @@ describe('Tracekit - Safari Tests', () => {
320320
},
321321
});
322322
});
323+
324+
it('should correctly parse parentheses', () => {
325+
const PARENTHESIS_FRAME_EXCEPTION = {
326+
message: 'aha',
327+
name: 'Error',
328+
stack:
329+
'@http://localhost:3000/(group)/[route]/script.js:1:131\n' +
330+
'global code@http://localhost:3000/(group)/[route]/script.js:1:334',
331+
};
332+
333+
const ex = exceptionFromError(parser, PARENTHESIS_FRAME_EXCEPTION);
334+
335+
expect(ex).toEqual({
336+
value: 'aha',
337+
type: 'Error',
338+
stacktrace: {
339+
frames: [
340+
{
341+
colno: 334,
342+
filename: 'http://localhost:3000/(group)/[route]/script.js',
343+
function: 'global code',
344+
in_app: true,
345+
lineno: 1,
346+
},
347+
{
348+
colno: 131,
349+
filename: 'http://localhost:3000/(group)/[route]/script.js',
350+
function: '?',
351+
in_app: true,
352+
lineno: 1,
353+
},
354+
],
355+
},
356+
});
357+
});
323358
});

0 commit comments

Comments
 (0)