From c1bc8118e3cbec0772d9f9ed222323444e35d27d Mon Sep 17 00:00:00 2001 From: Joyee Cheung Date: Tue, 13 Sep 2022 16:55:19 +0800 Subject: [PATCH] bootstrap: generate bootstrapper arguments in BuiltinLoader PR-URL: https://github.com/nodejs/node/pull/44488 Reviewed-By: Chengzhong Wu --- src/api/environment.cc | 22 +++-------- src/node.cc | 10 +---- src/node_builtins.cc | 89 ++++++++++++++++++++++++++++++++++++------ src/node_builtins.h | 12 ++++++ src/node_realm.cc | 46 ++++------------------ src/node_realm.h | 3 +- 6 files changed, 103 insertions(+), 79 deletions(-) diff --git a/src/api/environment.cc b/src/api/environment.cc index e1095037f3b997..49f63b60e22d25 100644 --- a/src/api/environment.cc +++ b/src/api/environment.cc @@ -492,11 +492,7 @@ MaybeLocal LoadEnvironment( builtins::BuiltinLoader::Add(name.c_str(), main_script_source_utf8); Realm* realm = env->principal_realm(); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> args = {realm->process_object(), - realm->builtin_module_require()}; - return realm->ExecuteBootstrapper(name.c_str(), &args); + return realm->ExecuteBootstrapper(name.c_str()); }); } @@ -734,19 +730,11 @@ Maybe InitializePrimordials(Local context) { nullptr}; for (const char** module = context_files; *module != nullptr; module++) { - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). Local arguments[] = {exports, primordials}; - MaybeLocal maybe_fn = - builtins::BuiltinLoader::LookupAndCompile(context, *module, nullptr); - Local fn; - if (!maybe_fn.ToLocal(&fn)) { - return Nothing(); - } - MaybeLocal result = - fn->Call(context, Undefined(isolate), arraysize(arguments), arguments); - // Execution failed during context creation. - if (result.IsEmpty()) { + if (builtins::BuiltinLoader::CompileAndCall( + context, *module, arraysize(arguments), arguments, nullptr) + .IsEmpty()) { + // Execution failed during context creation. return Nothing(); } } diff --git a/src/node.cc b/src/node.cc index 96cdcd3064f963..a4740977e690ac 100644 --- a/src/node.cc +++ b/src/node.cc @@ -275,15 +275,7 @@ MaybeLocal StartExecution(Environment* env, const char* main_script_id) { CHECK_NOT_NULL(main_script_id); Realm* realm = env->principal_realm(); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> arguments = {env->process_object(), - env->builtin_module_require(), - env->internal_binding_loader(), - env->primordials()}; - - return scope.EscapeMaybe( - realm->ExecuteBootstrapper(main_script_id, &arguments)); + return scope.EscapeMaybe(realm->ExecuteBootstrapper(main_script_id)); } MaybeLocal StartExecution(Environment* env, StartExecutionCallback cb) { diff --git a/src/node_builtins.cc b/src/node_builtins.cc index 356ec3acd0bf3a..1c6ad4f659fb6a 100644 --- a/src/node_builtins.cc +++ b/src/node_builtins.cc @@ -27,6 +27,7 @@ using v8::ScriptOrigin; using v8::Set; using v8::SideEffectType; using v8::String; +using v8::Undefined; using v8::Value; BuiltinLoader BuiltinLoader::instance_; @@ -390,8 +391,12 @@ MaybeLocal BuiltinLoader::LookupAndCompile( FIXED_ONE_BYTE_STRING(isolate, "exports"), FIXED_ONE_BYTE_STRING(isolate, "primordials"), }; - } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0) { - // internal/main/*: process, require, internalBinding, primordials + } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0 || + strncmp(id, + "internal/bootstrap/", + strlen("internal/bootstrap/")) == 0) { + // internal/main/*, internal/bootstrap/*: process, require, + // internalBinding, primordials parameters = { FIXED_ONE_BYTE_STRING(isolate, "process"), FIXED_ONE_BYTE_STRING(isolate, "require"), @@ -404,16 +409,6 @@ MaybeLocal BuiltinLoader::LookupAndCompile( FIXED_ONE_BYTE_STRING(isolate, "process"), FIXED_ONE_BYTE_STRING(isolate, "require"), }; - } else if (strncmp(id, - "internal/bootstrap/", - strlen("internal/bootstrap/")) == 0) { - // internal/bootstrap/*: process, require, internalBinding, primordials - parameters = { - FIXED_ONE_BYTE_STRING(isolate, "process"), - FIXED_ONE_BYTE_STRING(isolate, "require"), - FIXED_ONE_BYTE_STRING(isolate, "internalBinding"), - FIXED_ONE_BYTE_STRING(isolate, "primordials"), - }; } else { // others: exports, require, module, process, internalBinding, primordials parameters = { @@ -434,6 +429,76 @@ MaybeLocal BuiltinLoader::LookupAndCompile( return maybe; } +MaybeLocal BuiltinLoader::CompileAndCall(Local context, + const char* id, + Realm* realm) { + Isolate* isolate = context->GetIsolate(); + // Arguments must match the parameters specified in + // BuiltinLoader::LookupAndCompile(). + std::vector> arguments; + // Detects parameters of the scripts based on module ids. + // internal/bootstrap/loaders: process, getLinkedBinding, + // getInternalBinding, primordials + if (strcmp(id, "internal/bootstrap/loaders") == 0) { + Local get_linked_binding; + Local get_internal_binding; + if (!NewFunctionTemplate(isolate, binding::GetLinkedBinding) + ->GetFunction(context) + .ToLocal(&get_linked_binding) || + !NewFunctionTemplate(isolate, binding::GetInternalBinding) + ->GetFunction(context) + .ToLocal(&get_internal_binding)) { + return MaybeLocal(); + } + arguments = {realm->process_object(), + get_linked_binding, + get_internal_binding, + realm->primordials()}; + } else if (strncmp(id, "internal/main/", strlen("internal/main/")) == 0 || + strncmp(id, + "internal/bootstrap/", + strlen("internal/bootstrap/")) == 0) { + // internal/main/*, internal/bootstrap/*: process, require, + // internalBinding, primordials + arguments = {realm->process_object(), + realm->builtin_module_require(), + realm->internal_binding_loader(), + realm->primordials()}; + } else if (strncmp(id, "embedder_main_", strlen("embedder_main_")) == 0) { + // Synthetic embedder main scripts from LoadEnvironment(): process, require + arguments = { + realm->process_object(), + realm->builtin_module_require(), + }; + } else { + // This should be invoked with the other CompileAndCall() methods, as + // we are unable to generate the arguments. + // Currently there are two cases: + // internal/per_context/*: the arguments are generated in + // InitializePrimordials() + // all the other cases: the arguments are generated in the JS-land loader. + UNREACHABLE(); + } + return CompileAndCall( + context, id, arguments.size(), arguments.data(), realm->env()); +} + +MaybeLocal BuiltinLoader::CompileAndCall(Local context, + const char* id, + int argc, + Local argv[], + Environment* optional_env) { + // Arguments must match the parameters specified in + // BuiltinLoader::LookupAndCompile(). + MaybeLocal maybe_fn = LookupAndCompile(context, id, optional_env); + Local fn; + if (!maybe_fn.ToLocal(&fn)) { + return MaybeLocal(); + } + Local undefined = Undefined(context->GetIsolate()); + return fn->Call(context, undefined, argc, argv); +} + bool BuiltinLoader::CompileAllBuiltins(Local context) { BuiltinLoader* loader = GetInstance(); std::vector ids = loader->GetBuiltinIds(); diff --git a/src/node_builtins.h b/src/node_builtins.h index 90b158b84bb2a6..bc77bd4ae5a255 100644 --- a/src/node_builtins.h +++ b/src/node_builtins.h @@ -19,6 +19,8 @@ class PerProcessTest; namespace node { class SnapshotBuilder; class ExternalReferenceRegistry; +class Realm; + namespace builtins { using BuiltinSourceMap = std::map; @@ -51,6 +53,16 @@ class NODE_EXTERN_PRIVATE BuiltinLoader { const char* id, Environment* optional_env); + static v8::MaybeLocal CompileAndCall( + v8::Local context, + const char* id, + int argc, + v8::Local argv[], + Environment* optional_env); + + static v8::MaybeLocal CompileAndCall( + v8::Local context, const char* id, Realm* realm); + static v8::Local GetSourceObject(v8::Local context); // Returns config.gypi as a JSON string static v8::Local GetConfigString(v8::Isolate* isolate); diff --git a/src/node_realm.cc b/src/node_realm.cc index 4a1502b136fed1..00e0d42c3e0777 100644 --- a/src/node_realm.cc +++ b/src/node_realm.cc @@ -18,7 +18,6 @@ using v8::MaybeLocal; using v8::Object; using v8::SnapshotCreator; using v8::String; -using v8::Undefined; using v8::Value; Realm::Realm(Environment* env, @@ -157,20 +156,10 @@ void Realm::DeserializeProperties(const RealmSerializeInfo* info) { DoneBootstrapping(); } -MaybeLocal Realm::ExecuteBootstrapper( - const char* id, std::vector>* arguments) { +MaybeLocal Realm::ExecuteBootstrapper(const char* id) { EscapableHandleScope scope(isolate()); Local ctx = context(); - MaybeLocal maybe_fn = - BuiltinLoader::LookupAndCompile(ctx, id, env()); - - Local fn; - if (!maybe_fn.ToLocal(&fn)) { - return MaybeLocal(); - } - - MaybeLocal result = - fn->Call(ctx, Undefined(isolate()), arguments->size(), arguments->data()); + MaybeLocal result = BuiltinLoader::CompileAndCall(ctx, id, this); // If there was an error during bootstrap, it must be unrecoverable // (e.g. max call stack exceeded). Clear the stack so that the @@ -188,21 +177,9 @@ MaybeLocal Realm::ExecuteBootstrapper( MaybeLocal Realm::BootstrapInternalLoaders() { EscapableHandleScope scope(isolate_); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - std::vector> loaders_args = { - process_object(), - NewFunctionTemplate(isolate_, binding::GetLinkedBinding) - ->GetFunction(context()) - .ToLocalChecked(), - NewFunctionTemplate(isolate_, binding::GetInternalBinding) - ->GetFunction(context()) - .ToLocalChecked(), - primordials()}; - // Bootstrap internal loaders Local loader_exports; - if (!ExecuteBootstrapper("internal/bootstrap/loaders", &loaders_args) + if (!ExecuteBootstrapper("internal/bootstrap/loaders") .ToLocal(&loader_exports)) { return MaybeLocal(); } @@ -225,23 +202,14 @@ MaybeLocal Realm::BootstrapInternalLoaders() { MaybeLocal Realm::BootstrapNode() { EscapableHandleScope scope(isolate_); - // Arguments must match the parameters specified in - // BuiltinLoader::LookupAndCompile(). - // process, require, internalBinding, primordials - std::vector> node_args = {process_object(), - builtin_module_require(), - internal_binding_loader(), - primordials()}; - - MaybeLocal result = - ExecuteBootstrapper("internal/bootstrap/node", &node_args); + MaybeLocal result = ExecuteBootstrapper("internal/bootstrap/node"); if (result.IsEmpty()) { return MaybeLocal(); } if (!env_->no_browser_globals()) { - result = ExecuteBootstrapper("internal/bootstrap/browser", &node_args); + result = ExecuteBootstrapper("internal/bootstrap/browser"); if (result.IsEmpty()) { return MaybeLocal(); @@ -252,7 +220,7 @@ MaybeLocal Realm::BootstrapNode() { auto thread_switch_id = env_->is_main_thread() ? "internal/bootstrap/switches/is_main_thread" : "internal/bootstrap/switches/is_not_main_thread"; - result = ExecuteBootstrapper(thread_switch_id, &node_args); + result = ExecuteBootstrapper(thread_switch_id); if (result.IsEmpty()) { return MaybeLocal(); @@ -262,7 +230,7 @@ MaybeLocal Realm::BootstrapNode() { env_->owns_process_state() ? "internal/bootstrap/switches/does_own_process_state" : "internal/bootstrap/switches/does_not_own_process_state"; - result = ExecuteBootstrapper(process_state_switch_id, &node_args); + result = ExecuteBootstrapper(process_state_switch_id); if (result.IsEmpty()) { return MaybeLocal(); diff --git a/src/node_realm.h b/src/node_realm.h index 407a3729c32dee..74d8c33b39287a 100644 --- a/src/node_realm.h +++ b/src/node_realm.h @@ -67,8 +67,7 @@ class Realm : public MemoryRetainer { RealmSerializeInfo Serialize(v8::SnapshotCreator* creator); void DeserializeProperties(const RealmSerializeInfo* info); - v8::MaybeLocal ExecuteBootstrapper( - const char* id, std::vector>* arguments); + v8::MaybeLocal ExecuteBootstrapper(const char* id); v8::MaybeLocal BootstrapInternalLoaders(); v8::MaybeLocal BootstrapNode(); v8::MaybeLocal RunBootstrapping();