diff --git a/patches/v8/.patches b/patches/v8/.patches index 4c5e530a4b4..d9b32bf9556 100644 --- a/patches/v8/.patches +++ b/patches/v8/.patches @@ -9,3 +9,4 @@ fix_disable_implies_dcheck_for_node_stream_array_buffers.patch revert_runtime_dhceck_terminating_exception_in_microtasks.patch chore_disable_is_execution_terminating_dcheck.patch force_cppheapcreateparams_to_be_noncopyable.patch +chore_allow_customizing_microtask_policy_per_context.patch diff --git a/patches/v8/chore_allow_customizing_microtask_policy_per_context.patch b/patches/v8/chore_allow_customizing_microtask_policy_per_context.patch new file mode 100644 index 00000000000..7d62ff91391 --- /dev/null +++ b/patches/v8/chore_allow_customizing_microtask_policy_per_context.patch @@ -0,0 +1,41 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: deepak1556 +Date: Wed, 11 Jan 2023 19:21:06 +0900 +Subject: chore: allow customizing microtask policy per context + +With https://github.com/electron/electron/issues/36813, microtask queue associated with a context +will be used if available, instead of the default associated with an isolate. We need the +capability to switch the microtask polciy of these per context microtask queue to support +Node.js integration in the renderer. + +diff --git a/include/v8-microtask-queue.h b/include/v8-microtask-queue.h +index 85d227fa3fdce6fc29bc4927e30a0171987578ac..1a61190ed3a2aeb440aa774788a469079df13c79 100644 +--- a/include/v8-microtask-queue.h ++++ b/include/v8-microtask-queue.h +@@ -97,6 +97,9 @@ class V8_EXPORT MicrotaskQueue { + */ + virtual int GetMicrotasksScopeDepth() const = 0; + ++ virtual void set_microtasks_policy(v8::MicrotasksPolicy microtasks_policy) = 0; ++ virtual v8::MicrotasksPolicy microtasks_policy() const = 0; ++ + MicrotaskQueue(const MicrotaskQueue&) = delete; + MicrotaskQueue& operator=(const MicrotaskQueue&) = delete; + +diff --git a/src/execution/microtask-queue.h b/src/execution/microtask-queue.h +index 6091fa3575cf82ea532e88747c753040045cc9a0..55eee1dcede4daeed53bdc0447cfb714763d0d32 100644 +--- a/src/execution/microtask-queue.h ++++ b/src/execution/microtask-queue.h +@@ -91,10 +91,10 @@ class V8_EXPORT_PRIVATE MicrotaskQueue final : public v8::MicrotaskQueue { + } + #endif + +- void set_microtasks_policy(v8::MicrotasksPolicy microtasks_policy) { ++ void set_microtasks_policy(v8::MicrotasksPolicy microtasks_policy) override { + microtasks_policy_ = microtasks_policy; + } +- v8::MicrotasksPolicy microtasks_policy() const { return microtasks_policy_; } ++ v8::MicrotasksPolicy microtasks_policy() const override { return microtasks_policy_; } + + intptr_t capacity() const { return capacity_; } + intptr_t size() const { return size_; } diff --git a/shell/browser/feature_list.cc b/shell/browser/feature_list.cc index 401a6d6d503..0cf9374876b 100644 --- a/shell/browser/feature_list.cc +++ b/shell/browser/feature_list.cc @@ -16,7 +16,6 @@ #include "media/base/media_switches.h" #include "net/base/features.h" #include "services/network/public/cpp/features.h" -#include "third_party/blink/renderer/platform/scheduler/common/features.h" // nogncheck #if BUILDFLAG(IS_MAC) #include "device/base/features.h" // nogncheck @@ -37,12 +36,6 @@ void InitializeFeatureList() { disable_features += std::string(",") + features::kSpareRendererForSitePerProcess.name; - // Microtask queues per WindowAgent causes issues with Node, so disable - // this feature for now. See - // https://chromium-review.googlesource.com/c/chromium/src/+/4003663 - disable_features += - std::string(",") + blink::scheduler::kMicrotaskQueuePerWindowAgent.name; - #if BUILDFLAG(IS_MAC) // Needed for WebUSB implementation enable_features += std::string(",") + device::kNewUsbBackend.name; diff --git a/shell/common/api/electron_bindings.cc b/shell/common/api/electron_bindings.cc index c284f0fa7a9..ef84624a4d4 100644 --- a/shell/common/api/electron_bindings.cc +++ b/shell/common/api/electron_bindings.cc @@ -251,9 +251,11 @@ void ElectronBindings::DidReceiveMemoryDump( std::unique_ptr global_dump) { v8::Isolate* isolate = promise.isolate(); v8::HandleScope handle_scope(isolate); - gin_helper::MicrotasksScope microtasks_scope(isolate, true); - v8::Context::Scope context_scope( - v8::Local::New(isolate, context)); + v8::Local local_context = + v8::Local::New(isolate, context); + gin_helper::MicrotasksScope microtasks_scope( + isolate, local_context->GetMicrotaskQueue(), true); + v8::Context::Scope context_scope(local_context); if (!success) { promise.RejectWithErrorMessage("Failed to create memory dump"); diff --git a/shell/common/gin_helper/callback.h b/shell/common/gin_helper/callback.h index 5f40f57c78c..777238c9156 100644 --- a/shell/common/gin_helper/callback.h +++ b/shell/common/gin_helper/callback.h @@ -48,9 +48,10 @@ struct V8FunctionInvoker(ArgTypes...)> { v8::EscapableHandleScope handle_scope(isolate); if (!function.IsAlive()) return v8::Null(isolate); - gin_helper::MicrotasksScope microtasks_scope(isolate, true); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->GetCreationContextChecked(); + gin_helper::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), true); v8::Context::Scope context_scope(context); std::vector> args{ gin::ConvertToV8(isolate, std::forward(raw))...}; @@ -72,9 +73,10 @@ struct V8FunctionInvoker { v8::HandleScope handle_scope(isolate); if (!function.IsAlive()) return; - gin_helper::MicrotasksScope microtasks_scope(isolate, true); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->GetCreationContextChecked(); + gin_helper::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), true); v8::Context::Scope context_scope(context); std::vector> args{ gin::ConvertToV8(isolate, std::forward(raw))...}; @@ -95,9 +97,10 @@ struct V8FunctionInvoker { ReturnType ret = ReturnType(); if (!function.IsAlive()) return ret; - gin_helper::MicrotasksScope microtasks_scope(isolate, true); v8::Local holder = function.NewHandle(isolate); v8::Local context = holder->GetCreationContextChecked(); + gin_helper::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), true); v8::Context::Scope context_scope(context); std::vector> args{ gin::ConvertToV8(isolate, std::forward(raw))...}; diff --git a/shell/common/gin_helper/event_emitter_caller.cc b/shell/common/gin_helper/event_emitter_caller.cc index be112f55fa5..41b0c7b3557 100644 --- a/shell/common/gin_helper/event_emitter_caller.cc +++ b/shell/common/gin_helper/event_emitter_caller.cc @@ -15,7 +15,8 @@ v8::Local CallMethodWithArgs(v8::Isolate* isolate, const char* method, ValueVector* args) { // Perform microtask checkpoint after running JavaScript. - gin_helper::MicrotasksScope microtasks_scope(isolate, true); + gin_helper::MicrotasksScope microtasks_scope( + isolate, obj->GetCreationContextChecked()->GetMicrotaskQueue(), true); // Use node::MakeCallback to call the callback, and it will also run pending // tasks in Node.js. v8::MaybeLocal ret = node::MakeCallback( diff --git a/shell/common/gin_helper/function_template.h b/shell/common/gin_helper/function_template.h index c6d6410f945..265ddde5dbb 100644 --- a/shell/common/gin_helper/function_template.h +++ b/shell/common/gin_helper/function_template.h @@ -217,7 +217,9 @@ class Invoker, ArgTypes...> template void DispatchToCallback( base::RepeatingCallback callback) { - gin_helper::MicrotasksScope microtasks_scope(args_->isolate(), true); + gin_helper::MicrotasksScope microtasks_scope( + args_->isolate(), + args_->GetHolderCreationContext()->GetMicrotaskQueue(), true); args_->Return( callback.Run(std::move(ArgumentHolder::value)...)); } @@ -226,7 +228,9 @@ class Invoker, ArgTypes...> // expression to foo. As a result, we must specialize the case of Callbacks // that have the void return type. void DispatchToCallback(base::RepeatingCallback callback) { - gin_helper::MicrotasksScope microtasks_scope(args_->isolate(), true); + gin_helper::MicrotasksScope microtasks_scope( + args_->isolate(), + args_->GetHolderCreationContext()->GetMicrotaskQueue(), true); callback.Run(std::move(ArgumentHolder::value)...); } diff --git a/shell/common/gin_helper/microtasks_scope.cc b/shell/common/gin_helper/microtasks_scope.cc index a3f8c73d749..3b768a326f4 100644 --- a/shell/common/gin_helper/microtasks_scope.cc +++ b/shell/common/gin_helper/microtasks_scope.cc @@ -9,14 +9,15 @@ namespace gin_helper { MicrotasksScope::MicrotasksScope(v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue, bool ignore_browser_checkpoint, v8::MicrotasksScope::Type scope_type) { if (Locker::IsBrowserProcess()) { if (!ignore_browser_checkpoint) v8::MicrotasksScope::PerformCheckpoint(isolate); } else { - v8_microtasks_scope_ = - std::make_unique(isolate, scope_type); + v8_microtasks_scope_ = std::make_unique( + isolate, microtask_queue, scope_type); } } diff --git a/shell/common/gin_helper/microtasks_scope.h b/shell/common/gin_helper/microtasks_scope.h index 23815a09081..a8d27d3ccbd 100644 --- a/shell/common/gin_helper/microtasks_scope.h +++ b/shell/common/gin_helper/microtasks_scope.h @@ -16,6 +16,7 @@ namespace gin_helper { class MicrotasksScope { public: explicit MicrotasksScope(v8::Isolate* isolate, + v8::MicrotaskQueue* microtask_queue, bool ignore_browser_checkpoint = false, v8::MicrotasksScope::Type scope_type = v8::MicrotasksScope::kRunMicrotasks); diff --git a/shell/common/gin_helper/promise.cc b/shell/common/gin_helper/promise.cc index bc34dfa6310..4ed2ecafd26 100644 --- a/shell/common/gin_helper/promise.cc +++ b/shell/common/gin_helper/promise.cc @@ -25,7 +25,8 @@ PromiseBase& PromiseBase::operator=(PromiseBase&&) = default; v8::Maybe PromiseBase::Reject() { v8::HandleScope handle_scope(isolate()); - gin_helper::MicrotasksScope microtasks_scope(isolate()); + gin_helper::MicrotasksScope microtasks_scope( + isolate(), GetContext()->GetMicrotaskQueue()); v8::Context::Scope context_scope(GetContext()); return GetInner()->Reject(GetContext(), v8::Undefined(isolate())); @@ -33,7 +34,8 @@ v8::Maybe PromiseBase::Reject() { v8::Maybe PromiseBase::Reject(v8::Local except) { v8::HandleScope handle_scope(isolate()); - gin_helper::MicrotasksScope microtasks_scope(isolate()); + gin_helper::MicrotasksScope microtasks_scope( + isolate(), GetContext()->GetMicrotaskQueue()); v8::Context::Scope context_scope(GetContext()); return GetInner()->Reject(GetContext(), except); @@ -41,7 +43,8 @@ v8::Maybe PromiseBase::Reject(v8::Local except) { v8::Maybe PromiseBase::RejectWithErrorMessage(base::StringPiece message) { v8::HandleScope handle_scope(isolate()); - gin_helper::MicrotasksScope microtasks_scope(isolate()); + gin_helper::MicrotasksScope microtasks_scope( + isolate(), GetContext()->GetMicrotaskQueue()); v8::Context::Scope context_scope(GetContext()); v8::Local error = @@ -83,7 +86,8 @@ v8::Local Promise::ResolvedPromise(v8::Isolate* isolate) { v8::Maybe Promise::Resolve() { v8::HandleScope handle_scope(isolate()); - gin_helper::MicrotasksScope microtasks_scope(isolate()); + gin_helper::MicrotasksScope microtasks_scope( + isolate(), GetContext()->GetMicrotaskQueue()); v8::Context::Scope context_scope(GetContext()); return GetInner()->Resolve(GetContext(), v8::Undefined(isolate())); diff --git a/shell/common/gin_helper/promise.h b/shell/common/gin_helper/promise.h index c720b588d77..4029cb505bf 100644 --- a/shell/common/gin_helper/promise.h +++ b/shell/common/gin_helper/promise.h @@ -118,7 +118,8 @@ class Promise : public PromiseBase { v8::Maybe Resolve(const RT& value) { gin_helper::Locker locker(isolate()); v8::HandleScope handle_scope(isolate()); - gin_helper::MicrotasksScope microtasks_scope(isolate()); + gin_helper::MicrotasksScope microtasks_scope( + isolate(), GetContext()->GetMicrotaskQueue()); v8::Context::Scope context_scope(GetContext()); return GetInner()->Resolve(GetContext(), diff --git a/shell/common/node_bindings.cc b/shell/common/node_bindings.cc index de5ca32838e..7f135bfc77d 100644 --- a/shell/common/node_bindings.cc +++ b/shell/common/node_bindings.cc @@ -192,11 +192,11 @@ v8::ModifyCodeGenerationFromStringsResult ModifyCodeGenerationFromStrings( void ErrorMessageListener(v8::Local message, v8::Local data) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - gin_helper::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); node::Environment* env = node::Environment::GetCurrent(isolate); - if (env) { + gin_helper::MicrotasksScope microtasks_scope( + isolate, env->context()->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); // Emit the after() hooks now that the exception has been handled. // Analogous to node/lib/internal/process/execution.js#L176-L180 if (env->async_hooks()->fields()[node::AsyncHooks::kAfter]) { @@ -684,9 +684,10 @@ void NodeBindings::UvRunOnce() { // checkpoints after every call into JavaScript. Since we use a different // policy in the renderer - switch to `kExplicit` and then drop back to the // previous policy value. - auto old_policy = env->isolate()->GetMicrotasksPolicy(); - DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(env->isolate()), 0); - env->isolate()->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); + v8::MicrotaskQueue* microtask_queue = env->context()->GetMicrotaskQueue(); + auto old_policy = microtask_queue->microtasks_policy(); + DCHECK_EQ(microtask_queue->GetMicrotasksScopeDepth(), 0); + microtask_queue->set_microtasks_policy(v8::MicrotasksPolicy::kExplicit); if (browser_env_ != BrowserEnvironment::kBrowser) TRACE_EVENT_BEGIN0("devtools.timeline", "FunctionCall"); @@ -697,7 +698,7 @@ void NodeBindings::UvRunOnce() { if (browser_env_ != BrowserEnvironment::kBrowser) TRACE_EVENT_END0("devtools.timeline", "FunctionCall"); - env->isolate()->SetMicrotasksPolicy(old_policy); + microtask_queue->set_microtasks_policy(old_policy); if (r == 0) base::RunLoop().QuitWhenIdle(); // Quit from uv. diff --git a/shell/common/v8_value_serializer.cc b/shell/common/v8_value_serializer.cc index 6ede4c21dbe..645797bcbb3 100644 --- a/shell/common/v8_value_serializer.cc +++ b/shell/common/v8_value_serializer.cc @@ -34,7 +34,8 @@ class V8Serializer : public v8::ValueSerializer::Delegate { bool Serialize(v8::Local value, blink::CloneableMessage* out) { gin_helper::MicrotasksScope microtasks_scope( - isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate_, isolate_->GetCurrentContext()->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); WriteBlinkEnvelope(19); serializer_.WriteHeader(); diff --git a/shell/renderer/api/electron_api_spell_check_client.cc b/shell/renderer/api/electron_api_spell_check_client.cc index 916022a5d70..77a2b428316 100644 --- a/shell/renderer/api/electron_api_spell_check_client.cc +++ b/shell/renderer/api/electron_api_spell_check_client.cc @@ -217,14 +217,14 @@ void SpellCheckClient::SpellCheckWords(const SpellCheckScope& scope, const std::set& words) { DCHECK(!scope.spell_check_.IsEmpty()); + auto context = isolate_->GetCurrentContext(); gin_helper::MicrotasksScope microtasks_scope( - isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate_, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Local templ = gin_helper::CreateFunctionTemplate( isolate_, base::BindRepeating(&SpellCheckClient::OnSpellCheckDone, AsWeakPtr())); - - auto context = isolate_->GetCurrentContext(); v8::Local args[] = {gin::ConvertToV8(isolate_, words), templ->GetFunction(context).ToLocalChecked()}; // Call javascript with the words and the callback function diff --git a/shell/renderer/electron_api_service_impl.cc b/shell/renderer/electron_api_service_impl.cc index 370f4290718..65fc61a2ce9 100644 --- a/shell/renderer/electron_api_service_impl.cc +++ b/shell/renderer/electron_api_service_impl.cc @@ -87,7 +87,7 @@ void EmitIPCEvent(v8::Local context, v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope(context); - v8::MicrotasksScope script_scope(isolate, + v8::MicrotasksScope script_scope(isolate, context->GetMicrotaskQueue(), v8::MicrotasksScope::kRunMicrotasks); std::vector> argv = { diff --git a/shell/renderer/electron_render_frame_observer.cc b/shell/renderer/electron_render_frame_observer.cc index 3fbdf4e5bbb..11fedbf35e1 100644 --- a/shell/renderer/electron_render_frame_observer.cc +++ b/shell/renderer/electron_render_frame_observer.cc @@ -67,9 +67,10 @@ void ElectronRenderFrameObserver::DidClearWindowObject() { !web_frame->IsOnInitialEmptyDocument()) { v8::Isolate* isolate = blink::MainThreadIsolate(); v8::HandleScope handle_scope(isolate); - v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Handle context = web_frame->MainWorldScriptContext(); + v8::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); // DidClearWindowObject only emits for the main world. DidInstallConditionalFeatures(context, MAIN_WORLD_ID); @@ -112,7 +113,8 @@ void ElectronRenderFrameObserver::DidInstallConditionalFeatures( auto* isolate = context->GetIsolate(); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); if (ShouldNotifyClient(world_id)) renderer_client_->DidCreateScriptContext(context, render_frame_); diff --git a/shell/renderer/electron_renderer_client.cc b/shell/renderer/electron_renderer_client.cc index 66cadfbcbed..50b5cde56eb 100644 --- a/shell/renderer/electron_renderer_client.cc +++ b/shell/renderer/electron_renderer_client.cc @@ -138,10 +138,10 @@ void ElectronRendererClient::WillReleaseScriptContext( // checkpoints after every call into JavaScript. Since we use a different // policy in the renderer - switch to `kExplicit` and then drop back to the // previous policy value. - v8::Isolate* isolate = context->GetIsolate(); - auto old_policy = isolate->GetMicrotasksPolicy(); - DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(isolate), 0); - isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); + v8::MicrotaskQueue* microtask_queue = context->GetMicrotaskQueue(); + auto old_policy = microtask_queue->microtasks_policy(); + DCHECK_EQ(microtask_queue->GetMicrotasksScopeDepth(), 0); + microtask_queue->set_microtasks_policy(v8::MicrotasksPolicy::kExplicit); node::FreeEnvironment(env); if (node_bindings_->uv_env() == nullptr) { @@ -149,7 +149,7 @@ void ElectronRendererClient::WillReleaseScriptContext( node_bindings_->set_isolate_data(nullptr); } - isolate->SetMicrotasksPolicy(old_policy); + microtask_queue->set_microtasks_policy(old_policy); // ElectronBindings is tracking node environments. electron_bindings_->EnvironmentDestroyed(env); diff --git a/shell/renderer/electron_sandboxed_renderer_client.cc b/shell/renderer/electron_sandboxed_renderer_client.cc index a73404ac026..a0e36ff3dc4 100644 --- a/shell/renderer/electron_sandboxed_renderer_client.cc +++ b/shell/renderer/electron_sandboxed_renderer_client.cc @@ -162,12 +162,12 @@ void ElectronSandboxedRendererClient::RunScriptsAtDocumentStart( return; auto* isolate = blink::MainThreadIsolate(); - gin_helper::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::HandleScope handle_scope(isolate); - v8::Local context = GetContext(render_frame->GetWebFrame(), isolate); + gin_helper::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); InvokeHiddenCallback(context, kLifecycleKey, "onDocumentStart"); @@ -180,12 +180,12 @@ void ElectronSandboxedRendererClient::RunScriptsAtDocumentEnd( return; auto* isolate = blink::MainThreadIsolate(); - gin_helper::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); v8::HandleScope handle_scope(isolate); - v8::Local context = GetContext(render_frame->GetWebFrame(), isolate); + gin_helper::MicrotasksScope microtasks_scope( + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::Context::Scope context_scope(context); InvokeHiddenCallback(context, kLifecycleKey, "onDocumentEnd"); @@ -230,7 +230,8 @@ void ElectronSandboxedRendererClient::WillReleaseScriptContext( auto* isolate = context->GetIsolate(); gin_helper::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); v8::HandleScope handle_scope(isolate); v8::Context::Scope context_scope(context); InvokeHiddenCallback(context, kLifecycleKey, "onExit"); diff --git a/shell/renderer/web_worker_observer.cc b/shell/renderer/web_worker_observer.cc index 0eb07182fad..7cf9c1cd696 100644 --- a/shell/renderer/web_worker_observer.cc +++ b/shell/renderer/web_worker_observer.cc @@ -41,11 +41,14 @@ WebWorkerObserver::~WebWorkerObserver() { // Node.js expects `kExplicit` microtasks policy and will run microtasks // checkpoints after every call into JavaScript. Since we use a different // policy in the renderer - switch to `kExplicit` - v8::Isolate* isolate = node_bindings_->uv_env()->isolate(); - DCHECK_EQ(v8::MicrotasksScope::GetCurrentDepth(isolate), 0); - isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit); + v8::MicrotaskQueue* microtask_queue = + node_bindings_->uv_env()->context()->GetMicrotaskQueue(); + auto old_policy = microtask_queue->microtasks_policy(); + DCHECK_EQ(microtask_queue->GetMicrotasksScopeDepth(), 0); + microtask_queue->set_microtasks_policy(v8::MicrotasksPolicy::kExplicit); node::FreeEnvironment(node_bindings_->uv_env()); node::FreeIsolateData(node_bindings_->isolate_data()); + microtask_queue->set_microtasks_policy(old_policy); } void WebWorkerObserver::WorkerScriptReadyForEvaluation( @@ -53,7 +56,8 @@ void WebWorkerObserver::WorkerScriptReadyForEvaluation( v8::Context::Scope context_scope(worker_context); auto* isolate = worker_context->GetIsolate(); v8::MicrotasksScope microtasks_scope( - isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + isolate, worker_context->GetMicrotaskQueue(), + v8::MicrotasksScope::kDoNotRunMicrotasks); // Start the embed thread. node_bindings_->PrepareEmbedThread();