@@ -38,8 +38,8 @@ var tmp_async_hook_fields = null;
38
38
// Each constant tracks how many callbacks there are for any given step of
39
39
// async execution. These are tracked so if the user didn't include callbacks
40
40
// for a given step, that step can bail out early.
41
- const { kInit, kBefore, kAfter, kDestroy, kCurrentAsyncId , kCurrentTriggerId ,
42
- kAsyncUidCntr, kInitTriggerId } = async_wrap . constants ;
41
+ const { kInit, kBefore, kAfter, kDestroy, kTotals , kCurrentAsyncId ,
42
+ kCurrentTriggerId , kAsyncUidCntr, kInitTriggerId } = async_wrap . constants ;
43
43
44
44
const { async_id_symbol, trigger_id_symbol } = async_wrap ;
45
45
@@ -50,7 +50,9 @@ const after_symbol = Symbol('after');
50
50
const destroy_symbol = Symbol ( 'destroy' ) ;
51
51
52
52
// Setup the callbacks that node::AsyncWrap will call when there are hooks to
53
- // process. They use the same functions as the JS embedder API.
53
+ // process. They use the same functions as the JS embedder API. These callbacks
54
+ // are setup immediately to prevent async_wrap.setupHooks() from being hijacked
55
+ // and the cost of doing so is negligible.
54
56
async_wrap . setupHooks ( { init,
55
57
before : emitBeforeN ,
56
58
after : emitAfterN ,
@@ -103,14 +105,21 @@ class AsyncHook {
103
105
if ( hooks_array . includes ( this ) )
104
106
return this ;
105
107
108
+ const prev_kTotals = hook_fields [ kTotals ] ;
109
+ hook_fields [ kTotals ] = 0 ;
110
+
106
111
// createHook() has already enforced that the callbacks are all functions,
107
112
// so here simply increment the count of whether each callbacks exists or
108
113
// not.
109
- hook_fields [ kInit ] += + ! ! this [ init_symbol ] ;
110
- hook_fields [ kBefore ] += + ! ! this [ before_symbol ] ;
111
- hook_fields [ kAfter ] += + ! ! this [ after_symbol ] ;
112
- hook_fields [ kDestroy ] += + ! ! this [ destroy_symbol ] ;
114
+ hook_fields [ kTotals ] += hook_fields [ kInit ] += + ! ! this [ init_symbol ] ;
115
+ hook_fields [ kTotals ] += hook_fields [ kBefore ] += + ! ! this [ before_symbol ] ;
116
+ hook_fields [ kTotals ] += hook_fields [ kAfter ] += + ! ! this [ after_symbol ] ;
117
+ hook_fields [ kTotals ] += hook_fields [ kDestroy ] += + ! ! this [ destroy_symbol ] ;
113
118
hooks_array . push ( this ) ;
119
+
120
+ if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 )
121
+ async_wrap . enablePromiseHook ( ) ;
122
+
114
123
return this ;
115
124
}
116
125
@@ -121,11 +130,18 @@ class AsyncHook {
121
130
if ( index === - 1 )
122
131
return this ;
123
132
124
- hook_fields [ kInit ] -= + ! ! this [ init_symbol ] ;
125
- hook_fields [ kBefore ] -= + ! ! this [ before_symbol ] ;
126
- hook_fields [ kAfter ] -= + ! ! this [ after_symbol ] ;
127
- hook_fields [ kDestroy ] -= + ! ! this [ destroy_symbol ] ;
133
+ const prev_kTotals = hook_fields [ kTotals ] ;
134
+ hook_fields [ kTotals ] = 0 ;
135
+
136
+ hook_fields [ kTotals ] += hook_fields [ kInit ] -= + ! ! this [ init_symbol ] ;
137
+ hook_fields [ kTotals ] += hook_fields [ kBefore ] -= + ! ! this [ before_symbol ] ;
138
+ hook_fields [ kTotals ] += hook_fields [ kAfter ] -= + ! ! this [ after_symbol ] ;
139
+ hook_fields [ kTotals ] += hook_fields [ kDestroy ] -= + ! ! this [ destroy_symbol ] ;
128
140
hooks_array . splice ( index , 1 ) ;
141
+
142
+ if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 )
143
+ async_wrap . disablePromiseHook ( ) ;
144
+
129
145
return this ;
130
146
}
131
147
}
0 commit comments