diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/module_wrap.cc | 181 | ||||
-rw-r--r-- | src/module_wrap.h | 8 | ||||
-rw-r--r-- | src/node.cc | 12 | ||||
-rw-r--r-- | src/node_config.cc | 3 | ||||
-rw-r--r-- | src/node_internals.h | 5 |
5 files changed, 174 insertions, 35 deletions
diff --git a/src/module_wrap.cc b/src/module_wrap.cc index eddc0d6d6e..daa7f9036a 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -7,6 +7,8 @@ #include "node_url.h" #include "util-inl.h" #include "node_internals.h" +#include "node_contextify.h" +#include "node_watchdog.h" namespace node { namespace loader { @@ -59,6 +61,7 @@ ModuleWrap::~ModuleWrap() { } module_.Reset(); + context_.Reset(); } void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { @@ -71,12 +74,6 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { return; } - if (args.Length() != 2) { - env->ThrowError("constructor must have exactly 2 arguments " - "(string, string)"); - return; - } - if (!args[0]->IsString()) { env->ThrowError("first argument is not a string"); return; @@ -91,20 +88,39 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { Local<String> url = args[1].As<String>(); + Local<Object> that = args.This(); + + Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env); + TryCatch try_catch(isolate); + + Local<Value> options = args[2]; + MaybeLocal<Integer> line_offset = contextify::GetLineOffsetArg(env, options); + MaybeLocal<Integer> column_offset = + contextify::GetColumnOffsetArg(env, options); + MaybeLocal<Context> maybe_context = contextify::GetContextArg(env, options); + + + if (try_catch.HasCaught()) { + no_abort_scope.Close(); + try_catch.ReThrow(); + return; + } + + Local<Context> context = maybe_context.FromMaybe(that->CreationContext()); Local<Module> module; // compile { ScriptOrigin origin(url, - Integer::New(isolate, 0), // line offset - Integer::New(isolate, 0), // column offset + line_offset.ToLocalChecked(), // line offset + column_offset.ToLocalChecked(), // column offset False(isolate), // is cross origin Local<Integer>(), // script id Local<Value>(), // source map URL False(isolate), // is opaque (?) False(isolate), // is WASM True(isolate)); // is ES6 module - TryCatch try_catch(isolate); + Context::Scope context_scope(context); ScriptCompiler::Source source(source_text, origin); if (!ScriptCompiler::CompileModule(isolate, &source).ToLocal(&module)) { CHECK(try_catch.HasCaught()); @@ -117,8 +133,6 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { } } - Local<Object> that = args.This(); - Local<Context> context = that->CreationContext(); Local<String> url_str = FIXED_ONE_BYTE_STRING(isolate, "url"); if (!that->Set(context, url_str, url).FromMaybe(false)) { @@ -126,6 +140,7 @@ void ModuleWrap::New(const FunctionCallbackInfo<Value>& args) { } ModuleWrap* obj = new ModuleWrap(env, that, module, url); + obj->context_.Reset(isolate, context); env->module_map.emplace(module->GetIdentityHash(), obj); Wrap(that, obj); @@ -142,15 +157,19 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) { return; } - Local<Function> resolver_arg = args[0].As<Function>(); - Local<Object> that = args.This(); - ModuleWrap* obj = Unwrap<ModuleWrap>(that); - CHECK_NE(obj, nullptr); - Local<Context> mod_context = that->CreationContext(); - if (obj->linked_) return; + + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, that); + + if (obj->linked_) + return; obj->linked_ = true; - Local<Module> module(obj->module_.Get(isolate)); + + Local<Function> resolver_arg = args[0].As<Function>(); + + Local<Context> mod_context = obj->context_.Get(isolate); + Local<Module> module = obj->module_.Get(isolate); Local<Array> promises = Array::New(isolate, module->GetModuleRequestsLength()); @@ -187,11 +206,9 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) { void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); Isolate* isolate = args.GetIsolate(); - Local<Object> that = args.This(); - Local<Context> context = that->CreationContext(); - - ModuleWrap* obj = Unwrap<ModuleWrap>(that); - CHECK_NE(obj, nullptr); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); + Local<Context> context = obj->context_.Get(isolate); Local<Module> module = obj->module_.Get(isolate); TryCatch try_catch(isolate); Maybe<bool> ok = @@ -214,14 +231,60 @@ void ModuleWrap::Instantiate(const FunctionCallbackInfo<Value>& args) { } void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); Isolate* isolate = args.GetIsolate(); - Local<Object> that = args.This(); - Local<Context> context = that->CreationContext(); - ModuleWrap* obj = Unwrap<ModuleWrap>(that); - CHECK_NE(obj, nullptr); - MaybeLocal<Value> result = obj->module_.Get(isolate)->Evaluate(context); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); + Local<Context> context = obj->context_.Get(isolate); + Local<Module> module = obj->module_.Get(isolate); - if (result.IsEmpty()) { + Environment::ShouldNotAbortOnUncaughtScope no_abort_scope(env); + TryCatch try_catch(isolate); + Maybe<int64_t> maybe_timeout = + contextify::GetTimeoutArg(env, args[0]); + Maybe<bool> maybe_break_on_sigint = + contextify::GetBreakOnSigintArg(env, args[0]); + + if (try_catch.HasCaught()) { + no_abort_scope.Close(); + try_catch.ReThrow(); + return; + } + + int64_t timeout = maybe_timeout.ToChecked(); + bool break_on_sigint = maybe_break_on_sigint.ToChecked(); + + bool timed_out = false; + bool received_signal = false; + MaybeLocal<Value> result; + if (break_on_sigint && timeout != -1) { + Watchdog wd(isolate, timeout, &timed_out); + SigintWatchdog swd(isolate, &received_signal); + result = module->Evaluate(context); + } else if (break_on_sigint) { + SigintWatchdog swd(isolate, &received_signal); + result = module->Evaluate(context); + } else if (timeout != -1) { + Watchdog wd(isolate, timeout, &timed_out); + result = module->Evaluate(context); + } else { + result = module->Evaluate(context); + } + + if (timed_out || received_signal) { + // 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) { + env->ThrowError("Script execution timed out."); + } else if (received_signal) { + env->ThrowError("Script execution interrupted."); + } + env->isolate()->CancelTerminateExecution(); + } + + if (try_catch.HasCaught()) { + try_catch.ReThrow(); return; } @@ -231,9 +294,8 @@ void ModuleWrap::Evaluate(const FunctionCallbackInfo<Value>& args) { void ModuleWrap::Namespace(const FunctionCallbackInfo<Value>& args) { Environment* env = Environment::GetCurrent(args); Isolate* isolate = args.GetIsolate(); - Local<Object> that = args.This(); - ModuleWrap* obj = Unwrap<ModuleWrap>(that); - CHECK_NE(obj, nullptr); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); Local<Module> module = obj->module_.Get(isolate); @@ -251,6 +313,44 @@ void ModuleWrap::Namespace(const FunctionCallbackInfo<Value>& args) { args.GetReturnValue().Set(result); } +void ModuleWrap::GetStatus(const FunctionCallbackInfo<Value>& args) { + Isolate* isolate = args.GetIsolate(); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); + + Local<Module> module = obj->module_.Get(isolate); + + args.GetReturnValue().Set(module->GetStatus()); +} + +void ModuleWrap::GetStaticDependencySpecifiers( + const FunctionCallbackInfo<Value>& args) { + Environment* env = Environment::GetCurrent(args); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); + + Local<Module> module = obj->module_.Get(env->isolate()); + + int count = module->GetModuleRequestsLength(); + + Local<Array> specifiers = Array::New(env->isolate(), count); + + for (int i = 0; i < count; i++) + specifiers->Set(env->context(), i, module->GetModuleRequest(i)).FromJust(); + + args.GetReturnValue().Set(specifiers); +} + +void ModuleWrap::GetError(const FunctionCallbackInfo<Value>& args) { + Isolate* isolate = args.GetIsolate(); + ModuleWrap* obj; + ASSIGN_OR_RETURN_UNWRAP(&obj, args.This()); + + Local<Module> module = obj->module_.Get(isolate); + + args.GetReturnValue().Set(module->GetException()); +} + MaybeLocal<Module> ModuleWrap::ResolveCallback(Local<Context> context, Local<String> specifier, Local<Module> referrer) { @@ -642,12 +742,29 @@ void ModuleWrap::Initialize(Local<Object> target, env->SetProtoMethod(tpl, "instantiate", Instantiate); env->SetProtoMethod(tpl, "evaluate", Evaluate); env->SetProtoMethod(tpl, "namespace", Namespace); + env->SetProtoMethod(tpl, "getStatus", GetStatus); + env->SetProtoMethod(tpl, "getError", GetError); + env->SetProtoMethod(tpl, "getStaticDependencySpecifiers", + GetStaticDependencySpecifiers); target->Set(FIXED_ONE_BYTE_STRING(isolate, "ModuleWrap"), tpl->GetFunction()); env->SetMethod(target, "resolve", node::loader::ModuleWrap::Resolve); env->SetMethod(target, "setImportModuleDynamicallyCallback", node::loader::ModuleWrap::SetImportModuleDynamicallyCallback); + +#define V(name) \ + target->Set(context, \ + FIXED_ONE_BYTE_STRING(env->isolate(), #name), \ + Integer::New(env->isolate(), Module::Status::name)) \ + .FromJust() + V(kUninstantiated); + V(kInstantiating); + V(kInstantiated); + V(kEvaluating); + V(kEvaluated); + V(kErrored); +#undef V } } // namespace loader diff --git a/src/module_wrap.h b/src/module_wrap.h index ec4d6bf577..bedf665165 100644 --- a/src/module_wrap.h +++ b/src/module_wrap.h @@ -36,8 +36,11 @@ class ModuleWrap : public BaseObject { static void Instantiate(const v8::FunctionCallbackInfo<v8::Value>& args); static void Evaluate(const v8::FunctionCallbackInfo<v8::Value>& args); static void Namespace(const v8::FunctionCallbackInfo<v8::Value>& args); - static void GetUrl(v8::Local<v8::String> property, - const v8::PropertyCallbackInfo<v8::Value>& info); + static void GetStatus(const v8::FunctionCallbackInfo<v8::Value>& args); + static void GetError(const v8::FunctionCallbackInfo<v8::Value>& args); + static void GetStaticDependencySpecifiers( + const v8::FunctionCallbackInfo<v8::Value>& args); + static void Resolve(const v8::FunctionCallbackInfo<v8::Value>& args); static void SetImportModuleDynamicallyCallback( const v8::FunctionCallbackInfo<v8::Value>& args); @@ -50,6 +53,7 @@ class ModuleWrap : public BaseObject { v8::Persistent<v8::String> url_; bool linked_ = false; std::unordered_map<std::string, v8::Persistent<v8::Promise>> resolve_cache_; + v8::Persistent<v8::Context> context_; }; } // namespace loader diff --git a/src/node.cc b/src/node.cc index 39f441b1ea..0a466d20c9 100644 --- a/src/node.cc +++ b/src/node.cc @@ -241,6 +241,11 @@ bool config_preserve_symlinks = false; // that is used by lib/module.js bool config_experimental_modules = false; +// Set in node.cc by ParseArgs when --experimental-vm-modules is used. +// Used in node_config.cc to set a constant on process.binding('config') +// that is used by lib/vm.js +bool config_experimental_vm_modules = false; + // Set in node.cc by ParseArgs when --loader is used. // Used in node_config.cc to set a constant on process.binding('config') // that is used by lib/internal/bootstrap_node.js @@ -3775,6 +3780,8 @@ static void PrintHelp() { " --preserve-symlinks preserve symbolic links when resolving\n" " --experimental-modules experimental ES Module support\n" " and caching modules\n" + " --experimental-vm-modules experimental ES Module support\n" + " in vm module\n" #endif "\n" "Environment variables:\n" @@ -3854,6 +3861,7 @@ static void CheckIfAllowedInEnv(const char* exe, bool is_env, "--napi-modules", "--expose-http2", // keep as a non-op through v9.x "--experimental-modules", + "--experimental-vm-modules", "--loader", "--trace-warnings", "--redirect-warnings", @@ -4025,7 +4033,9 @@ static void ParseArgs(int* argc, config_experimental_modules = true; new_v8_argv[new_v8_argc] = "--harmony-dynamic-import"; new_v8_argc += 1; - } else if (strcmp(arg, "--loader") == 0) { + } else if (strcmp(arg, "--experimental-vm-modules") == 0) { + config_experimental_vm_modules = true; + } else if (strcmp(arg, "--loader") == 0) { const char* module = argv[index + 1]; if (!config_experimental_modules) { fprintf(stderr, "%s: %s requires --experimental-modules be enabled\n", diff --git a/src/node_config.cc b/src/node_config.cc index 2e9ad2ed13..cac551ad2c 100644 --- a/src/node_config.cc +++ b/src/node_config.cc @@ -82,6 +82,9 @@ static void InitConfig(Local<Object> target, } } + if (config_experimental_vm_modules) + READONLY_BOOLEAN_PROPERTY("experimentalVMModules"); + if (config_pending_deprecation) READONLY_BOOLEAN_PROPERTY("pendingDeprecation"); diff --git a/src/node_internals.h b/src/node_internals.h index 469d872336..ced92da321 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -172,6 +172,11 @@ extern bool config_preserve_symlinks; // that is used by lib/module.js extern bool config_experimental_modules; +// Set in node.cc by ParseArgs when --experimental-vm-modules is used. +// Used in node_config.cc to set a constant on process.binding('config') +// that is used by lib/vm.js +extern bool config_experimental_vm_modules; + // Set in node.cc by ParseArgs when --loader is used. // Used in node_config.cc to set a constant on process.binding('config') // that is used by lib/internal/bootstrap_node.js |