@@ -27,8 +27,11 @@ const {
2727const {
2828 pushAsyncContext,
2929 popAsyncContext,
30+ symbols : {
31+ async_id_symbol : kAsyncIdSymbol ,
32+ trigger_async_id_symbol : kTriggerAsyncIdSymbol
33+ }
3034} = require ( 'internal/async_hooks' ) ;
31- const async_hooks = require ( 'async_hooks' ) ;
3235const { isErrorStackTraceLimitWritable } = require ( 'internal/errors' ) ;
3336
3437// *Must* match Environment::TickInfo::Fields in src/env.h.
@@ -123,20 +126,11 @@ function resolveError(type, promise, reason) {
123126}
124127
125128function unhandledRejection ( promise , reason ) {
126- const asyncId = async_hooks . executionAsyncId ( ) ;
127- const triggerAsyncId = async_hooks . triggerAsyncId ( ) ;
128- const resource = promise ;
129-
130129 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 ) ;
139132 }
133+ return process . emit ( 'unhandledRejection' , reason , promise ) ;
140134 } ;
141135
142136 maybeUnhandledPromises . set ( promise , {
@@ -220,40 +214,73 @@ function processPromiseRejections() {
220214 promiseInfo . warned = true ;
221215 const { reason, uid, emit } = promiseInfo ;
222216
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 : {
244235 const err = reason instanceof Error ?
245236 reason : generateUnhandledRejectionError ( reason ) ;
237+ // This destroys the async stack, don't clear it after
246238 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 ;
247249 }
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 ) ;
253256 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 ) ;
255283 }
256- break ;
257284 }
258285 }
259286 maybeScheduledTicksOrMicrotasks = true ;
0 commit comments