diff --git a/src/env.cc b/src/env.cc index 703a2a15758f95..f75115e1098fd1 100644 --- a/src/env.cc +++ b/src/env.cc @@ -708,6 +708,9 @@ void Environment::RunAndClearInterrupts() { void Environment::RunAndClearNativeImmediates(bool only_refed) { TraceEventScope trace_scope(TRACING_CATEGORY_NODE1(environment), "RunAndClearNativeImmediates", this); + HandleScope handle_scope(isolate_); + InternalCallbackScope cb_scope(this, Object::New(isolate_), { 0, 0 }); + size_t ref_count = 0; // Handle interrupts first. These functions are not allowed to throw diff --git a/test/async-hooks/test-late-hook-enable.js b/test/async-hooks/test-late-hook-enable.js index 0ffa6b24a3077d..82a80b24bb777c 100644 --- a/test/async-hooks/test-late-hook-enable.js +++ b/test/async-hooks/test-late-hook-enable.js @@ -17,14 +17,16 @@ const fnsToTest = [setTimeout, (cb) => { }); }); }, (cb) => { - process.nextTick(() => { - cb(); + setImmediate(() => { + process.nextTick(() => { + cb(); - // We need to keep the event loop open for this to actually work - // since destroy hooks are triggered in unrefed Immediates - setImmediate(() => { - hook.disable(); - assert.strictEqual(fnsToTest.length, 0); + // We need to keep the event loop open for this to actually work + // since destroy hooks are triggered in unrefed Immediates + setImmediate(() => { + hook.disable(); + assert.strictEqual(fnsToTest.length, 0); + }); }); }); }]; diff --git a/test/cctest/test_environment.cc b/test/cctest/test_environment.cc index d0182ca8620fac..dbe026e53889bf 100644 --- a/test/cctest/test_environment.cc +++ b/test/cctest/test_environment.cc @@ -466,3 +466,29 @@ TEST_F(EnvironmentTest, ExitHandlerTest) { node::LoadEnvironment(*env, "process.exit(42)").ToLocalChecked(); EXPECT_EQ(callback_calls, 1); } + +TEST_F(EnvironmentTest, SetImmediateMicrotasks) { + int called = 0; + + { + const v8::HandleScope handle_scope(isolate_); + const Argv argv; + Env env {handle_scope, argv}; + + node::LoadEnvironment(*env, + [&](const node::StartExecutionCallbackInfo& info) + -> v8::MaybeLocal { + return v8::Object::New(isolate_); + }); + + (*env)->SetImmediate([&](node::Environment* env_arg) { + EXPECT_EQ(env_arg, *env); + isolate_->EnqueueMicrotask([](void* arg) { + ++*static_cast(arg); + }, &called); + }, node::CallbackFlags::kRefed); + uv_run(¤t_loop, UV_RUN_DEFAULT); + } + + EXPECT_EQ(called, 1); +}