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.
@@ -298,71 +297,68 @@ function restoreActiveHooks() {
298297 active_hooks . tmp_fields = null ;
299298}
300299
301- function trackPromise ( promise , parent , silent ) {
302- const asyncId = getOrSetAsyncId ( promise ) ;
300+ function trackPromise ( promise , parent ) {
301+ if ( promise [ async_id_symbol ] ) {
302+ return ;
303+ }
303304
305+ promise [ async_id_symbol ] = newAsyncId ( ) ;
304306 promise [ trigger_async_id_symbol ] = parent ? getOrSetAsyncId ( parent ) :
305307 getDefaultTriggerAsyncId ( ) ;
308+ }
306309
307- if ( ! silent && initHooksExist ( ) ) {
308- const triggerId = promise [ trigger_async_id_symbol ] ;
309- emitInitScript ( asyncId , 'PROMISE' , triggerId , promise ) ;
310- }
310+ function promiseInitHook ( promise , parent ) {
311+ trackPromise ( promise , parent ) ;
312+ const asyncId = promise [ async_id_symbol ] ;
313+ const triggerAsyncId = promise [ trigger_async_id_symbol ] ;
314+ emitInitScript ( asyncId , 'PROMISE' , triggerAsyncId , promise ) ;
311315}
312316
313- function fastPromiseHook ( type , promise , parent ) {
314- if ( type === kInit || ! promise [ async_id_symbol ] ) {
315- const silent = type !== kInit ;
316- if ( parent instanceof Promise ) {
317- trackPromise ( promise , parent , silent ) ;
318- } else {
319- trackPromise ( promise , null , silent ) ;
320- }
317+ function promiseBeforeHook ( promise ) {
318+ trackPromise ( promise ) ;
319+ const asyncId = promise [ async_id_symbol ] ;
320+ const triggerId = promise [ trigger_async_id_symbol ] ;
321+ emitBeforeScript ( asyncId , triggerId , promise ) ;
322+ }
321323
322- if ( ! silent ) return ;
324+ function promiseAfterHook ( promise ) {
325+ trackPromise ( promise ) ;
326+ const asyncId = promise [ async_id_symbol ] ;
327+ if ( hasHooks ( kAfter ) ) {
328+ emitAfterNative ( asyncId ) ;
323329 }
330+ if ( asyncId === executionAsyncId ( ) ) {
331+ // This condition might not be true if async_hooks was enabled during
332+ // the promise callback execution.
333+ // Popping it off the stack can be skipped in that case, because it is
334+ // known that it would correspond to exactly one call with
335+ // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
336+ popAsyncContext ( asyncId ) ;
337+ }
338+ }
324339
340+ function promiseResolveHook ( promise ) {
341+ trackPromise ( promise ) ;
325342 const asyncId = promise [ async_id_symbol ] ;
326- switch ( type ) {
327- case kBefore :
328- const triggerId = promise [ trigger_async_id_symbol ] ;
329- emitBeforeScript ( asyncId , triggerId , promise ) ;
330- break ;
331- case kAfter :
332- if ( hasHooks ( kAfter ) ) {
333- emitAfterNative ( asyncId ) ;
334- }
335- if ( asyncId === executionAsyncId ( ) ) {
336- // This condition might not be true if async_hooks was enabled during
337- // the promise callback execution.
338- // Popping it off the stack can be skipped in that case, because it is
339- // known that it would correspond to exactly one call with
340- // PromiseHookType::kBefore that was not witnessed by the PromiseHook.
341- popAsyncContext ( asyncId ) ;
342- }
343- break ;
344- case kPromiseResolve :
345- emitPromiseResolveNative ( asyncId ) ;
346- break ;
347- }
343+ emitPromiseResolveNative ( asyncId ) ;
348344}
349345
350346let wantPromiseHook = false ;
351347function enableHooks ( ) {
352348 async_hook_fields [ kCheck ] += 1 ;
353349}
354350
355- let promiseHookMode = - 1 ;
356351function updatePromiseHookMode ( ) {
357352 wantPromiseHook = true ;
358353 if ( destroyHooksExist ( ) ) {
359- if ( promiseHookMode !== 1 ) {
360- promiseHookMode = 1 ;
361- enablePromiseHook ( ) ;
362- }
363- } else if ( promiseHookMode !== 0 ) {
364- promiseHookMode = 0 ;
365- enablePromiseHook ( fastPromiseHook ) ;
354+ enablePromiseHook ( ) ;
355+ } else {
356+ setPromiseHooks (
357+ initHooksExist ( ) ? promiseInitHook : undefined ,
358+ promiseBeforeHook ,
359+ promiseAfterHook ,
360+ promiseResolveHooksExist ( ) ? promiseResolveHook : undefined ,
361+ ) ;
366362 }
367363}
368364
@@ -378,8 +374,8 @@ function disableHooks() {
378374
379375function disablePromiseHookIfNecessary ( ) {
380376 if ( ! wantPromiseHook ) {
381- promiseHookMode = - 1 ;
382377 disablePromiseHook ( ) ;
378+ setPromiseHooks ( undefined , undefined , undefined , undefined ) ;
383379 }
384380}
385381
@@ -453,6 +449,10 @@ function destroyHooksExist() {
453449 return hasHooks ( kDestroy ) ;
454450}
455451
452+ function promiseResolveHooksExist ( ) {
453+ return hasHooks ( kPromiseResolve ) ;
454+ }
455+
456456
457457function emitInitScript ( asyncId , type , triggerAsyncId , resource ) {
458458 // Short circuit all checks for the common case. Which is that no hooks have
0 commit comments