@@ -61,7 +61,7 @@ const active_hooks = {
6161// async execution. These are tracked so if the user didn't include callbacks
6262// for a given step, that step can bail out early.
6363const { kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve,
64- kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
64+ kCheck , kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
6565 kInitTriggerAsyncId } = async_wrap . constants ;
6666
6767// Symbols used to store the respective ids on both AsyncResource instances and
@@ -157,8 +157,10 @@ class AsyncHook {
157157 hook_fields [ kPromiseResolve ] += + ! ! this [ promise_resolve_symbol ] ;
158158 hooks_array . push ( this ) ;
159159
160- if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 )
160+ if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 ) {
161161 enablePromiseHook ( ) ;
162+ hook_fields [ kCheck ] += 1 ;
163+ }
162164
163165 return this ;
164166 }
@@ -181,8 +183,10 @@ class AsyncHook {
181183 hook_fields [ kPromiseResolve ] -= + ! ! this [ promise_resolve_symbol ] ;
182184 hooks_array . splice ( index , 1 ) ;
183185
184- if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 )
186+ if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 ) {
185187 disablePromiseHook ( ) ;
188+ hook_fields [ kCheck ] -= 1 ;
189+ }
186190
187191 return this ;
188192 }
@@ -244,6 +248,15 @@ function triggerAsyncId() {
244248 return async_id_fields [ kTriggerAsyncId ] ;
245249}
246250
251+ function validateAsyncId ( asyncId , type ) {
252+ // Skip validation when async_hooks is disabled
253+ if ( async_hook_fields [ kCheck ] <= 0 ) return ;
254+
255+ if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
256+ fatalError ( new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , type , asyncId ) ) ;
257+ }
258+ }
259+
247260
248261// Embedder API //
249262
@@ -349,10 +362,16 @@ function setInitTriggerId(triggerAsyncId) {
349362
350363
351364function emitInitScript ( asyncId , type , triggerAsyncId , resource ) {
365+ validateAsyncId ( asyncId , 'asyncId' ) ;
366+ if ( triggerAsyncId !== null )
367+ validateAsyncId ( triggerAsyncId , 'triggerAsyncId' ) ;
368+ if ( async_hook_fields [ kCheck ] > 0 &&
369+ ( typeof type !== 'string' || type . length <= 0 ) ) {
370+ throw new errors . TypeError ( 'ERR_ASYNC_TYPE' , type ) ;
371+ }
372+
352373 // Short circuit all checks for the common case. Which is that no hooks have
353374 // been set. Do this to remove performance impact for embedders (and core).
354- // Even though it bypasses all the argument checks. The performance savings
355- // here is critical.
356375 if ( async_hook_fields [ kInit ] === 0 )
357376 return ;
358377
@@ -366,18 +385,6 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
366385 async_id_fields [ kInitTriggerAsyncId ] = 0 ;
367386 }
368387
369- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
370- throw new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ;
371- }
372- if ( ! Number . isSafeInteger ( triggerAsyncId ) || triggerAsyncId < - 1 ) {
373- throw new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' ,
374- 'triggerAsyncId' ,
375- triggerAsyncId ) ;
376- }
377- if ( typeof type !== 'string' || type . length <= 0 ) {
378- throw new errors . TypeError ( 'ERR_ASYNC_TYPE' , type ) ;
379- }
380-
381388 emitInitNative ( asyncId , type , triggerAsyncId , resource ) ;
382389}
383390
@@ -423,15 +430,8 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
423430 // Validate the ids. An id of -1 means it was never set and is visible on the
424431 // call graph. An id < -1 should never happen in any circumstance. Throw
425432 // on user calls because async state should still be recoverable.
426- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
427- fatalError (
428- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
429- }
430- if ( ! Number . isSafeInteger ( triggerAsyncId ) || triggerAsyncId < - 1 ) {
431- fatalError ( new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' ,
432- 'triggerAsyncId' ,
433- triggerAsyncId ) ) ;
434- }
433+ validateAsyncId ( asyncId , 'asyncId' ) ;
434+ validateAsyncId ( triggerAsyncId , 'triggerAsyncId' ) ;
435435
436436 pushAsyncIds ( asyncId , triggerAsyncId ) ;
437437
@@ -441,10 +441,7 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
441441
442442
443443function emitAfterScript ( asyncId ) {
444- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
445- fatalError (
446- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
447- }
444+ validateAsyncId ( asyncId , 'asyncId' ) ;
448445
449446 if ( async_hook_fields [ kAfter ] > 0 )
450447 emitAfterNative ( asyncId ) ;
@@ -454,10 +451,7 @@ function emitAfterScript(asyncId) {
454451
455452
456453function emitDestroyScript ( asyncId ) {
457- if ( ! Number . isSafeInteger ( asyncId ) || asyncId < - 1 ) {
458- fatalError (
459- new errors . RangeError ( 'ERR_INVALID_ASYNC_ID' , 'asyncId' , asyncId ) ) ;
460- }
454+ validateAsyncId ( asyncId , 'asyncId' ) ;
461455
462456 // Return early if there are no destroy callbacks, or invalid asyncId.
463457 if ( async_hook_fields [ kDestroy ] === 0 || asyncId <= 0 )
0 commit comments