@@ -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' ) {
@@ -330,8 +347,8 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
330347}
331348
332349
333- function emitBeforeScript ( asyncId , triggerAsyncId ) {
334- pushAsyncIds ( asyncId , triggerAsyncId ) ;
350+ function emitBeforeScript ( asyncId , triggerAsyncId , resource ) {
351+ pushAsyncContext ( asyncId , triggerAsyncId , resource ) ;
335352
336353 if ( async_hook_fields [ kBefore ] > 0 )
337354 emitBeforeNative ( asyncId ) ;
@@ -342,7 +359,7 @@ function emitAfterScript(asyncId) {
342359 if ( async_hook_fields [ kAfter ] > 0 )
343360 emitAfterNative ( asyncId ) ;
344361
345- popAsyncIds ( asyncId ) ;
362+ popAsyncContext ( asyncId ) ;
346363}
347364
348365
@@ -360,6 +377,7 @@ function clearAsyncIdStack() {
360377 async_id_fields [ kExecutionAsyncId ] = 0 ;
361378 async_id_fields [ kTriggerAsyncId ] = 0 ;
362379 async_hook_fields [ kStackLength ] = 0 ;
380+ execution_async_resources . splice ( 0 , execution_async_resources . length ) ;
363381}
364382
365383
@@ -369,31 +387,33 @@ function hasAsyncIdStack() {
369387
370388
371389// This is the equivalent of the native push_async_ids() call.
372- function pushAsyncIds ( asyncId , triggerAsyncId ) {
390+ function pushAsyncContext ( asyncId , triggerAsyncId , resource ) {
373391 const offset = async_hook_fields [ kStackLength ] ;
374392 if ( offset * 2 >= async_wrap . async_ids_stack . length )
375- return pushAsyncIds_ ( asyncId , triggerAsyncId ) ;
393+ return pushAsyncContext_ ( asyncId , triggerAsyncId , resource ) ;
376394 async_wrap . async_ids_stack [ offset * 2 ] = async_id_fields [ kExecutionAsyncId ] ;
377395 async_wrap . async_ids_stack [ offset * 2 + 1 ] = async_id_fields [ kTriggerAsyncId ] ;
396+ execution_async_resources [ offset ] = resource ;
378397 async_hook_fields [ kStackLength ] ++ ;
379398 async_id_fields [ kExecutionAsyncId ] = asyncId ;
380399 async_id_fields [ kTriggerAsyncId ] = triggerAsyncId ;
381400}
382401
383402
384403// This is the equivalent of the native pop_async_ids() call.
385- function popAsyncIds ( asyncId ) {
404+ function popAsyncContext ( asyncId ) {
386405 const stackLength = async_hook_fields [ kStackLength ] ;
387406 if ( stackLength === 0 ) return false ;
388407
389408 if ( enabledHooksExist ( ) && async_id_fields [ kExecutionAsyncId ] !== asyncId ) {
390409 // Do the same thing as the native code (i.e. crash hard).
391- return popAsyncIds_ ( asyncId ) ;
410+ return popAsyncContext_ ( asyncId ) ;
392411 }
393412
394413 const offset = stackLength - 1 ;
395414 async_id_fields [ kExecutionAsyncId ] = async_wrap . async_ids_stack [ 2 * offset ] ;
396415 async_id_fields [ kTriggerAsyncId ] = async_wrap . async_ids_stack [ 2 * offset + 1 ] ;
416+ execution_async_resources . pop ( ) ;
397417 async_hook_fields [ kStackLength ] = offset ;
398418 return offset > 0 ;
399419}
@@ -426,6 +446,7 @@ module.exports = {
426446 clearDefaultTriggerAsyncId,
427447 clearAsyncIdStack,
428448 hasAsyncIdStack,
449+ executionAsyncResource,
429450 // Internal Embedder API
430451 newAsyncId,
431452 getOrSetAsyncId,
0 commit comments