@@ -28,18 +28,26 @@ const async_wrap = internalBinding('async_wrap');
2828 * 3. executionAsyncId of the current resource.
2929 *
3030 * async_ids_stack is a Float64Array that contains part of the async ID
31- * stack. Each pushAsyncIds () call adds two doubles to it, and each
32- * popAsyncIds () call removes two doubles from it.
31+ * stack. Each pushAsyncContext () call adds two doubles to it, and each
32+ * popAsyncContext () call removes two doubles from it.
3333 * It has a fixed size, so if that is exceeded, calls to the native
34- * side are used instead in pushAsyncIds () and popAsyncIds ().
34+ * side are used instead in pushAsyncContext () and popAsyncContext ().
3535 */
36- const { async_hook_fields, async_id_fields, owner_symbol } = async_wrap ;
36+ const {
37+ async_hook_fields,
38+ async_id_fields,
39+ execution_async_resources,
40+ owner_symbol
41+ } = async_wrap ;
3742// Store the pair executionAsyncId and triggerAsyncId in a std::stack on
3843// Environment::AsyncHooks::async_ids_stack_ tracks the resource responsible for
3944// the current execution stack. This is unwound as each resource exits. In the
4045// case of a fatal exception this stack is emptied after calling each hook's
4146// after() callback.
42- const { pushAsyncIds : pushAsyncIds_ , popAsyncIds : popAsyncIds_ } = async_wrap ;
47+ const {
48+ pushAsyncContext : pushAsyncContext_ ,
49+ popAsyncContext : popAsyncContext_
50+ } = async_wrap ;
4351// For performance reasons, only track Promises when a hook is enabled.
4452const { enablePromiseHook, disablePromiseHook } = async_wrap ;
4553// Properties in active_hooks are used to keep track of the set of hooks being
@@ -92,6 +100,15 @@ const emitDestroyNative = emitHookFactory(destroy_symbol, 'emitDestroyNative');
92100const emitPromiseResolveNative =
93101 emitHookFactory ( promise_resolve_symbol , 'emitPromiseResolveNative' ) ;
94102
103+ const topLevelResource = { } ;
104+
105+ function executionAsyncResource ( ) {
106+ const index = async_hook_fields [ kStackLength ] - 1 ;
107+ if ( index === - 1 ) return topLevelResource ;
108+ const resource = execution_async_resources [ index ] ;
109+ return resource ;
110+ }
111+
95112// Used to fatally abort the process if a callback throws.
96113function fatalError ( e ) {
97114 if ( typeof e . stack === 'string' ) {
@@ -334,8 +351,8 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
334351}
335352
336353
337- function emitBeforeScript ( asyncId , triggerAsyncId ) {
338- pushAsyncIds ( asyncId , triggerAsyncId ) ;
354+ function emitBeforeScript ( asyncId , triggerAsyncId , resource ) {
355+ pushAsyncContext ( asyncId , triggerAsyncId , resource ) ;
339356
340357 if ( hasHooks ( kBefore ) )
341358 emitBeforeNative ( asyncId ) ;
@@ -346,7 +363,7 @@ function emitAfterScript(asyncId) {
346363 if ( hasHooks ( kAfter ) )
347364 emitAfterNative ( asyncId ) ;
348365
349- popAsyncIds ( asyncId ) ;
366+ popAsyncContext ( asyncId ) ;
350367}
351368
352369
@@ -364,6 +381,7 @@ function clearAsyncIdStack() {
364381 async_id_fields [ kExecutionAsyncId ] = 0 ;
365382 async_id_fields [ kTriggerAsyncId ] = 0 ;
366383 async_hook_fields [ kStackLength ] = 0 ;
384+ execution_async_resources . splice ( 0 , execution_async_resources . length ) ;
367385}
368386
369387
@@ -373,31 +391,33 @@ function hasAsyncIdStack() {
373391
374392
375393// This is the equivalent of the native push_async_ids() call.
376- function pushAsyncIds ( asyncId , triggerAsyncId ) {
394+ function pushAsyncContext ( asyncId , triggerAsyncId , resource ) {
377395 const offset = async_hook_fields [ kStackLength ] ;
378396 if ( offset * 2 >= async_wrap . async_ids_stack . length )
379- return pushAsyncIds_ ( asyncId , triggerAsyncId ) ;
397+ return pushAsyncContext_ ( asyncId , triggerAsyncId , resource ) ;
380398 async_wrap . async_ids_stack [ offset * 2 ] = async_id_fields [ kExecutionAsyncId ] ;
381399 async_wrap . async_ids_stack [ offset * 2 + 1 ] = async_id_fields [ kTriggerAsyncId ] ;
400+ execution_async_resources [ offset ] = resource ;
382401 async_hook_fields [ kStackLength ] ++ ;
383402 async_id_fields [ kExecutionAsyncId ] = asyncId ;
384403 async_id_fields [ kTriggerAsyncId ] = triggerAsyncId ;
385404}
386405
387406
388407// This is the equivalent of the native pop_async_ids() call.
389- function popAsyncIds ( asyncId ) {
408+ function popAsyncContext ( asyncId ) {
390409 const stackLength = async_hook_fields [ kStackLength ] ;
391410 if ( stackLength === 0 ) return false ;
392411
393412 if ( enabledHooksExist ( ) && async_id_fields [ kExecutionAsyncId ] !== asyncId ) {
394413 // Do the same thing as the native code (i.e. crash hard).
395- return popAsyncIds_ ( asyncId ) ;
414+ return popAsyncContext_ ( asyncId ) ;
396415 }
397416
398417 const offset = stackLength - 1 ;
399418 async_id_fields [ kExecutionAsyncId ] = async_wrap . async_ids_stack [ 2 * offset ] ;
400419 async_id_fields [ kTriggerAsyncId ] = async_wrap . async_ids_stack [ 2 * offset + 1 ] ;
420+ execution_async_resources . pop ( ) ;
401421 async_hook_fields [ kStackLength ] = offset ;
402422 return offset > 0 ;
403423}
@@ -430,6 +450,7 @@ module.exports = {
430450 clearDefaultTriggerAsyncId,
431451 clearAsyncIdStack,
432452 hasAsyncIdStack,
453+ executionAsyncResource,
433454 // Internal Embedder API
434455 newAsyncId,
435456 getOrSetAsyncId,
0 commit comments