From b6bbf0fd1658d6f0417022c050f7387f94019903 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Mar 2023 15:14:41 -0500 Subject: [PATCH 1/4] ref(utils): use test instead of indexof --- packages/utils/src/stacktrace.ts | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/packages/utils/src/stacktrace.ts b/packages/utils/src/stacktrace.ts index ccf18c64e897..93b62490a250 100644 --- a/packages/utils/src/stacktrace.ts +++ b/packages/utils/src/stacktrace.ts @@ -64,28 +64,31 @@ export function stripSentryFramesAndReverse(stack: StackFrame[]): StackFrame[] { let localStack = stack; - const firstFrameFunction = localStack[0].function || ''; - const lastFrameFunction = localStack[localStack.length - 1].function || ''; - - // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call) - if (firstFrameFunction.indexOf('captureMessage') !== -1 || firstFrameFunction.indexOf('captureException') !== -1) { - localStack = localStack.slice(1); + if (stack.length >= STACKTRACE_LIMIT) { + localStack.slice(0, STACKTRACE_LIMIT); } + const lastFrameFunction = localStack[localStack.length - 1].function; // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call) - if (lastFrameFunction.indexOf('sentryWrapped') !== -1) { - localStack = localStack.slice(0, -1); + if (lastFrameFunction && /sentryWrapped/.test(lastFrameFunction)) { + localStack.pop(); + } + + // Reversing in the middle of the procedure allows us to just pop the values off the stack + localStack = localStack.reverse(); + + const firstFrameFunction = localStack[localStack.length - 1].function; + // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call) + if (firstFrameFunction && /captureMessage|captureException/.test(firstFrameFunction)) { + localStack.pop(); } // The frame where the crash happened, should be the last entry in the array - return localStack - .slice(0, STACKTRACE_LIMIT) - .map(frame => ({ - ...frame, - filename: frame.filename || localStack[0].filename, - function: frame.function || '?', - })) - .reverse(); + return localStack.map(frame => ({ + ...frame, + filename: frame.filename || localStack[0].filename, + function: frame.function || '?', + })); } const defaultFunctionName = ''; From d0cafb526f14a579350e2c5c3c3caabab9e5e775 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Mar 2023 15:17:51 -0500 Subject: [PATCH 2/4] ref(utils): use readonly value so we dont mutate arguments --- packages/utils/src/stacktrace.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/packages/utils/src/stacktrace.ts b/packages/utils/src/stacktrace.ts index 93b62490a250..8a304001efc6 100644 --- a/packages/utils/src/stacktrace.ts +++ b/packages/utils/src/stacktrace.ts @@ -57,16 +57,12 @@ export function stackParserFromStackParserOptions(stackParser: StackParser | Sta /** * @hidden */ -export function stripSentryFramesAndReverse(stack: StackFrame[]): StackFrame[] { +export function stripSentryFramesAndReverse(stack: ReadonlyArray): StackFrame[] { if (!stack.length) { return []; } - let localStack = stack; - - if (stack.length >= STACKTRACE_LIMIT) { - localStack.slice(0, STACKTRACE_LIMIT); - } + let localStack = stack.slice(0, STACKTRACE_LIMIT); const lastFrameFunction = localStack[localStack.length - 1].function; // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call) From d59a812211e876cdcbddafdac0cc620cc8ed436a Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Mar 2023 15:28:10 -0500 Subject: [PATCH 3/4] ref(utils): add stripSentryFramesAndReverse comment --- packages/utils/src/stacktrace.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/utils/src/stacktrace.ts b/packages/utils/src/stacktrace.ts index 8a304001efc6..5a1477485d62 100644 --- a/packages/utils/src/stacktrace.ts +++ b/packages/utils/src/stacktrace.ts @@ -55,6 +55,9 @@ export function stackParserFromStackParserOptions(stackParser: StackParser | Sta } /** + * Removes Sentry frames from the top and bottom of the stack if present and enforces a limit of max number of frames. + * Assumes stack input is ordered from top to bottom and returns the reverse representation so call site of the + * function that caused the crash is the last frame in the array. * @hidden */ export function stripSentryFramesAndReverse(stack: ReadonlyArray): StackFrame[] { @@ -79,7 +82,6 @@ export function stripSentryFramesAndReverse(stack: ReadonlyArray): S localStack.pop(); } - // The frame where the crash happened, should be the last entry in the array return localStack.map(frame => ({ ...frame, filename: frame.filename || localStack[0].filename, From e4e9db23ad20d1880ad4963ba34c05c47c07db38 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Mar 2023 17:52:30 -0500 Subject: [PATCH 4/4] test(utils): test fallback to last --- packages/utils/src/stacktrace.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/utils/src/stacktrace.ts b/packages/utils/src/stacktrace.ts index 5a1477485d62..e1a221444eb6 100644 --- a/packages/utils/src/stacktrace.ts +++ b/packages/utils/src/stacktrace.ts @@ -65,26 +65,26 @@ export function stripSentryFramesAndReverse(stack: ReadonlyArray): S return []; } - let localStack = stack.slice(0, STACKTRACE_LIMIT); + const localStack = stack.slice(0, STACKTRACE_LIMIT); const lastFrameFunction = localStack[localStack.length - 1].function; - // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call) + // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call) if (lastFrameFunction && /sentryWrapped/.test(lastFrameFunction)) { localStack.pop(); } // Reversing in the middle of the procedure allows us to just pop the values off the stack - localStack = localStack.reverse(); + localStack.reverse(); const firstFrameFunction = localStack[localStack.length - 1].function; - // If stack starts with one of our API calls, remove it (starts, meaning it's the top of the stack - aka last call) + // If stack ends with one of our internal API calls, remove it (ends, meaning it's the bottom of the stack - aka top-most call) if (firstFrameFunction && /captureMessage|captureException/.test(firstFrameFunction)) { localStack.pop(); } return localStack.map(frame => ({ ...frame, - filename: frame.filename || localStack[0].filename, + filename: frame.filename || localStack[localStack.length - 1].filename, function: frame.function || '?', })); }