diff options
author | Gus Caplan <me@gus.host> | 2018-08-18 01:26:34 +0300 |
---|---|---|
committer | Gus Caplan <me@gus.host> | 2018-10-07 01:33:25 +0300 |
commit | 4c37df779cf944b5666fc72e2a27fbf2e745881f (patch) | |
tree | 80d135f6cbd7cd9545bee950c280659985c276b8 /src/node_contextify.cc | |
parent | 124a8e21238f8452028614625fe491b3049f7244 (diff) |
vm: add dynamic import support
PR-URL: https://github.com/nodejs/node/pull/22381
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Guy Bedford <guybedford@gmail.com>
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
Diffstat (limited to 'src/node_contextify.cc')
-rw-r--r-- | src/node_contextify.cc | 618 |
1 files changed, 317 insertions, 301 deletions
diff --git a/src/node_contextify.cc b/src/node_contextify.cc index 4239f07f061..023a659ebb6 100644 --- a/src/node_contextify.cc +++ b/src/node_contextify.cc @@ -26,6 +26,7 @@ #include "node_contextify.h" #include "node_context_data.h" #include "node_errors.h" +#include "module_wrap.h" namespace node { namespace contextify { @@ -49,8 +50,10 @@ using v8::Maybe; using v8::MaybeLocal; using v8::Name; using v8::NamedPropertyHandlerConfiguration; +using v8::Number; using v8::Object; using v8::ObjectTemplate; +using v8::PrimitiveArray; using v8::PropertyAttribute; using v8::PropertyCallbackInfo; using v8::PropertyDescriptor; @@ -586,368 +589,381 @@ void ContextifyContext::IndexedPropertyDeleterCallback( args.GetReturnValue().Set(false); } -class ContextifyScript : public BaseObject { - private: - Persistent<UnboundScript> script_; - - public: - SET_NO_MEMORY_INFO() - SET_MEMORY_INFO_NAME(ContextifyScript) - SET_SELF_SIZE(ContextifyScript) - - static void Init(Environment* env, Local<Object> target) { - HandleScope scope(env->isolate()); - Local<String> class_name = - FIXED_ONE_BYTE_STRING(env->isolate(), "ContextifyScript"); - - Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New); - script_tmpl->InstanceTemplate()->SetInternalFieldCount(1); - script_tmpl->SetClassName(class_name); - env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData); - env->SetProtoMethod(script_tmpl, "runInContext", RunInContext); - env->SetProtoMethod(script_tmpl, "runInThisContext", RunInThisContext); - - target->Set(class_name, - script_tmpl->GetFunction(env->context()).ToLocalChecked()); - env->set_script_context_constructor_template(script_tmpl); - } - - - static void New(const FunctionCallbackInfo<Value>& args) { - Environment* env = Environment::GetCurrent(args); - Isolate* isolate = env->isolate(); - Local<Context> context = env->context(); - - CHECK(args.IsConstructCall()); - - const int argc = args.Length(); - CHECK_GE(argc, 2); - - CHECK(args[0]->IsString()); - Local<String> code = args[0].As<String>(); - - CHECK(args[1]->IsString()); - Local<String> filename = args[1].As<String>(); - - Local<Integer> line_offset; - Local<Integer> column_offset; - Local<Uint8Array> cached_data_buf; - bool produce_cached_data = false; - Local<Context> parsing_context = context; - - if (argc > 2) { - // new ContextifyScript(code, filename, lineOffset, columnOffset, - // cachedData, produceCachedData, parsingContext) - CHECK_EQ(argc, 7); - CHECK(args[2]->IsNumber()); - line_offset = args[2].As<Integer>(); - CHECK(args[3]->IsNumber()); - column_offset = args[3].As<Integer>(); - if (!args[4]->IsUndefined()) { - CHECK(args[4]->IsUint8Array()); - cached_data_buf = args[4].As<Uint8Array>(); - } - CHECK(args[5]->IsBoolean()); - produce_cached_data = args[5]->IsTrue(); - if (!args[6]->IsUndefined()) { - CHECK(args[6]->IsObject()); - ContextifyContext* sandbox = - ContextifyContext::ContextFromContextifiedSandbox( - env, args[6].As<Object>()); - CHECK_NOT_NULL(sandbox); - parsing_context = sandbox->context(); - } - } else { - line_offset = Integer::New(isolate, 0); - column_offset = Integer::New(isolate, 0); - } - - ContextifyScript* contextify_script = - new ContextifyScript(env, args.This()); - - if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( - TRACING_CATEGORY_NODE2(vm, script)) != 0) { - Utf8Value fn(isolate, filename); - TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( - TRACING_CATEGORY_NODE2(vm, script), - "ContextifyScript::New", - contextify_script, - "filename", TRACE_STR_COPY(*fn)); - } +void ContextifyScript::Init(Environment* env, Local<Object> target) { + HandleScope scope(env->isolate()); + Local<String> class_name = + FIXED_ONE_BYTE_STRING(env->isolate(), "ContextifyScript"); + + Local<FunctionTemplate> script_tmpl = env->NewFunctionTemplate(New); + script_tmpl->InstanceTemplate()->SetInternalFieldCount(1); + script_tmpl->SetClassName(class_name); + env->SetProtoMethod(script_tmpl, "createCachedData", CreateCachedData); + env->SetProtoMethod(script_tmpl, "runInContext", RunInContext); + env->SetProtoMethod(script_tmpl, "runInThisContext", RunInThisContext); + + target->Set(class_name, + script_tmpl->GetFunction(env->context()).ToLocalChecked()); + env->set_script_context_constructor_template(script_tmpl); +} - ScriptCompiler::CachedData* cached_data = nullptr; - if (!cached_data_buf.IsEmpty()) { - ArrayBuffer::Contents contents = cached_data_buf->Buffer()->GetContents(); - uint8_t* data = static_cast<uint8_t*>(contents.Data()); - cached_data = new ScriptCompiler::CachedData( - data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength()); - } +void ContextifyScript::New(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + Isolate* isolate = env->isolate(); + Local<Context> context = env->context(); - ScriptOrigin origin(filename, line_offset, column_offset); - ScriptCompiler::Source source(code, origin, cached_data); - ScriptCompiler::CompileOptions compile_options = - ScriptCompiler::kNoCompileOptions; + CHECK(args.IsConstructCall()); - if (source.GetCachedData() != nullptr) - compile_options = ScriptCompiler::kConsumeCodeCache; + const int argc = args.Length(); + CHECK_GE(argc, 2); - TryCatch try_catch(isolate); - Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env); - Context::Scope scope(parsing_context); + CHECK(args[0]->IsString()); + Local<String> code = args[0].As<String>(); - MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript( - isolate, - &source, - compile_options); + CHECK(args[1]->IsString()); + Local<String> filename = args[1].As<String>(); - if (v8_script.IsEmpty()) { - DecorateErrorStack(env, try_catch); - no_abort_scope.Close(); - try_catch.ReThrow(); - TRACE_EVENT_NESTABLE_ASYNC_END0( - TRACING_CATEGORY_NODE2(vm, script), - "ContextifyScript::New", - contextify_script); - return; + Local<Integer> line_offset; + Local<Integer> column_offset; + Local<Uint8Array> cached_data_buf; + bool produce_cached_data = false; + Local<Context> parsing_context = context; + + if (argc > 2) { + // new ContextifyScript(code, filename, lineOffset, columnOffset, + // cachedData, produceCachedData, parsingContext) + CHECK_EQ(argc, 7); + CHECK(args[2]->IsNumber()); + line_offset = args[2].As<Integer>(); + CHECK(args[3]->IsNumber()); + column_offset = args[3].As<Integer>(); + if (!args[4]->IsUndefined()) { + CHECK(args[4]->IsUint8Array()); + cached_data_buf = args[4].As<Uint8Array>(); } - contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked()); - - if (compile_options == ScriptCompiler::kConsumeCodeCache) { - args.This()->Set( - env->cached_data_rejected_string(), - Boolean::New(isolate, source.GetCachedData()->rejected)); - } else if (produce_cached_data) { - const ScriptCompiler::CachedData* cached_data = - ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked()); - bool cached_data_produced = cached_data != nullptr; - if (cached_data_produced) { - MaybeLocal<Object> buf = Buffer::Copy( - env, - reinterpret_cast<const char*>(cached_data->data), - cached_data->length); - args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); - } - args.This()->Set( - env->cached_data_produced_string(), - Boolean::New(isolate, cached_data_produced)); + CHECK(args[5]->IsBoolean()); + produce_cached_data = args[5]->IsTrue(); + if (!args[6]->IsUndefined()) { + CHECK(args[6]->IsObject()); + ContextifyContext* sandbox = + ContextifyContext::ContextFromContextifiedSandbox( + env, args[6].As<Object>()); + CHECK_NOT_NULL(sandbox); + parsing_context = sandbox->context(); } - TRACE_EVENT_NESTABLE_ASYNC_END0( + } else { + line_offset = Integer::New(isolate, 0); + column_offset = Integer::New(isolate, 0); + } + + ContextifyScript* contextify_script = + new ContextifyScript(env, args.This()); + + if (*TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( + TRACING_CATEGORY_NODE2(vm, script)) != 0) { + Utf8Value fn(isolate, filename); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN1( TRACING_CATEGORY_NODE2(vm, script), "ContextifyScript::New", - contextify_script); + contextify_script, + "filename", TRACE_STR_COPY(*fn)); } - - static bool InstanceOf(Environment* env, const Local<Value>& value) { - return !value.IsEmpty() && - env->script_context_constructor_template()->HasInstance(value); + ScriptCompiler::CachedData* cached_data = nullptr; + if (!cached_data_buf.IsEmpty()) { + ArrayBuffer::Contents contents = cached_data_buf->Buffer()->GetContents(); + uint8_t* data = static_cast<uint8_t*>(contents.Data()); + cached_data = new ScriptCompiler::CachedData( + data + cached_data_buf->ByteOffset(), cached_data_buf->ByteLength()); } + Local<PrimitiveArray> host_defined_options = + PrimitiveArray::New(isolate, loader::HostDefinedOptions::kLength); + host_defined_options->Set(isolate, loader::HostDefinedOptions::kType, + Number::New(isolate, loader::ScriptType::kScript)); + host_defined_options->Set(isolate, loader::HostDefinedOptions::kID, + Number::New(isolate, contextify_script->id())); + + ScriptOrigin origin(filename, + line_offset, // line offset + column_offset, // column offset + False(isolate), // is cross origin + Local<Integer>(), // script id + Local<Value>(), // source map URL + False(isolate), // is opaque (?) + False(isolate), // is WASM + False(isolate), // is ES Module + host_defined_options); + ScriptCompiler::Source source(code, origin, cached_data); + ScriptCompiler::CompileOptions compile_options = + ScriptCompiler::kNoCompileOptions; - static void CreateCachedData(const FunctionCallbackInfo<Value>& args) { - Environment* env = Environment::GetCurrent(args); - ContextifyScript* wrapped_script; - ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); - Local<UnboundScript> unbound_script = - PersistentToLocal(env->isolate(), wrapped_script->script_); - std::unique_ptr<ScriptCompiler::CachedData> cached_data( - ScriptCompiler::CreateCodeCache(unbound_script)); - if (!cached_data) { - args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked()); - } else { + if (source.GetCachedData() != nullptr) + compile_options = ScriptCompiler::kConsumeCodeCache; + + TryCatch try_catch(isolate); + Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env); + Context::Scope scope(parsing_context); + + MaybeLocal<UnboundScript> v8_script = ScriptCompiler::CompileUnboundScript( + isolate, + &source, + compile_options); + + if (v8_script.IsEmpty()) { + DecorateErrorStack(env, try_catch); + no_abort_scope.Close(); + try_catch.ReThrow(); + TRACE_EVENT_NESTABLE_ASYNC_END0( + TRACING_CATEGORY_NODE2(vm, script), + "ContextifyScript::New", + contextify_script); + return; + } + contextify_script->script_.Reset(isolate, v8_script.ToLocalChecked()); + + if (compile_options == ScriptCompiler::kConsumeCodeCache) { + args.This()->Set( + env->cached_data_rejected_string(), + Boolean::New(isolate, source.GetCachedData()->rejected)); + } else if (produce_cached_data) { + const ScriptCompiler::CachedData* cached_data = + ScriptCompiler::CreateCodeCache(v8_script.ToLocalChecked()); + bool cached_data_produced = cached_data != nullptr; + if (cached_data_produced) { MaybeLocal<Object> buf = Buffer::Copy( env, reinterpret_cast<const char*>(cached_data->data), cached_data->length); - args.GetReturnValue().Set(buf.ToLocalChecked()); + args.This()->Set(env->cached_data_string(), buf.ToLocalChecked()); } + args.This()->Set( + env->cached_data_produced_string(), + Boolean::New(isolate, cached_data_produced)); } + TRACE_EVENT_NESTABLE_ASYNC_END0( + TRACING_CATEGORY_NODE2(vm, script), + "ContextifyScript::New", + contextify_script); +} +bool ContextifyScript::InstanceOf(Environment* env, + const Local<Value>& value) { + return !value.IsEmpty() && + env->script_context_constructor_template()->HasInstance(value); +} - static void RunInThisContext(const FunctionCallbackInfo<Value>& args) { - Environment* env = Environment::GetCurrent(args); +void ContextifyScript::CreateCachedData( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + ContextifyScript* wrapped_script; + ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); + Local<UnboundScript> unbound_script = + PersistentToLocal(env->isolate(), wrapped_script->script_); + std::unique_ptr<ScriptCompiler::CachedData> cached_data( + ScriptCompiler::CreateCodeCache(unbound_script)); + if (!cached_data) { + args.GetReturnValue().Set(Buffer::New(env, 0).ToLocalChecked()); + } else { + MaybeLocal<Object> buf = Buffer::Copy( + env, + reinterpret_cast<const char*>(cached_data->data), + cached_data->length); + args.GetReturnValue().Set(buf.ToLocalChecked()); + } +} - ContextifyScript* wrapped_script; - ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); +void ContextifyScript::RunInThisContext( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); - TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( - TRACING_CATEGORY_NODE2(vm, script), "RunInThisContext", wrapped_script); + ContextifyScript* wrapped_script; + ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); - CHECK_EQ(args.Length(), 3); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( + TRACING_CATEGORY_NODE2(vm, script), "RunInThisContext", wrapped_script); - CHECK(args[0]->IsNumber()); - int64_t timeout = args[0]->IntegerValue(env->context()).FromJust(); + CHECK_EQ(args.Length(), 3); - CHECK(args[1]->IsBoolean()); - bool display_errors = args[1]->IsTrue(); + CHECK(args[0]->IsNumber()); + int64_t timeout = args[0]->IntegerValue(env->context()).FromJust(); - CHECK(args[2]->IsBoolean()); - bool break_on_sigint = args[2]->IsTrue(); + CHECK(args[1]->IsBoolean()); + bool display_errors = args[1]->IsTrue(); - // Do the eval within this context - EvalMachine(env, timeout, display_errors, break_on_sigint, args); + CHECK(args[2]->IsBoolean()); + bool break_on_sigint = args[2]->IsTrue(); - TRACE_EVENT_NESTABLE_ASYNC_END0( - TRACING_CATEGORY_NODE2(vm, script), "RunInThisContext", wrapped_script); - } + // Do the eval within this context + EvalMachine(env, timeout, display_errors, break_on_sigint, args); - static void RunInContext(const FunctionCallbackInfo<Value>& args) { - Environment* env = Environment::GetCurrent(args); + TRACE_EVENT_NESTABLE_ASYNC_END0( + TRACING_CATEGORY_NODE2(vm, script), "RunInThisContext", wrapped_script); +} - ContextifyScript* wrapped_script; - ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); +void ContextifyScript::RunInContext(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); - CHECK_EQ(args.Length(), 4); + ContextifyScript* wrapped_script; + ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder()); - CHECK(args[0]->IsObject()); - Local<Object> sandbox = args[0].As<Object>(); - // Get the context from the sandbox - ContextifyContext* contextify_context = - ContextifyContext::ContextFromContextifiedSandbox(env, sandbox); - CHECK_NOT_NULL(contextify_context); + CHECK_EQ(args.Length(), 4); - if (contextify_context->context().IsEmpty()) - return; + CHECK(args[0]->IsObject()); + Local<Object> sandbox = args[0].As<Object>(); + // Get the context from the sandbox + ContextifyContext* contextify_context = + ContextifyContext::ContextFromContextifiedSandbox(env, sandbox); + CHECK_NOT_NULL(contextify_context); - TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( - TRACING_CATEGORY_NODE2(vm, script), "RunInContext", wrapped_script); + if (contextify_context->context().IsEmpty()) + return; - CHECK(args[1]->IsNumber()); - int64_t timeout = args[1]->IntegerValue(env->context()).FromJust(); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( + TRACING_CATEGORY_NODE2(vm, script), "RunInContext", wrapped_script); - CHECK(args[2]->IsBoolean()); - bool display_errors = args[2]->IsTrue(); + CHECK(args[1]->IsNumber()); + int64_t timeout = args[1]->IntegerValue(env->context()).FromJust(); - CHECK(args[3]->IsBoolean()); - bool break_on_sigint = args[3]->IsTrue(); + CHECK(args[2]->IsBoolean()); + bool display_errors = args[2]->IsTrue(); - // Do the eval within the context - Context::Scope context_scope(contextify_context->context()); - EvalMachine(contextify_context->env(), - timeout, - display_errors, - break_on_sigint, - args); + CHECK(args[3]->IsBoolean()); + bool break_on_sigint = args[3]->IsTrue(); + + // Do the eval within the context + Context::Scope context_scope(contextify_context->context()); + EvalMachine(contextify_context->env(), + timeout, + display_errors, + break_on_sigint, + args); + + TRACE_EVENT_NESTABLE_ASYNC_END0( + TRACING_CATEGORY_NODE2(vm, script), "RunInContext", wrapped_script); +} - TRACE_EVENT_NESTABLE_ASYNC_END0( - TRACING_CATEGORY_NODE2(vm, script), "RunInContext", wrapped_script); - } +void ContextifyScript::DecorateErrorStack( + Environment* env, const TryCatch& try_catch) { + Local<Value> exception = try_catch.Exception(); - static void DecorateErrorStack(Environment* env, const TryCatch& try_catch) { - Local<Value> exception = try_catch.Exception(); + if (!exception->IsObject()) + return; - if (!exception->IsObject()) - return; + Local<Object> err_obj = exception.As<Object>(); - Local<Object> err_obj = exception.As<Object>(); + if (IsExceptionDecorated(env, err_obj)) + return; - if (IsExceptionDecorated(env, err_obj)) - return; + AppendExceptionLine(env, exception, try_catch.Message(), CONTEXTIFY_ERROR); + Local<Value> stack = err_obj->Get(env->stack_string()); + MaybeLocal<Value> maybe_value = + err_obj->GetPrivate( + env->context(), + env->arrow_message_private_symbol()); - AppendExceptionLine(env, exception, try_catch.Message(), CONTEXTIFY_ERROR); - Local<Value> stack = err_obj->Get(env->stack_string()); - MaybeLocal<Value> maybe_value = - err_obj->GetPrivate( - env->context(), - env->arrow_message_private_symbol()); + Local<Value> arrow; + if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) { + return; + } - Local<Value> arrow; - if (!(maybe_value.ToLocal(&arrow) && arrow->IsString())) { - return; - } + if (stack.IsEmpty() || !stack->IsString()) { + return; + } - if (stack.IsEmpty() || !stack->IsString()) { - return; - } + Local<String> decorated_stack = String::Concat( + env->isolate(), + String::Concat(env->isolate(), + arrow.As<String>(), + FIXED_ONE_BYTE_STRING(env->isolate(), "\n")), + stack.As<String>()); + err_obj->Set(env->stack_string(), decorated_stack); + err_obj->SetPrivate( + env->context(), + env->decorated_private_symbol(), + True(env->isolate())); +} - Local<String> decorated_stack = String::Concat( - env->isolate(), - String::Concat(env->isolate(), - arrow.As<String>(), - FIXED_ONE_BYTE_STRING(env->isolate(), "\n")), - stack.As<String>()); - err_obj->Set(env->stack_string(), decorated_stack); - err_obj->SetPrivate( - env->context(), - env->decorated_private_symbol(), - True(env->isolate())); +bool ContextifyScript::EvalMachine(Environment* env, + const int64_t timeout, + const bool display_errors, + const bool break_on_sigint, + const FunctionCallbackInfo<Value>& args) { + if (!env->can_call_into_js()) + return false; + if (!ContextifyScript::InstanceOf(env, args.Holder())) { + env->ThrowTypeError( + "Script methods can only be called on script instances."); + return false; + } + TryCatch try_catch(env->isolate()); + ContextifyScript* wrapped_script; + ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder(), false); + Local<UnboundScript> unbound_script = + PersistentToLocal(env->isolate(), wrapped_script->script_); + Local<Script> script = unbound_script->BindToCurrentContext(); + + MaybeLocal<Value> result; + bool timed_out = false; + bool received_signal = false; + if (break_on_sigint && timeout != -1) { + Watchdog wd(env->isolate(), timeout, &timed_out); + SigintWatchdog swd(env->isolate(), &received_signal); + result = script->Run(env->context()); + } else if (break_on_sigint) { + SigintWatchdog swd(env->isolate(), &received_signal); + result = script->Run(env->context()); + } else if (timeout != -1) { + Watchdog wd(env->isolate(), timeout, &timed_out); + result = script->Run(env->context()); + } else { + result = script->Run(env->context()); } - static bool EvalMachine(Environment* env, - const int64_t timeout, - const bool display_errors, - const bool break_on_sigint, - const FunctionCallbackInfo<Value>& args) { - if (!env->can_call_into_js()) - return false; - if (!ContextifyScript::InstanceOf(env, args.Holder())) { - env->ThrowTypeError( - "Script methods can only be called on script instances."); - return false; - } - TryCatch try_catch(env->isolate()); - ContextifyScript* wrapped_script; - ASSIGN_OR_RETURN_UNWRAP(&wrapped_script, args.Holder(), false); - Local<UnboundScript> unbound_script = - PersistentToLocal(env->isolate(), wrapped_script->script_); - Local<Script> script = unbound_script->BindToCurrentContext(); - - MaybeLocal<Value> result; - bool timed_out = false; - bool received_signal = false; - if (break_on_sigint && timeout != -1) { - Watchdog wd(env->isolate(), timeout, &timed_out); - SigintWatchdog swd(env->isolate(), &received_signal); - result = script->Run(env->context()); - } else if (break_on_sigint) { - SigintWatchdog swd(env->isolate(), &received_signal); - result = script->Run(env->context()); - } else if (timeout != -1) { - Watchdog wd(env->isolate(), timeout, &timed_out); - result = script->Run(env->context()); - } else { - result = script->Run(env->context()); + // Convert the termination exception into a regular exception. + if (timed_out || received_signal) { + env->isolate()->CancelTerminateExecution(); + // It is possible that execution was terminated by another timeout in + // which this timeout is nested, so check whether one of the watchdogs + // from this invocation is responsible for termination. + if (timed_out) { + node::THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout); + } else if (received_signal) { + node::THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env); } + } - // Convert the termination exception into a regular exception. - if (timed_out || received_signal) { - env->isolate()->CancelTerminateExecution(); - // It is possible that execution was terminated by another timeout in - // which this timeout is nested, so check whether one of the watchdogs - // from this invocation is responsible for termination. - if (timed_out) { - node::THROW_ERR_SCRIPT_EXECUTION_TIMEOUT(env, timeout); - } else if (received_signal) { - node::THROW_ERR_SCRIPT_EXECUTION_INTERRUPTED(env); - } + if (try_catch.HasCaught()) { + if (!timed_out && !received_signal && display_errors) { + // We should decorate non-termination exceptions + DecorateErrorStack(env, try_catch); } - if (try_catch.HasCaught()) { - if (!timed_out && !received_signal && display_errors) { - // We should decorate non-termination exceptions - DecorateErrorStack(env, try_catch); - } + // If there was an exception thrown during script execution, re-throw it. + // If one of the above checks threw, re-throw the exception instead of + // letting try_catch catch it. + // If execution has been terminated, but not by one of the watchdogs from + // this invocation, this will re-throw a `null` value. + try_catch.ReThrow(); - // If there was an exception thrown during script execution, re-throw it. - // If one of the above checks threw, re-throw the exception instead of - // letting try_catch catch it. - // If execution has been terminated, but not by one of the watchdogs from - // this invocation, this will re-throw a `null` value. - try_catch.ReThrow(); + return false; + } - return false; - } + args.GetReturnValue().Set(result.ToLocalChecked()); + return true; +} - args.GetReturnValue().Set(result.ToLocalChecked()); - return true; - } + +ContextifyScript::ContextifyScript(Environment* env, Local<Object> object) + : BaseObject(env, object), + id_(env->get_next_script_id()) { + MakeWeak(); + env->id_to_script_map.emplace(id_, this); +} - ContextifyScript(Environment* env, Local<Object> object) - : BaseObject(env, object) { - MakeWeak(); - } -}; +ContextifyScript::~ContextifyScript() { + env()->id_to_script_map.erase(id_); +} void ContextifyContext::CompileFunction( |