@@ -60,7 +60,7 @@ const active_hooks = {
6060// async execution. These are tracked so if the user didn't include callbacks
6161// for a given step, that step can bail out early.
6262const { kInit, kBefore, kAfter, kDestroy, kTotals, kPromiseResolve,
63- kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
63+ kCheck , kExecutionAsyncId, kTriggerAsyncId, kAsyncIdCounter,
6464 kInitTriggerAsyncId } = async_wrap . constants ;
6565
6666// Symbols used to store the respective ids on both AsyncResource instances and
@@ -156,8 +156,10 @@ class AsyncHook {
156156 hook_fields [ kPromiseResolve ] += + ! ! this [ promise_resolve_symbol ] ;
157157 hooks_array . push ( this ) ;
158158
159- if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 )
159+ if ( prev_kTotals === 0 && hook_fields [ kTotals ] > 0 ) {
160160 enablePromiseHook ( ) ;
161+ hook_fields [ kCheck ] += 1 ;
162+ }
161163
162164 return this ;
163165 }
@@ -180,8 +182,10 @@ class AsyncHook {
180182 hook_fields [ kPromiseResolve ] -= + ! ! this [ promise_resolve_symbol ] ;
181183 hooks_array . splice ( index , 1 ) ;
182184
183- if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 )
185+ if ( prev_kTotals > 0 && hook_fields [ kTotals ] === 0 ) {
184186 disablePromiseHook ( ) ;
187+ hook_fields [ kCheck ] -= 1 ;
188+ }
185189
186190 return this ;
187191 }
@@ -243,6 +247,15 @@ function triggerAsyncId() {
243247 return async_id_fields [ kTriggerAsyncId ] ;
244248}
245249
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+
246259
247260// Embedder API //
248261
@@ -337,10 +350,16 @@ function setInitTriggerId(triggerAsyncId) {
337350
338351
339352function 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+
340361 // Short circuit all checks for the common case. Which is that no hooks have
341362 // 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.
344363 if ( async_hook_fields [ kInit ] === 0 )
345364 return ;
346365
@@ -354,18 +373,6 @@ function emitInitScript(asyncId, type, triggerAsyncId, resource) {
354373 async_id_fields [ kInitTriggerAsyncId ] = 0 ;
355374 }
356375
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-
369376 emitInitNative ( asyncId , type , triggerAsyncId , resource ) ;
370377}
371378
@@ -411,15 +418,8 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
411418 // Validate the ids. An id of -1 means it was never set and is visible on the
412419 // call graph. An id < -1 should never happen in any circumstance. Throw
413420 // 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' ) ;
423423
424424 pushAsyncIds ( asyncId , triggerAsyncId ) ;
425425
@@ -429,10 +429,7 @@ function emitBeforeScript(asyncId, triggerAsyncId) {
429429
430430
431431function 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' ) ;
436433
437434 if ( async_hook_fields [ kAfter ] > 0 )
438435 emitAfterNative ( asyncId ) ;
@@ -442,10 +439,7 @@ function emitAfterScript(asyncId) {
442439
443440
444441function 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' ) ;
449443
450444 // Return early if there are no destroy callbacks, or invalid asyncId.
451445 if ( async_hook_fields [ kDestroy ] === 0 || asyncId <= 0 )
0 commit comments