@@ -26,10 +26,10 @@ const { pushAsyncIds, popAsyncIds } = async_wrap;
26
26
// Using var instead of (preferably const) in order to assign
27
27
// tmp_active_hooks_array if a hook is enabled/disabled during hook execution.
28
28
var active_hooks_array = [ ] ;
29
- // Track whether a hook callback is currently being processed. Used to make
30
- // sure active_hooks_array isn't altered in mid execution if another hook is
31
- // added or removed.
32
- var processing_hook = false ;
29
+ // Use a counter to track whether a hook callback is currently being processed.
30
+ // Used to make sure active_hooks_array isn't altered in mid execution if
31
+ // another hook is added or removed. A counter is used to track nested calls .
32
+ var processing_hook = 0 ;
33
33
// Use to temporarily store and updated active_hooks_array if the user enables
34
34
// or disables a hook while hooks are being processed.
35
35
var tmp_active_hooks_array = null ;
@@ -151,7 +151,7 @@ class AsyncHook {
151
151
152
152
153
153
function getHookArrays ( ) {
154
- if ( ! processing_hook )
154
+ if ( processing_hook === 0 )
155
155
return [ active_hooks_array , async_hook_fields ] ;
156
156
// If this hook is being enabled while in the middle of processing the array
157
157
// of currently active hooks then duplicate the current set of active hooks
@@ -342,7 +342,7 @@ function emitHookFactory(symbol, name) {
342
342
// before this is called.
343
343
// eslint-disable-next-line func-style
344
344
const fn = function ( asyncId ) {
345
- processing_hook = true ;
345
+ processing_hook += 1 ;
346
346
// Use a single try/catch for all hook to avoid setting up one per
347
347
// iteration.
348
348
try {
@@ -353,10 +353,11 @@ function emitHookFactory(symbol, name) {
353
353
}
354
354
} catch ( e ) {
355
355
fatalError ( e ) ;
356
+ } finally {
357
+ processing_hook -= 1 ;
356
358
}
357
- processing_hook = false ;
358
359
359
- if ( tmp_active_hooks_array !== null ) {
360
+ if ( processing_hook === 0 && tmp_active_hooks_array !== null ) {
360
361
restoreTmpHooks ( ) ;
361
362
}
362
363
} ;
@@ -422,7 +423,7 @@ function emitDestroyS(asyncId) {
422
423
// slim chance of the application remaining stable after handling one of these
423
424
// exceptions.
424
425
function init ( asyncId , type , triggerAsyncId , resource ) {
425
- processing_hook = true ;
426
+ processing_hook += 1 ;
426
427
// Use a single try/catch for all hook to avoid setting up one per iteration.
427
428
try {
428
429
for ( var i = 0 ; i < active_hooks_array . length ; i ++ ) {
@@ -435,11 +436,18 @@ function init(asyncId, type, triggerAsyncId, resource) {
435
436
}
436
437
} catch ( e ) {
437
438
fatalError ( e ) ;
439
+ } finally {
440
+ processing_hook -= 1 ;
438
441
}
439
- processing_hook = false ;
440
442
441
- // Isn't null if hooks were added/removed while the hooks were running.
442
- if ( tmp_active_hooks_array !== null ) {
443
+ // * `tmp_active_hooks_array` is null if no hooks were added/removed while
444
+ // the hooks were running. In that case no restoration is needed.
445
+ // * In the case where another hook was added/removed while the hooks were
446
+ // running and a handle was created causing the `init` hooks to fire again,
447
+ // then `restoreTmpHooks` should not be called for the nested `hooks`.
448
+ // Otherwise `active_hooks_array` can change during execution of the
449
+ // `hooks`.
450
+ if ( processing_hook === 0 && tmp_active_hooks_array !== null ) {
443
451
restoreTmpHooks ( ) ;
444
452
}
445
453
}
0 commit comments