summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/module_wrap.cc181
-rw-r--r--src/module_wrap.h8
-rw-r--r--src/node.cc12
-rw-r--r--src/node_config.cc3
-rw-r--r--src/node_internals.h5
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