1
1
import type { Debugger , InspectorNotification , Runtime } from 'node:inspector' ;
2
2
import { Session } from 'node:inspector/promises' ;
3
3
import { parentPort , workerData } from 'node:worker_threads' ;
4
- import type { StackParser } from '@sentry/types' ;
4
+ import type { StackFrame , StackParser } from '@sentry/types' ;
5
5
import { createStackParser , nodeStackLineParser } from '@sentry/utils' ;
6
6
import { createGetModuleFromFilename } from '../../utils/module' ;
7
7
import type { LocalVariablesWorkerArgs , PausedExceptionEvent , RateLimitIncrement , Variables } from './common' ;
8
- import { createRateLimiter , hashFromStack } from './common' ;
8
+ import { createRateLimiter , functionNamesMatch , hashFromStack } from './common' ;
9
9
10
10
const options : LocalVariablesWorkerArgs = workerData ;
11
11
@@ -104,9 +104,24 @@ async function handlePaused(
104
104
return ;
105
105
}
106
106
107
+ const originalErrorStackFrames : StackFrame [ ] = stackParser (
108
+ data . description ,
109
+ ) . filter ( ( frame ) => frame . function !== 'new Promise' ) ;
110
+
111
+ // Debugger frames being longer than the originalErrorStackFrames means they definitely dont match
112
+ // Debugger callFrames don't include anything beyond an async boundary, so they should be SHORTER or equal to the full error stack
113
+ // If they are longer, we are in a re-throw and we should stop to avoid overriding the error's detected vars from the original throw
114
+ if ( callFrames . length > originalErrorStackFrames . length ) {
115
+ return ;
116
+ }
117
+
107
118
const frames = [ ] ;
108
119
109
120
for ( let i = 0 ; i < callFrames . length ; i ++ ) {
121
+ // sentry frames are in reverse order
122
+ const originalErrorStackFramesIndex =
123
+ originalErrorStackFrames . length - 1 - i ;
124
+
110
125
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
111
126
const { scopeChain, functionName, this : obj } = callFrames [ i ] ! ;
112
127
@@ -115,6 +130,14 @@ async function handlePaused(
115
130
// obj.className is undefined in ESM modules
116
131
const fn = obj . className === 'global' || ! obj . className ? functionName : `${ obj . className } .${ functionName } ` ;
117
132
133
+ if (
134
+ ! functionNamesMatch ( fn , originalErrorStackFrames [ originalErrorStackFramesIndex ] ?. function )
135
+ ) {
136
+ // If at any point we encounter a function name that doesn't match the original error stack, we stop
137
+ // this means we are in a re-throw and we don't want to override the error's detected vars from the original throw
138
+ return ;
139
+ }
140
+
118
141
if ( localScope ?. object . objectId === undefined ) {
119
142
frames [ i ] = { function : fn } ;
120
143
} else {
0 commit comments