diff options
author | Joyee Cheung <joyeec9h3@gmail.com> | 2022-03-24 16:37:08 +0300 |
---|---|---|
committer | Joyee Cheung <joyeec9h3@gmail.com> | 2022-03-31 14:29:12 +0300 |
commit | 37aee80643822c8c9ff35c906d034ecc8fc448d5 (patch) | |
tree | 65a9107f2ed3b7e4cdaf38936a1df65ccd25a587 /src | |
parent | 8a297ba3a0aa39afb7c84fceee4accff609b7cfe (diff) |
build: add --node-snapshot-main configure option
This adds a --build-snapshot runtime option which is currently only
supported by the node_mksnapshot binary, and a --node-snapshot-main
configure option that makes use it to run a custom script when
building the embedded snapshot. The idea is to have this experimental
feature in core as a configure-time feature for now, and investigate
the renaming V8 bugs before we make it available to more users via
making it a runtime option.
PR-URL: https://github.com/nodejs/node/pull/42466
Reviewed-By: Darshan Sen <raisinten@gmail.com>
Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com>
Reviewed-By: Khaidi Chu <i@2333.moe>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node.cc | 10 | ||||
-rw-r--r-- | src/node_binding.cc | 1 | ||||
-rw-r--r-- | src/node_external_reference.h | 1 | ||||
-rw-r--r-- | src/node_options.cc | 5 | ||||
-rw-r--r-- | src/node_options.h | 1 | ||||
-rw-r--r-- | src/node_snapshotable.cc | 81 | ||||
-rw-r--r-- | src/node_snapshotable.h | 2 |
7 files changed, 100 insertions, 1 deletions
diff --git a/src/node.cc b/src/node.cc index e503fd9f5b4..5ba03b75407 100644 --- a/src/node.cc +++ b/src/node.cc @@ -495,6 +495,10 @@ MaybeLocal<Value> StartExecution(Environment* env, StartExecutionCallback cb) { return StartExecution(env, "internal/main/inspect"); } + if (per_process::cli_options->build_snapshot) { + return StartExecution(env, "internal/main/mksnapshot"); + } + if (per_process::cli_options->print_help) { return StartExecution(env, "internal/main/print_help"); } @@ -1153,6 +1157,12 @@ int Start(int argc, char** argv) { return result.exit_code; } + if (per_process::cli_options->build_snapshot) { + fprintf(stderr, + "--build-snapshot is not yet supported in the node binary\n"); + return 1; + } + { bool use_node_snapshot = per_process::cli_options->per_isolate->node_snapshot; diff --git a/src/node_binding.cc b/src/node_binding.cc index 050c5dff0ad..ed8ab9237fd 100644 --- a/src/node_binding.cc +++ b/src/node_binding.cc @@ -59,6 +59,7 @@ V(js_udp_wrap) \ V(messaging) \ V(module_wrap) \ + V(mksnapshot) \ V(native_module) \ V(options) \ V(os) \ diff --git a/src/node_external_reference.h b/src/node_external_reference.h index c57a01ff39c..306c726631a 100644 --- a/src/node_external_reference.h +++ b/src/node_external_reference.h @@ -66,6 +66,7 @@ class ExternalReferenceRegistry { V(handle_wrap) \ V(heap_utils) \ V(messaging) \ + V(mksnapshot) \ V(native_module) \ V(options) \ V(os) \ diff --git a/src/node_options.cc b/src/node_options.cc index 35ee54d2231..bb568ce458a 100644 --- a/src/node_options.cc +++ b/src/node_options.cc @@ -725,6 +725,11 @@ PerProcessOptionsParser::PerProcessOptionsParser( "disable Object.prototype.__proto__", &PerProcessOptions::disable_proto, kAllowedInEnvironment); + AddOption("--build-snapshot", + "Generate a snapshot blob when the process exits." + "Currently only supported in the node_mksnapshot binary.", + &PerProcessOptions::build_snapshot, + kDisallowedInEnvironment); // 12.x renamed this inadvertently, so alias it for consistency within the // release line, while using the original name for consistency with older diff --git a/src/node_options.h b/src/node_options.h index 3335c12b8cd..7a73e6e5987 100644 --- a/src/node_options.h +++ b/src/node_options.h @@ -229,6 +229,7 @@ class PerProcessOptions : public Options { bool zero_fill_all_buffers = false; bool debug_arraybuffer_allocations = false; std::string disable_proto; + bool build_snapshot; std::vector<std::string> security_reverts; bool print_bash_completion = false; diff --git a/src/node_snapshotable.cc b/src/node_snapshotable.cc index 71b025df81e..327246743bb 100644 --- a/src/node_snapshotable.cc +++ b/src/node_snapshotable.cc @@ -18,12 +18,18 @@ namespace node { using v8::Context; +using v8::Function; +using v8::FunctionCallbackInfo; using v8::HandleScope; using v8::Isolate; using v8::Local; +using v8::MaybeLocal; using v8::Object; +using v8::ScriptCompiler; +using v8::ScriptOrigin; using v8::SnapshotCreator; using v8::StartupData; +using v8::String; using v8::TryCatch; using v8::Value; @@ -130,16 +136,36 @@ void SnapshotBuilder::Generate(SnapshotData* out, nullptr, node::EnvironmentFlags::kDefaultFlags, {}); + // TODO(joyeecheung): run env->InitializeInspector({}) here. // Run scripts in lib/internal/bootstrap/ { TryCatch bootstrapCatch(isolate); - v8::MaybeLocal<Value> result = env->RunBootstrapping(); + MaybeLocal<Value> result = env->RunBootstrapping(); if (bootstrapCatch.HasCaught()) { PrintCaughtException(isolate, context, bootstrapCatch); } result.ToLocalChecked(); } + // If --build-snapshot is true, lib/internal/main/mksnapshot.js would be + // loaded via LoadEnvironment() to execute process.argv[1] as the entry + // point (we currently only support this kind of entry point, but we + // could also explore snapshotting other kinds of execution modes + // in the future). + if (per_process::cli_options->build_snapshot) { + TryCatch bootstrapCatch(isolate); + // TODO(joyeecheung): we could use the result for something special, + // like setting up initializers that should be invoked at snapshot + // dehydration. + MaybeLocal<Value> result = + LoadEnvironment(env, StartExecutionCallback{}); + if (bootstrapCatch.HasCaught()) { + PrintCaughtException(isolate, context, bootstrapCatch); + } + result.ToLocalChecked(); + // TODO(joyeecheung): run SpinEventLoop here. + } + if (per_process::enabled_debug_list.enabled(DebugCategory::MKSNAPSHOT)) { env->PrintAllBaseObjects(); printf("Environment = %p\n", env); @@ -309,4 +335,57 @@ void SerializeBindingData(Environment* env, }); } +namespace mksnapshot { + +static void CompileSnapshotMain(const FunctionCallbackInfo<Value>& args) { + CHECK(args[0]->IsString()); + Local<String> filename = args[0].As<String>(); + Local<String> source = args[1].As<String>(); + Isolate* isolate = args.GetIsolate(); + Local<Context> context = isolate->GetCurrentContext(); + ScriptOrigin origin(isolate, filename, 0, 0, true); + // TODO(joyeecheung): do we need all of these? Maybe we would want a less + // internal version of them. + std::vector<Local<String>> parameters = { + FIXED_ONE_BYTE_STRING(isolate, "require"), + FIXED_ONE_BYTE_STRING(isolate, "__filename"), + FIXED_ONE_BYTE_STRING(isolate, "__dirname"), + }; + ScriptCompiler::Source script_source(source, origin); + Local<Function> fn; + if (ScriptCompiler::CompileFunctionInContext(context, + &script_source, + parameters.size(), + parameters.data(), + 0, + nullptr, + ScriptCompiler::kEagerCompile) + .ToLocal(&fn)) { + args.GetReturnValue().Set(fn); + } +} + +static void Initialize(Local<Object> target, + Local<Value> unused, + Local<Context> context, + void* priv) { + Environment* env = Environment::GetCurrent(context); + Isolate* isolate = context->GetIsolate(); + env->SetMethod(target, "compileSnapshotMain", CompileSnapshotMain); + target + ->Set(context, + FIXED_ONE_BYTE_STRING(isolate, "cleanups"), + v8::Array::New(isolate)) + .Check(); +} + +static void RegisterExternalReferences(ExternalReferenceRegistry* registry) { + registry->Register(CompileSnapshotMain); + registry->Register(MarkBootstrapComplete); +} +} // namespace mksnapshot } // namespace node + +NODE_MODULE_CONTEXT_AWARE_INTERNAL(mksnapshot, node::mksnapshot::Initialize) +NODE_MODULE_EXTERNAL_REFERENCE(mksnapshot, + node::mksnapshot::RegisterExternalReferences) diff --git a/src/node_snapshotable.h b/src/node_snapshotable.h index 1ccd9a93226..30b684eb68a 100644 --- a/src/node_snapshotable.h +++ b/src/node_snapshotable.h @@ -127,6 +127,8 @@ class SnapshotBuilder { public: static std::string Generate(const std::vector<std::string> args, const std::vector<std::string> exec_args); + + // Generate the snapshot into out. static void Generate(SnapshotData* out, const std::vector<std::string> args, const std::vector<std::string> exec_args); |