@@ -27,8 +27,11 @@ const {
27
27
const {
28
28
pushAsyncContext,
29
29
popAsyncContext,
30
+ symbols : {
31
+ async_id_symbol : kAsyncIdSymbol ,
32
+ trigger_async_id_symbol : kTriggerAsyncIdSymbol
33
+ }
30
34
} = require ( 'internal/async_hooks' ) ;
31
- const async_hooks = require ( 'async_hooks' ) ;
32
35
const { isErrorStackTraceLimitWritable } = require ( 'internal/errors' ) ;
33
36
34
37
// *Must* match Environment::TickInfo::Fields in src/env.h.
@@ -123,20 +126,11 @@ function resolveError(type, promise, reason) {
123
126
}
124
127
125
128
function unhandledRejection ( promise , reason ) {
126
- const asyncId = async_hooks . executionAsyncId ( ) ;
127
- const triggerAsyncId = async_hooks . triggerAsyncId ( ) ;
128
- const resource = promise ;
129
-
130
129
const emit = ( reason , promise , promiseInfo ) => {
131
- try {
132
- pushAsyncContext ( asyncId , triggerAsyncId , resource ) ;
133
- if ( promiseInfo . domain ) {
134
- return promiseInfo . domain . emit ( 'error' , reason ) ;
135
- }
136
- return process . emit ( 'unhandledRejection' , reason , promise ) ;
137
- } finally {
138
- popAsyncContext ( asyncId ) ;
130
+ if ( promiseInfo . domain ) {
131
+ return promiseInfo . domain . emit ( 'error' , reason ) ;
139
132
}
133
+ return process . emit ( 'unhandledRejection' , reason , promise ) ;
140
134
} ;
141
135
142
136
maybeUnhandledPromises . set ( promise , {
@@ -220,40 +214,73 @@ function processPromiseRejections() {
220
214
promiseInfo . warned = true ;
221
215
const { reason, uid, emit } = promiseInfo ;
222
216
223
- switch ( unhandledRejectionsMode ) {
224
- case kStrictUnhandledRejections : {
225
- const err = reason instanceof Error ?
226
- reason : generateUnhandledRejectionError ( reason ) ;
227
- triggerUncaughtException ( err , true /* fromPromise */ ) ;
228
- const handled = emit ( reason , promise , promiseInfo ) ;
229
- if ( ! handled ) emitUnhandledRejectionWarning ( uid , reason ) ;
230
- break ;
231
- }
232
- case kIgnoreUnhandledRejections : {
233
- emit ( reason , promise , promiseInfo ) ;
234
- break ;
235
- }
236
- case kAlwaysWarnUnhandledRejections : {
237
- emit ( reason , promise , promiseInfo ) ;
238
- emitUnhandledRejectionWarning ( uid , reason ) ;
239
- break ;
240
- }
241
- case kThrowUnhandledRejections : {
242
- const handled = emit ( reason , promise , promiseInfo ) ;
243
- if ( ! handled ) {
217
+ let needPop = true ;
218
+ const {
219
+ [ kAsyncIdSymbol ] : promiseAsyncId ,
220
+ [ kTriggerAsyncIdSymbol ] : promiseTriggerAsyncId ,
221
+ } = promise ;
222
+ // We need to check if async_hooks are enabled
223
+ // don't use enabledHooksExist as a Promise could
224
+ // come from a vm.* context and not have an async id
225
+ if ( typeof promiseAsyncId !== 'undefined' ) {
226
+ pushAsyncContext (
227
+ promiseAsyncId ,
228
+ promiseTriggerAsyncId ,
229
+ promise
230
+ ) ;
231
+ }
232
+ try {
233
+ switch ( unhandledRejectionsMode ) {
234
+ case kStrictUnhandledRejections : {
244
235
const err = reason instanceof Error ?
245
236
reason : generateUnhandledRejectionError ( reason ) ;
237
+ // This destroys the async stack, don't clear it after
246
238
triggerUncaughtException ( err , true /* fromPromise */ ) ;
239
+ if ( typeof promiseAsyncId !== 'undefined' ) {
240
+ pushAsyncContext (
241
+ promise [ kAsyncIdSymbol ] ,
242
+ promise [ kTriggerAsyncIdSymbol ] ,
243
+ promise
244
+ ) ;
245
+ }
246
+ const handled = emit ( reason , promise , promiseInfo ) ;
247
+ if ( ! handled ) emitUnhandledRejectionWarning ( uid , reason ) ;
248
+ break ;
247
249
}
248
- break ;
249
- }
250
- case kWarnWithErrorCodeUnhandledRejections : {
251
- const handled = emit ( reason , promise , promiseInfo ) ;
252
- if ( ! handled ) {
250
+ case kIgnoreUnhandledRejections : {
251
+ emit ( reason , promise , promiseInfo ) ;
252
+ break ;
253
+ }
254
+ case kAlwaysWarnUnhandledRejections : {
255
+ emit ( reason , promise , promiseInfo ) ;
253
256
emitUnhandledRejectionWarning ( uid , reason ) ;
254
- process . exitCode = 1 ;
257
+ break ;
258
+ }
259
+ case kThrowUnhandledRejections : {
260
+ const handled = emit ( reason , promise , promiseInfo ) ;
261
+ if ( ! handled ) {
262
+ const err = reason instanceof Error ?
263
+ reason : generateUnhandledRejectionError ( reason ) ;
264
+ // This destroys the async stack, don't clear it after
265
+ triggerUncaughtException ( err , true /* fromPromise */ ) ;
266
+ needPop = false ;
267
+ }
268
+ break ;
269
+ }
270
+ case kWarnWithErrorCodeUnhandledRejections : {
271
+ const handled = emit ( reason , promise , promiseInfo ) ;
272
+ if ( ! handled ) {
273
+ emitUnhandledRejectionWarning ( uid , reason ) ;
274
+ process . exitCode = 1 ;
275
+ }
276
+ break ;
277
+ }
278
+ }
279
+ } finally {
280
+ if ( needPop ) {
281
+ if ( typeof promiseAsyncId !== 'undefined' ) {
282
+ popAsyncContext ( promiseAsyncId ) ;
255
283
}
256
- break ;
257
284
}
258
285
}
259
286
maybeScheduledTicksOrMicrotasks = true ;
0 commit comments