From 6c49cb3b276a5ce4e78a838e24a99b49f55eccf3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 27 Apr 2026 15:18:09 -0500 Subject: [PATCH] fix: add MicrotasksScope for worker exit emit in ContextWillDestroy (#51326) a39108c5a4 (#47244) replaced gin_helper::EmitEvent with a direct `v8::Function::Call()` in `WebWorkerObserver::ContextWillDestroy` to avoid re-entering the microtask checkpoint during worker teardown. V8 `DCHECK()`s that a policy is set. Under the old code path, this happened with a node::CallbackScope. Under the new code path, it's possible for a policy to not be set, causing that `DCHECK()` to fail. This PR copies a39108c5a4's changes in `ShareEnvironmentWithContext()`: it explicitly adds a `kDoNotRunMicrotasks` scope. --- shell/renderer/web_worker_observer.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/shell/renderer/web_worker_observer.cc b/shell/renderer/web_worker_observer.cc index 51efd42a91..ee20ba1752 100644 --- a/shell/renderer/web_worker_observer.cc +++ b/shell/renderer/web_worker_observer.cc @@ -252,6 +252,13 @@ void WebWorkerObserver::ContextWillDestroy(v8::Local context) { .ToLocal(&emit_v) && emit_v->IsFunction()) { v8::Local args[] = {gin::StringToV8(isolate, "exit")}; + // Worker/worklet contexts use kScoped microtask policy (set by + // Blink). V8 DCHECKs that a MicrotasksScope exists around every + // Call() under that policy. We use kDoNotRunMicrotasks because + // the context is mid-teardown. + v8::MicrotasksScope microtasks_scope{ + isolate, ctx->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks}; v8::TryCatch try_catch(isolate); emit_v.As() ->Call(ctx, env->process_object(), 1, args)