Skip to content

Commit b1f0c6a

Browse files
authored
fix: Drop initial frame for production react errors (#2728)
1 parent 61a1828 commit b1f0c6a

File tree

2 files changed

+104
-1
lines changed

2 files changed

+104
-1
lines changed

packages/browser/src/tracekit.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,23 @@ const gecko = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:file|https?|blob|chrome|webpac
5050
const winjs = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:file|ms-appx|https?|webpack|blob):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
5151
const geckoEval = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
5252
const chromeEval = /\((\S*)(?::(\d+))(?::(\d+))\)/;
53+
// Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108
54+
const reactMinifiedRegexp = /Minified React error #\d+;/i;
5355

5456
/** JSDoc */
5557
export function computeStackTrace(ex: any): StackTrace {
5658
// tslint:disable:no-unsafe-any
5759

5860
let stack = null;
59-
const popSize: number = ex && ex.framesToPop;
61+
let popSize = 0;
62+
63+
if (ex) {
64+
if (typeof ex.framesToPop === 'number') {
65+
popSize = ex.framesToPop;
66+
} else if (reactMinifiedRegexp.test(ex.message)) {
67+
popSize = 1;
68+
}
69+
}
6070

6171
try {
6272
// This must be tried first because Opera 10 *destroys*

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

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,5 +352,98 @@ describe('Tracekit - Custom Tests', () => {
352352
},
353353
]);
354354
});
355+
356+
it('should correctly parse production errors and drop initial frame if its not relevant', () => {
357+
const REACT_PRODUCTION_ERROR = {
358+
message:
359+
'Minified React error #200; visit https://reactjs.org/docs/error-decoder.html?invariant=200 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.',
360+
name: 'Error',
361+
stack: `Error: Minified React error #200; visit https://reactjs.org/docs/error-decoder.html?invariant=200 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
362+
at http://localhost:5000/static/js/foo.chunk.js:1:21738
363+
at a (http://localhost:5000/static/js/foo.chunk.js:1:21841)
364+
at ho (http://localhost:5000/static/js/foo.chunk.js:1:68735)
365+
at f (http://localhost:5000/:1:980)`,
366+
};
367+
368+
const stacktrace = computeStackTrace(REACT_PRODUCTION_ERROR);
369+
370+
expect(stacktrace.stack).deep.equal([
371+
{
372+
args: [],
373+
column: 21738,
374+
func: '?',
375+
line: 1,
376+
url: 'http://localhost:5000/static/js/foo.chunk.js',
377+
},
378+
{
379+
args: [],
380+
column: 21841,
381+
func: 'a',
382+
line: 1,
383+
url: 'http://localhost:5000/static/js/foo.chunk.js',
384+
},
385+
{
386+
args: [],
387+
column: 68735,
388+
func: 'ho',
389+
line: 1,
390+
url: 'http://localhost:5000/static/js/foo.chunk.js',
391+
},
392+
{
393+
args: [],
394+
column: 980,
395+
func: 'f',
396+
line: 1,
397+
url: 'http://localhost:5000/',
398+
},
399+
]);
400+
});
401+
402+
it('should not drop additional frame for production errors if framesToPop is still there', () => {
403+
const REACT_PRODUCTION_ERROR = {
404+
framesToPop: 1,
405+
message:
406+
'Minified React error #200; visit https://reactjs.org/docs/error-decoder.html?invariant=200 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.',
407+
name: 'Error',
408+
stack: `Error: Minified React error #200; visit https://reactjs.org/docs/error-decoder.html?invariant=200 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
409+
at http://localhost:5000/static/js/foo.chunk.js:1:21738
410+
at a (http://localhost:5000/static/js/foo.chunk.js:1:21841)
411+
at ho (http://localhost:5000/static/js/foo.chunk.js:1:68735)
412+
at f (http://localhost:5000/:1:980)`,
413+
};
414+
415+
const stacktrace = computeStackTrace(REACT_PRODUCTION_ERROR);
416+
417+
expect(stacktrace.stack).deep.equal([
418+
{
419+
args: [],
420+
column: 21738,
421+
func: '?',
422+
line: 1,
423+
url: 'http://localhost:5000/static/js/foo.chunk.js',
424+
},
425+
{
426+
args: [],
427+
column: 21841,
428+
func: 'a',
429+
line: 1,
430+
url: 'http://localhost:5000/static/js/foo.chunk.js',
431+
},
432+
{
433+
args: [],
434+
column: 68735,
435+
func: 'ho',
436+
line: 1,
437+
url: 'http://localhost:5000/static/js/foo.chunk.js',
438+
},
439+
{
440+
args: [],
441+
column: 980,
442+
func: 'f',
443+
line: 1,
444+
url: 'http://localhost:5000/',
445+
},
446+
]);
447+
});
355448
});
356449
});

0 commit comments

Comments
 (0)