88 FunctionPrototypeBind,
99 ObjectPrototypeHasOwnProperty,
1010 ObjectDefineProperty,
11- Promise,
1211 ReflectApply,
1312 Symbol,
1413} = primordials ;
@@ -57,7 +56,7 @@ const {
5756 clearAsyncIdStack,
5857} = async_wrap ;
5958// For performance reasons, only track Promises when a hook is enabled.
60- const { enablePromiseHook, disablePromiseHook } = async_wrap ;
59+ const { enablePromiseHook, disablePromiseHook, setPromiseHooks } = async_wrap ;
6160// Properties in active_hooks are used to keep track of the set of hooks being
6261// executed in case another hook is enabled/disabled. The new set of hooks is
6362// then restored once the active set of hooks is finished executing.
@@ -306,71 +305,68 @@ function restoreActiveHooks() {
306305 active_hooks . tmp_fields = null ;
307306}
308307
309- function trackPromise ( promise , parent , silent ) {
310- const asyncId = getOrSetAsyncId ( promise ) ;
308+ function trackPromise ( promise , parent ) {
309+ if ( promise [ async_id_symbol ] ) {
310+ return ;
311+ }
311312
313+ promise [ async_id_symbol ] = newAsyncId ( ) ;
312314 promise [ trigger_async_id_symbol ] = parent ? getOrSetAsyncId ( parent ) :
313315 getDefaultTriggerAsyncId ( ) ;
316+ }
314317
315- if ( ! silent && initHooksExist ( ) ) {
316- const triggerId = promise [ trigger_async_id_symbol ] ;
317- emitInitScript ( asyncId , 'PROMISE' , triggerId , promise ) ;
318- }
318+ function promiseInitHook ( promise , parent ) {
319+ trackPromise ( promise , parent ) ;
320+ const asyncId = promise [ async_id_symbol ] ;
321+ const triggerAsyncId = promise [ trigger_async_id_symbol ] ;
322+ emitInitScript ( asyncId , 'PROMISE' , triggerAsyncId , promise ) ;
319323}
320324
321- function fastPromiseHook ( type , promise , parent ) {
322- if ( type === kInit || ! promise [ async_id_symbol ] ) {
323- const silent = type !== kInit ;
324- if ( parent instanceof Promise ) {
325- trackPromise ( promise , parent , silent ) ;
326- } else {
327- trackPromise ( promise , null , silent ) ;
328- }
325+ function promiseBeforeHook ( promise ) {
326+ trackPromise ( promise ) ;
327+ const asyncId = promise [ async_id_symbol ] ;
328+ const triggerId = promise [ trigger_async_id_symbol ] ;
329+ emitBeforeScript ( asyncId , triggerId , promise ) ;
330+ }
329331
330- if ( ! silent ) return ;
332+ function promiseAfterHook ( promise ) {
333+ trackPromise ( promise ) ;
334+ const asyncId = promise [ async_id_symbol ] ;
335+ if ( hasHooks ( kAfter ) ) {
336+ emitAfterNative ( asyncId ) ;
331337 }
338+ if ( asyncId === executionAsyncId ( ) ) {
339+ // This condition might not be true if async_hooks was enabled during
340+ // the promise callback execution.
341+ // Popping it off the stack can be skipped in that case, because it is
342+ // known that it would correspond to exactly one call with
343+ // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
344+ popAsyncContext ( asyncId ) ;
345+ }
346+ }
332347
348+ function promiseResolveHook ( promise ) {
349+ trackPromise ( promise ) ;
333350 const asyncId = promise [ async_id_symbol ] ;
334- switch ( type ) {
335- case kBefore :
336- const triggerId = promise [ trigger_async_id_symbol ] ;
337- emitBeforeScript ( asyncId , triggerId , promise ) ;
338- break ;
339- case kAfter :
340- if ( hasHooks ( kAfter ) ) {
341- emitAfterNative ( asyncId ) ;
342- }
343- if ( asyncId === executionAsyncId ( ) ) {
344- // This condition might not be true if async_hooks was enabled during
345- // the promise callback execution.
346- // Popping it off the stack can be skipped in that case, because it is
347- // known that it would correspond to exactly one call with
348- // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
349- popAsyncContext ( asyncId ) ;
350- }
351- break ;
352- case kPromiseResolve :
353- emitPromiseResolveNative ( asyncId ) ;
354- break ;
355- }
351+ emitPromiseResolveNative ( asyncId ) ;
356352}
357353
358354let wantPromiseHook = false ;
359355function enableHooks ( ) {
360356 async_hook_fields [ kCheck ] += 1 ;
361357}
362358
363- let promiseHookMode = - 1 ;
364359function updatePromiseHookMode ( ) {
365360 wantPromiseHook = true ;
366361 if ( destroyHooksExist ( ) ) {
367- if ( promiseHookMode !== 1 ) {
368- promiseHookMode = 1 ;
369- enablePromiseHook ( ) ;
370- }
371- } else if ( promiseHookMode !== 0 ) {
372- promiseHookMode = 0 ;
373- enablePromiseHook ( fastPromiseHook ) ;
362+ enablePromiseHook ( ) ;
363+ } else {
364+ setPromiseHooks (
365+ initHooksExist ( ) ? promiseInitHook : undefined ,
366+ promiseBeforeHook ,
367+ promiseAfterHook ,
368+ promiseResolveHooksExist ( ) ? promiseResolveHook : undefined ,
369+ ) ;
374370 }
375371}
376372
@@ -386,8 +382,8 @@ function disableHooks() {
386382
387383function disablePromiseHookIfNecessary ( ) {
388384 if ( ! wantPromiseHook ) {
389- promiseHookMode = - 1 ;
390385 disablePromiseHook ( ) ;
386+ setPromiseHooks ( undefined , undefined , undefined , undefined ) ;
391387 }
392388}
393389
@@ -461,6 +457,10 @@ function destroyHooksExist() {
461457 return hasHooks ( kDestroy ) ;
462458}
463459
460+ function promiseResolveHooksExist ( ) {
461+ return hasHooks ( kPromiseResolve ) ;
462+ }
463+
464464
465465function emitInitScript ( asyncId , type , triggerAsyncId , resource ) {
466466 // Short circuit all checks for the common case. Which is that no hooks have
0 commit comments