@@ -60,7 +60,7 @@ const active_hooks = {
60
60
// async execution. These are tracked so if the user didn't include callbacks
61
61
// for a given step, that step can bail out early.
62
62
const { kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve,
63
- kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
63
+ kCheck , kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
64
64
kInitTriggerAsyncId } = async_wrap . constants ;
65
65
66
66
// Symbols used to store the respective ids on both AsyncResource instances and
@@ -156,8 +156,10 @@ class AsyncHook {
156
156
hook_fields [ kPromiseResolve ] += + ! ! this [ promise_resolve_symbol ] ;
157
157
hooks_array . push ( this ) ;
158
158
159
- if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 )
159
+ if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 ) {
160
160
enablePromiseHook ( ) ;
161
+ hook_fields [ kCheck ] += 1 ;
162
+ }
161
163
162
164
return this ;
163
165
}
@@ -180,8 +182,10 @@ class AsyncHook {
180
182
hook_fields [ kPromiseResolve ] -= + ! ! this [ promise_resolve_symbol ] ;
181
183
hooks_array . splice ( index , 1 ) ;
182
184
183
- if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 )
185
+ if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 ) {
184
186
disablePromiseHook ( ) ;
187
+ hook_fields [ kCheck ] -= 1 ;
188
+ }
185
189
186
190
return this ;
187
191
}
@@ -243,6 +247,15 @@ function triggerAsyncId() {
243
247
return async_id_fields [ kTriggerAsyncId ] ;
244
248
}
245
249
250
+ function validateAsyncId ( asyncId , type ) {
251
+ // Skip validation when async_hooks is disabled
252
+ if ( async_hook_fields [ kCheck ] <= 0 ) return ;
253
+
254
+ if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
255
+ fatalError ( new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , type , asyncId ) ) ;
256
+ }
257
+ }
258
+
246
259
247
260
// Embedder API //
248
261
@@ -337,10 +350,16 @@ function setInitTriggerId(triggerAsyncId) {
337
350
338
351
339
352
function emitInitScript ( asyncId , type , triggerAsyncId , resource ) {
353
+ validateAsyncId ( asyncId , 'asyncId' ) ;
354
+ if ( triggerAsyncId !== null )
355
+ validateAsyncId ( triggerAsyncId , 'triggerAsyncId' ) ;
356
+ if ( async_hook_fields [ kCheck ] > 0 &&
357
+ ( typeof type !== 'string' || type . length <= 0 ) ) {
358
+ throw new errors . TypeError ( 'ERR_ASYNC_TYPE' , type ) ;
359
+ }
360
+
340
361
// Short circuit all checks for the common case. Which is that no hooks have
341
362
// been set. Do this to remove performance impact for embedders (and core).
342
- // Even though it bypasses all the argument checks. The performance savings
343
- // here is critical.
344
363
if ( async_hook_fields [ kInit ] === 0 )
345
364
return ;
346
365
@@ -354,18 +373,6 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
354
373
async_id_fields [ kInitTriggerAsyncId ] = 0 ;
355
374
}
356
375
357
- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
358
- throw new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ;
359
- }
360
- if ( ! Number . isSafeInteger ( triggerAsyncId ) || triggerAsyncId < - 1 ) {
361
- throw new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' ,
362
- 'triggerAsyncId' ,
363
- triggerAsyncId ) ;
364
- }
365
- if ( typeof type !== 'string' || type . length <= 0 ) {
366
- throw new errors . TypeError ( 'ERR_ASYNC_TYPE' , type ) ;
367
- }
368
-
369
376
emitInitNative ( asyncId , type , triggerAsyncId , resource ) ;
370
377
}
371
378
@@ -411,15 +418,8 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
411
418
// Validate the ids. An id of -1 means it was never set and is visible on the
412
419
// call graph. An id < -1 should never happen in any circumstance. Throw
413
420
// on user calls because async state should still be recoverable.
414
- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
415
- fatalError (
416
- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
417
- }
418
- if ( ! Number . isSafeInteger ( triggerAsyncId ) || triggerAsyncId < - 1 ) {
419
- fatalError ( new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' ,
420
- 'triggerAsyncId' ,
421
- triggerAsyncId ) ) ;
422
- }
421
+ validateAsyncId ( asyncId , 'asyncId' ) ;
422
+ validateAsyncId ( triggerAsyncId , 'triggerAsyncId' ) ;
423
423
424
424
pushAsyncIds ( asyncId , triggerAsyncId ) ;
425
425
@@ -429,10 +429,7 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
429
429
430
430
431
431
function emitAfterScript ( asyncId ) {
432
- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
433
- fatalError (
434
- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
435
- }
432
+ validateAsyncId ( asyncId , 'asyncId' ) ;
436
433
437
434
if ( async_hook_fields [ kAfter ] > 0 )
438
435
emitAfterNative ( asyncId ) ;
@@ -442,10 +439,7 @@ function emitAfterScript(asyncId) {
442
439
443
440
444
441
function emitDestroyScript ( asyncId ) {
445
- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
446
- fatalError (
447
- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
448
- }
442
+ validateAsyncId ( asyncId , 'asyncId' ) ;
449
443
450
444
// Return early if there are no destroy callbacks, or invalid asyncId.
451
445
if ( async_hook_fields [ kDestroy ] === 0 || asyncId <= 0 )
0 commit comments