From ee4a90162a965fcd1a537ab8c8e5880d917abde5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Thu, 9 May 2019 14:02:52 +0200 Subject: [PATCH 1/3] fix: Use 'native code' as a filename for some frames --- packages/browser/src/tracekit.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/browser/src/tracekit.ts b/packages/browser/src/tracekit.ts index cf3445c09468..a9a922a3952a 100644 --- a/packages/browser/src/tracekit.ts +++ b/packages/browser/src/tracekit.ts @@ -492,19 +492,17 @@ TraceKit._computeStackTrace = (function _computeStackTraceWrapper() { for (var i = 0, j = lines.length; i < j; ++i) { if ((parts = chrome.exec(lines[i]))) { - var isNative = parts[2] && parts[2].indexOf('native') === 0; // start of line isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line if (isEval && (submatch = chromeEval.exec(parts[2]))) { // throw out eval line/column and use top-most line/column number parts[2] = submatch[1]; // url - // NOTE: It's messing out our integration tests in Karma, let's see if we can live with it – Kamil - // parts[3] = submatch[2]; // line - // parts[4] = submatch[3]; // column + parts[3] = submatch[2]; // line + parts[4] = submatch[3]; // column } element = { - url: !isNative ? parts[2] : null, + url: parts[2], func: parts[1] || UNKNOWN_FUNCTION, - args: isNative ? [parts[2]] : [], + args: [], line: parts[3] ? +parts[3] : null, column: parts[4] ? +parts[4] : null, }; @@ -521,9 +519,8 @@ TraceKit._computeStackTrace = (function _computeStackTraceWrapper() { if (isEval && (submatch = geckoEval.exec(parts[3]))) { // throw out eval line/column and use top-most line number parts[3] = submatch[1]; - // NOTE: It's messing out our integration tests in Karma, let's see if we can live with it – Kamil - // parts[4] = submatch[2]; - // parts[5] = null; // no column when eval + parts[4] = submatch[2]; + parts[5] = ''; // no column when eval } else if (i === 0 && !parts[5] && ex.columnNumber !== void 0) { // FireFox uses this awesome columnNumber property for its top frame // Also note, Firefox's column number is 0-based and everything else expects 1-based, From 77640d387728834eb5dab9cfc29b427f4afd4558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Thu, 9 May 2019 14:40:07 +0200 Subject: [PATCH 2/3] test: Add tests for computeStackTrace native frames --- packages/browser/src/tracekit.ts | 3 +- packages/browser/test/tracekit.test.ts | 194 +++++++++++++++++++++++++ 2 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 packages/browser/test/tracekit.test.ts diff --git a/packages/browser/src/tracekit.ts b/packages/browser/src/tracekit.ts index a9a922a3952a..335226824950 100644 --- a/packages/browser/src/tracekit.ts +++ b/packages/browser/src/tracekit.ts @@ -38,6 +38,7 @@ interface ComputeStackTrace { * @param {(string|number)=} depth */ (ex: Error, depth?: string | number): StackTrace; + _computeStackTraceFromStackProp(ex: any): StackTrace; } /** @@ -469,7 +470,7 @@ TraceKit._computeStackTrace = (function _computeStackTraceWrapper() { * @memberof TraceKit._computeStackTrace */ function _computeStackTraceFromStackProp(ex: any) { - if (!ex.stack) { + if (!ex || !ex.stack) { return null; } diff --git a/packages/browser/test/tracekit.test.ts b/packages/browser/test/tracekit.test.ts new file mode 100644 index 000000000000..970e8f8464eb --- /dev/null +++ b/packages/browser/test/tracekit.test.ts @@ -0,0 +1,194 @@ +import { expect } from 'chai'; + +import { _computeStackTrace } from '../src/tracekit'; + +const CHROME73_NATIVE_CODE_EXCEPTION = { + stack: `Error: test + at fooIterator (http://192.168.20.143:5000/test:20:17) + at Array.map () + at foo (http://192.168.20.143:5000/test:19:19) + at http://192.168.20.143:5000/test:24:7`, +}; + +const FIREFOX66_NATIVE_CODE_EXCEPTION = { + stack: `fooIterator@http://192.168.20.143:5000/test:20:17 + foo@http://192.168.20.143:5000/test:19:19 + @http://192.168.20.143:5000/test:24:7`, +}; + +const SAFARI12_NATIVE_CODE_EXCEPTION = { + stack: `fooIterator@http://192.168.20.143:5000/test:20:26 + map@[native code] + foo@http://192.168.20.143:5000/test:19:22 + global code@http://192.168.20.143:5000/test:24:10`, +}; + +const EDGE44_NATIVE_CODE_EXCEPTION = { + stack: `Error: test + at fooIterator (http://192.168.20.143:5000/test:20:11) + at Array.prototype.map (native code) + at foo (http://192.168.20.143:5000/test:19:9) + at Global code (http://192.168.20.143:5000/test:24:7)`, +}; + +describe('Tracekit', () => { + describe('computeStackTrace', () => { + it('no exception', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp(undefined); + expect(stacktrace).equal(null); + }); + + it('no stack', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp({}); + expect(stacktrace).equal(null); + }); + + it('chrome73', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp(CHROME73_NATIVE_CODE_EXCEPTION); + + expect(stacktrace.stack).deep.equal([ + { + args: [], + column: 17, + context: null, + func: 'fooIterator', + line: 20, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: null, + context: null, + func: 'Array.map', + line: null, + url: '', + }, + { + args: [], + column: 19, + context: null, + func: 'foo', + line: 19, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: 7, + context: null, + func: '?', + line: 24, + url: 'http://192.168.20.143:5000/test', + }, + ]); + }); + + it('firefox66', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp(FIREFOX66_NATIVE_CODE_EXCEPTION); + + expect(stacktrace.stack).deep.equal([ + { + args: [], + column: 17, + context: null, + func: 'fooIterator', + line: 20, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: 19, + context: null, + func: 'foo', + line: 19, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: 7, + context: null, + func: '?', + line: 24, + url: 'http://192.168.20.143:5000/test', + }, + ]); + }); + + it('safari12', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp(SAFARI12_NATIVE_CODE_EXCEPTION); + + expect(stacktrace.stack).deep.equal([ + { + args: [], + column: 26, + context: null, + func: 'fooIterator', + line: 20, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: null, + context: null, + func: 'map', + line: null, + url: '[native code]', + }, + { + args: [], + column: 22, + context: null, + func: 'foo', + line: 19, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: 10, + context: null, + func: 'global code', + line: 24, + url: 'http://192.168.20.143:5000/test', + }, + ]); + }); + + it('edge44', () => { + const stacktrace = _computeStackTrace._computeStackTraceFromStackProp(EDGE44_NATIVE_CODE_EXCEPTION); + + expect(stacktrace.stack).deep.equal([ + { + args: [], + column: 11, + context: null, + func: 'fooIterator', + line: 20, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: null, + context: null, + func: 'Array.prototype.map', + line: null, + url: 'native code', + }, + { + args: [], + column: 9, + context: null, + func: 'foo', + line: 19, + url: 'http://192.168.20.143:5000/test', + }, + { + args: [], + column: 7, + context: null, + func: 'Global code', + line: 24, + url: 'http://192.168.20.143:5000/test', + }, + ]); + }); + }); +}); From ae26a161dcc6aa61b124b562c4310b372ca85a08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Og=C3=B3rek?= Date: Thu, 9 May 2019 15:57:35 +0200 Subject: [PATCH 3/3] misc: Note regarding Tracekit Chromium browsers --- packages/browser/src/tracekit.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/browser/src/tracekit.ts b/packages/browser/src/tracekit.ts index 335226824950..4750cbc5cad2 100644 --- a/packages/browser/src/tracekit.ts +++ b/packages/browser/src/tracekit.ts @@ -474,6 +474,7 @@ TraceKit._computeStackTrace = (function _computeStackTraceWrapper() { return null; } + // Chromium based browsers: Chrome, Brave, new Opera, new Edge var chrome = /^\s*at (?:(.*?) ?\()?((?:file|https?|blob|chrome-extension|native|eval|webpack||[a-z]:|\/).*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i, // gecko regex: `(?:bundle|\d+\.js)`: `bundle` is for react native, `\d+\.js` also but specifically for ram bundles because it // generates filenames without a prefix like `file://` the filenames in the stacktrace are just 42.js