@@ -319,6 +319,14 @@ class NodeInspectorClient : public V8InspectorClient {
319319 return uv_hrtime () * 1.0 / NANOS_PER_MSEC;
320320 }
321321
322+ void maxAsyncCallStackDepthChanged (int depth) override {
323+ if (depth == 0 ) {
324+ env_->inspector_agent ()->DisableAsyncHook ();
325+ } else {
326+ env_->inspector_agent ()->EnableAsyncHook ();
327+ }
328+ }
329+
322330 void contextCreated (Local<Context> context, const std::string& name) {
323331 std::unique_ptr<StringBuffer> name_buffer = Utf8ToStringView (name);
324332 v8_inspector::V8ContextInfo info (context, CONTEXT_GROUP_ID,
@@ -449,7 +457,9 @@ Agent::Agent(Environment* env) : parent_env_(env),
449457 client_(nullptr ),
450458 platform_(nullptr ),
451459 enabled_(false ),
452- next_context_number_(1 ) {}
460+ next_context_number_(1 ),
461+ pending_enable_async_hook_(false ),
462+ pending_disable_async_hook_(false ) {}
453463
454464// Destructor needs to be defined here in implementation file as the header
455465// does not have full definition of some classes.
@@ -498,17 +508,6 @@ bool Agent::StartIoThread(bool wait_for_connect) {
498508 HandleScope handle_scope (isolate);
499509 auto context = parent_env_->context ();
500510
501- // Enable tracking of async stack traces
502- if (!enable_async_hook_function_.IsEmpty ()) {
503- Local<Function> enable_fn = enable_async_hook_function_.Get (isolate);
504- auto result = enable_fn->Call (context, Undefined (isolate), 0 , nullptr );
505- if (result.IsEmpty ()) {
506- FatalError (
507- " node::InspectorAgent::StartIoThread" ,
508- " Cannot enable Inspector's AsyncHook, please report this." );
509- }
510- }
511-
512511 // Send message to enable debug in workers
513512 Local<Object> process_object = parent_env_->process_object ();
514513 Local<Value> emit_fn =
@@ -537,38 +536,9 @@ void Agent::Stop() {
537536 io_.reset ();
538537 enabled_ = false ;
539538 }
540-
541- v8::Isolate* isolate = parent_env_->isolate ();
542- HandleScope handle_scope (isolate);
543-
544- // Disable tracking of async stack traces
545- if (!disable_async_hook_function_.IsEmpty ()) {
546- Local<Function> disable_fn = disable_async_hook_function_.Get (isolate);
547- auto result = disable_fn->Call (parent_env_->context (),
548- Undefined (parent_env_->isolate ()), 0 , nullptr );
549- if (result.IsEmpty ()) {
550- FatalError (
551- " node::InspectorAgent::Stop" ,
552- " Cannot disable Inspector's AsyncHook, please report this." );
553- }
554- }
555539}
556540
557541void Agent::Connect (InspectorSessionDelegate* delegate) {
558- if (!enabled_) {
559- // Enable tracking of async stack traces
560- v8::Isolate* isolate = parent_env_->isolate ();
561- HandleScope handle_scope (isolate);
562- auto context = parent_env_->context ();
563- Local<Function> enable_fn = enable_async_hook_function_.Get (isolate);
564- auto result = enable_fn->Call (context, Undefined (isolate), 0 , nullptr );
565- if (result.IsEmpty ()) {
566- FatalError (
567- " node::InspectorAgent::Connect" ,
568- " Cannot enable Inspector's AsyncHook, please report this." );
569- }
570- }
571-
572542 enabled_ = true ;
573543 client_->connectFrontend (delegate);
574544}
@@ -626,6 +596,50 @@ void Agent::RegisterAsyncHook(Isolate* isolate,
626596 v8::Local<v8::Function> disable_function) {
627597 enable_async_hook_function_.Reset (isolate, enable_function);
628598 disable_async_hook_function_.Reset (isolate, disable_function);
599+ if (pending_enable_async_hook_) {
600+ CHECK (!pending_disable_async_hook_);
601+ pending_enable_async_hook_ = false ;
602+ EnableAsyncHook ();
603+ } else if (pending_disable_async_hook_) {
604+ CHECK (!pending_enable_async_hook_);
605+ pending_disable_async_hook_ = false ;
606+ DisableAsyncHook ();
607+ }
608+ }
609+
610+ void Agent::EnableAsyncHook () {
611+ if (!enable_async_hook_function_.IsEmpty ()) {
612+ Isolate* isolate = parent_env_->isolate ();
613+ ToggleAsyncHook (isolate, enable_async_hook_function_.Get (isolate));
614+ } else if (pending_disable_async_hook_) {
615+ CHECK (!pending_enable_async_hook_);
616+ pending_disable_async_hook_ = false ;
617+ } else {
618+ pending_enable_async_hook_ = true ;
619+ }
620+ }
621+
622+ void Agent::DisableAsyncHook () {
623+ if (!disable_async_hook_function_.IsEmpty ()) {
624+ Isolate* isolate = parent_env_->isolate ();
625+ ToggleAsyncHook (isolate, disable_async_hook_function_.Get (isolate));
626+ } else if (pending_enable_async_hook_) {
627+ CHECK (!pending_disable_async_hook_);
628+ pending_enable_async_hook_ = false ;
629+ } else {
630+ pending_disable_async_hook_ = true ;
631+ }
632+ }
633+
634+ void Agent::ToggleAsyncHook (Isolate* isolate, Local<Function> fn) {
635+ HandleScope handle_scope (isolate);
636+ auto context = parent_env_->context ();
637+ auto result = fn->Call (context, Undefined (isolate), 0 , nullptr );
638+ if (result.IsEmpty ()) {
639+ FatalError (
640+ " node::inspector::Agent::ToggleAsyncHook" ,
641+ " Cannot toggle Inspector's AsyncHook, please report this." );
642+ }
629643}
630644
631645void Agent::AsyncTaskScheduled (const StringView& task_name, void * task,
0 commit comments