diff --git a/src/env-inl.h b/src/env-inl.h index 1f05bac239d429..ae5d231afb4776 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -127,6 +127,11 @@ inline void AsyncHooks::SetJSPromiseHooks(v8::Local init, js_promise_hooks_[2].Reset(env()->isolate(), after); js_promise_hooks_[3].Reset(env()->isolate(), resolve); for (auto it = contexts_.begin(); it != contexts_.end(); it++) { + if (it->IsEmpty()) { + it = contexts_.erase(it); + it--; + continue; + } PersistentToLocal::Weak(env()->isolate(), *it) ->SetPromiseHooks(init, before, after, resolve); } @@ -279,8 +284,13 @@ inline void AsyncHooks::RemoveContext(v8::Local ctx) { v8::Isolate* isolate = env()->isolate(); v8::HandleScope handle_scope(isolate); for (auto it = contexts_.begin(); it != contexts_.end(); it++) { + if (it->IsEmpty()) { + it = contexts_.erase(it); + it--; + continue; + } v8::Local saved_context = - PersistentToLocal::Weak(env()->isolate(), *it); + PersistentToLocal::Weak(isolate, *it); if (saved_context == ctx) { it->Reset(); contexts_.erase(it); diff --git a/test/parallel/test-async-hooks-vm-gc.js b/test/parallel/test-async-hooks-vm-gc.js new file mode 100644 index 00000000000000..da95e3579dcca4 --- /dev/null +++ b/test/parallel/test-async-hooks-vm-gc.js @@ -0,0 +1,15 @@ +// Flags: --expose-gc +'use strict'; + +require('../common'); +const asyncHooks = require('async_hooks'); +const vm = require('vm'); + +// This is a regression test for https://github.com/nodejs/node/issues/39019 +// +// It should not segfault. + +const hook = asyncHooks.createHook({ init() {} }).enable(); +vm.createContext(); +globalThis.gc(); +hook.disable();