diff --git a/src/api/environment.cc b/src/api/environment.cc index 6a56ddb5117958..cd3e3aefc2ccfd 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -23,6 +23,7 @@ using v8::MaybeLocal; using v8::Message; using v8::MicrotasksPolicy; using v8::ObjectTemplate; +using v8::SealHandleScope; using v8::String; using v8::Value; @@ -34,7 +35,9 @@ static bool AllowWasmCodeGenerationCallback(Local context, } static bool ShouldAbortOnUncaughtException(Isolate* isolate) { - HandleScope scope(isolate); +#ifdef DEBUG + SealHandleScope scope(isolate); +#endif Environment* env = Environment::GetCurrent(isolate); return env != nullptr && (env->is_main_thread() || !env->is_stopping_worker()) && diff --git a/src/api/exceptions.cc b/src/api/exceptions.cc index 897a4de365283b..ceac9374082ad8 100644 --- a/src/api/exceptions.cc +++ b/src/api/exceptions.cc @@ -28,6 +28,7 @@ Local ErrnoException(Isolate* isolate, const char* msg, const char* path) { Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); Local e; Local estring = OneByteString(isolate, errors::errno_string(errorno)); @@ -99,6 +100,7 @@ Local UVException(Isolate* isolate, const char* path, const char* dest) { Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); if (!msg || !msg[0]) msg = uv_strerror(errorno); @@ -187,6 +189,7 @@ Local WinapiErrnoException(Isolate* isolate, const char* msg, const char* path) { Environment* env = Environment::GetCurrent(isolate); + CHECK_NOT_NULL(env); Local e; bool must_free = false; if (!msg || !msg[0]) { diff --git a/src/api/hooks.cc b/src/api/hooks.cc index b54292638ddf95..aa647778d51537 100644 --- a/src/api/hooks.cc +++ b/src/api/hooks.cc @@ -11,6 +11,7 @@ using v8::Integer; using v8::Isolate; using v8::Local; using v8::Object; +using v8::SealHandleScope; using v8::String; using v8::Value; using v8::NewStringType; @@ -88,16 +89,12 @@ void RemoveEnvironmentCleanupHook(Isolate* isolate, } async_id AsyncHooksGetExecutionAsyncId(Isolate* isolate) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); Environment* env = Environment::GetCurrent(isolate); if (env == nullptr) return -1; return env->execution_async_id(); } async_id AsyncHooksGetTriggerAsyncId(Isolate* isolate) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); Environment* env = Environment::GetCurrent(isolate); if (env == nullptr) return -1; return env->trigger_async_id(); @@ -119,7 +116,9 @@ async_context EmitAsyncInit(Isolate* isolate, Local resource, Local name, async_id trigger_async_id) { - HandleScope handle_scope(isolate); +#ifdef DEBUG + SealHandleScope handle_scope(isolate); +#endif Environment* env = Environment::GetCurrent(isolate); CHECK_NOT_NULL(env); @@ -140,8 +139,6 @@ async_context EmitAsyncInit(Isolate* isolate, } void EmitAsyncDestroy(Isolate* isolate, async_context asyncContext) { - // Environment::GetCurrent() allocates a Local<> handle. - HandleScope handle_scope(isolate); AsyncWrap::EmitDestroy( Environment::GetCurrent(isolate), asyncContext.async_id); } diff --git a/src/env-inl.h b/src/env-inl.h index 9752613b292368..7b12fa8e9aa7b0 100644 --- a/src/env-inl.h +++ b/src/env-inl.h @@ -296,6 +296,8 @@ inline void Environment::AssignToContext(v8::Local context, } inline Environment* Environment::GetCurrent(v8::Isolate* isolate) { + if (UNLIKELY(!isolate->InContext())) return nullptr; + v8::HandleScope handle_scope(isolate); return GetCurrent(isolate->GetCurrentContext()); } diff --git a/src/inspector/main_thread_interface.cc b/src/inspector/main_thread_interface.cc index 25a82864c1ee3a..3aa6a86a948923 100644 --- a/src/inspector/main_thread_interface.cc +++ b/src/inspector/main_thread_interface.cc @@ -287,6 +287,14 @@ void MainThreadInterface::DispatchMessages() { MessageQueue::value_type task; std::swap(dispatching_message_queue_.front(), task); dispatching_message_queue_.pop_front(); + + // TODO(addaleax): The V8 inspector code currently sometimes allocates + // handles that leak to the outside scope, rendering a HandleScope here + // necessary. This handle scope can be removed/turned into a + // SealHandleScope once/if + // https://chromium-review.googlesource.com/c/v8/v8/+/1484304 makes it + // into our copy of V8, maybe guarded with #ifdef DEBUG if we want. + v8::HandleScope handle_scope(isolate_); task->Call(this); } } while (had_messages); diff --git a/src/node_errors.cc b/src/node_errors.cc index 17394c863cd079..2f2700655946d9 100644 --- a/src/node_errors.cc +++ b/src/node_errors.cc @@ -314,7 +314,6 @@ void OnFatalError(const char* location, const char* message) { } #ifdef NODE_REPORT Isolate* isolate = Isolate::GetCurrent(); - HandleScope handle_scope(isolate); Environment* env = Environment::GetCurrent(isolate); if (env == nullptr || env->isolate_data()->options()->report_on_fatalerror) { report::TriggerNodeReport( diff --git a/src/node_perf.cc b/src/node_perf.cc index 908c76c2110d26..e16be29a872f80 100644 --- a/src/node_perf.cc +++ b/src/node_perf.cc @@ -333,10 +333,9 @@ inline Local GetName(Local fn) { // execution. void TimerFunctionCall(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); - HandleScope scope(isolate); - Environment* env = Environment::GetCurrent(isolate); + Local context = isolate->GetCurrentContext(); + Environment* env = Environment::GetCurrent(context); CHECK_NOT_NULL(env); - Local context = env->context(); Local fn = args.Data().As(); size_t count = args.Length(); size_t idx; diff --git a/src/node_platform.cc b/src/node_platform.cc index 139e2ebfc1f5ec..c671d86daff437 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -8,11 +8,11 @@ namespace node { -using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Object; using v8::Platform; +using v8::SealHandleScope; using v8::Task; using node::tracing::TracingController; @@ -332,11 +332,17 @@ int NodePlatform::NumberOfWorkerThreads() { void PerIsolatePlatformData::RunForegroundTask(std::unique_ptr task) { Isolate* isolate = Isolate::GetCurrent(); - HandleScope scope(isolate); +#ifdef DEBUG + SealHandleScope scope(isolate); +#endif Environment* env = Environment::GetCurrent(isolate); - InternalCallbackScope cb_scope(env, Local(), { 0, 0 }, - InternalCallbackScope::kAllowEmptyResource); - task->Run(); + if (env != nullptr) { + InternalCallbackScope cb_scope(env, Local(), { 0, 0 }, + InternalCallbackScope::kAllowEmptyResource); + task->Run(); + } else { + task->Run(); + } } void PerIsolatePlatformData::DeleteFromScheduledTasks(DelayedTask* task) {