-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
fix(wasm): Fix wasm integration stacktrace parsing for filename #15572
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -41,15 +41,27 @@ | |
* if applicable. Returns true if the provided list of stack frames had at least one | ||
* matching registered image. | ||
*/ | ||
function patchFrames(frames: Array<StackFrame>): boolean { | ||
// Only exported for tests | ||
export function patchFrames(frames: Array<StackFrame>): boolean { | ||
let hasAtLeastOneWasmFrameWithImage = false; | ||
frames.forEach(frame => { | ||
if (!frame.filename) { | ||
return; | ||
} | ||
const match = frame.filename.match(/^(.*?):wasm-function\[\d+\]:(0x[a-fA-F0-9]+)$/) as | ||
|
||
// I will call this first match a "messy match". | ||
// The browser stacktrace parser spits out frames that have a filename like this: "int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb" | ||
// It contains some leftover mess because wasm stackframes are more complicated than our parser can handle: "at MyClass::bar(int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb)" | ||
// This first match simply tries to mitigate the mess up until the first opening parens. | ||
// The match afterwards is a sensible fallback | ||
let match = frame.filename.match(/^.*\((.*?):wasm-function\[\d+\]:(0x[a-fA-F0-9]+)$/) as | ||
| null | ||
| [string, string, string]; | ||
|
||
if (!match) { | ||
match = frame.filename.match(/^(.*?):wasm-function\[\d+\]:(0x[a-fA-F0-9]+)$/) as null | [string, string, string]; | ||
} | ||
|
||
if (match) { | ||
const index = getImage(match[1]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could check the length of the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If there is a match it is 100% guaranteed to have 3 entries so I don't think it would matter and it saves bundle size. |
||
frame.instruction_addr = match[2]; | ||
|
@@ -62,5 +74,6 @@ | |
} | ||
} | ||
}); | ||
|
||
return hasAtLeastOneWasmFrameWithImage; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
import { describe, it, expect } from 'vitest'; | ||
import { patchFrames } from '../src/index'; | ||
|
||
describe('patchFrames()', () => { | ||
it('should correctly extract instruction addresses', () => { | ||
const frames = [ | ||
{ | ||
colno: 5, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'run', | ||
in_app: true, | ||
lineno: 7101, | ||
}, | ||
{ | ||
colno: 71, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'doRun', | ||
in_app: true, | ||
lineno: 7084, | ||
}, | ||
{ | ||
colno: 9, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'Object.onRuntimeInitialized', | ||
in_app: true, | ||
lineno: 39, | ||
}, | ||
{ | ||
colno: 11, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'captureError', | ||
in_app: true, | ||
lineno: 27, | ||
}, | ||
{ | ||
colno: 22, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'myFunctionVectorOutOfBounds', | ||
in_app: true, | ||
lineno: 18, | ||
}, | ||
{ | ||
colno: 27, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'ClassHandle.MyClass$getAt [as getAt]', | ||
in_app: true, | ||
lineno: 2201, | ||
}, | ||
{ | ||
filename: | ||
'int) const, int, MyClass const*, int>::invoke(int (MyClass::* const&)(int) const, MyClass const*, int) (http://localhost:8001/main.wasm:wasm-function[152]:0x47df', | ||
function: 'emscripten::internal::MethodInvoker<int (MyClass::*)', | ||
in_app: true, | ||
}, | ||
{ | ||
filename: 'int) const (http://localhost:8001/main.wasm:wasm-function[182]:0x540b', | ||
function: 'MyClass::getAt', | ||
in_app: true, | ||
}, | ||
{ | ||
filename: 'int) const (http://localhost:8001/main.wasm:wasm-function[186]:0x5637', | ||
function: 'MyClass::foo', | ||
in_app: true, | ||
}, | ||
{ | ||
filename: 'int) const (http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb', | ||
function: 'MyClass::bar', | ||
in_app: true, | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm:wasm-function[190]:0x5aeb', | ||
function: 'MyClass::bar', | ||
in_app: true, | ||
}, | ||
]; | ||
|
||
patchFrames(frames); | ||
|
||
expect(frames).toStrictEqual([ | ||
{ | ||
colno: 5, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'run', | ||
in_app: true, | ||
lineno: 7101, | ||
}, | ||
{ | ||
colno: 71, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'doRun', | ||
in_app: true, | ||
lineno: 7084, | ||
}, | ||
{ | ||
colno: 9, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'Object.onRuntimeInitialized', | ||
in_app: true, | ||
lineno: 39, | ||
}, | ||
{ | ||
colno: 11, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'captureError', | ||
in_app: true, | ||
lineno: 27, | ||
}, | ||
{ | ||
colno: 22, | ||
filename: 'http://localhost:8001/main.html', | ||
function: 'myFunctionVectorOutOfBounds', | ||
in_app: true, | ||
lineno: 18, | ||
}, | ||
{ | ||
colno: 27, | ||
filename: 'http://localhost:8001/main.js', | ||
function: 'ClassHandle.MyClass$getAt [as getAt]', | ||
in_app: true, | ||
lineno: 2201, | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm', | ||
function: 'emscripten::internal::MethodInvoker<int (MyClass::*)', | ||
in_app: true, | ||
instruction_addr: '0x47df', | ||
platform: 'native', | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm', | ||
function: 'MyClass::getAt', | ||
in_app: true, | ||
instruction_addr: '0x540b', | ||
platform: 'native', | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm', | ||
function: 'MyClass::foo', | ||
in_app: true, | ||
instruction_addr: '0x5637', | ||
platform: 'native', | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm', | ||
function: 'MyClass::bar', | ||
in_app: true, | ||
instruction_addr: '0x5aeb', | ||
platform: 'native', | ||
}, | ||
{ | ||
filename: 'http://localhost:8001/main.wasm', | ||
function: 'MyClass::bar', | ||
in_app: true, | ||
instruction_addr: '0x5aeb', | ||
platform: 'native', | ||
}, | ||
]); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"extends": "../tsconfig.test.json" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"extends": "./tsconfig.json", | ||
"include": ["test/**/*", "vite.config.ts"], | ||
"compilerOptions": { | ||
"types": ["node"], | ||
"lib": ["DOM", "ESNext"] | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import baseConfig from '../../vite/vite.config'; | ||
|
||
export default { | ||
...baseConfig, | ||
test: { | ||
...baseConfig.test, | ||
}, | ||
}; |
Uh oh!
There was an error while loading. Please reload this page.