Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bootstrap: generate bootstrapper arguments in BuiltinLoader #44488

Merged
merged 1 commit into from Sep 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 5 additions & 17 deletions src/api/environment.cc
Expand Up @@ -456,11 +456,7 @@ MaybeLocal<Value> LoadEnvironment(
env->set_main_utf16(std::move(main_utf16));
Realm* realm = env->principal_realm();

// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
std::vector<Local<Value>> args = {realm->process_object(),
realm->builtin_module_require()};
return realm->ExecuteBootstrapper(name.c_str(), &args);
return realm->ExecuteBootstrapper(name.c_str());
});
}

Expand Down Expand Up @@ -699,19 +695,11 @@ Maybe<bool> InitializePrimordials(Local<Context> context) {
nullptr};

for (const char** module = context_files; *module != nullptr; module++) {
// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
Local<Value> arguments[] = {exports, primordials};
MaybeLocal<Function> maybe_fn =
builtins::BuiltinLoader::LookupAndCompile(context, *module, nullptr);
Local<Function> fn;
if (!maybe_fn.ToLocal(&fn)) {
return Nothing<bool>();
}
MaybeLocal<Value> 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<bool>();
}
}
Expand Down
10 changes: 1 addition & 9 deletions src/node.cc
Expand Up @@ -262,15 +262,7 @@ MaybeLocal<Value> 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<Local<Value>> 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<Value> StartExecution(Environment* env, StartExecutionCallback cb) {
Expand Down
89 changes: 77 additions & 12 deletions src/node_builtins.cc
Expand Up @@ -26,6 +26,7 @@ using v8::ScriptOrigin;
using v8::Set;
using v8::SideEffectType;
using v8::String;
using v8::Undefined;
using v8::Value;

BuiltinLoader BuiltinLoader::instance_;
Expand Down Expand Up @@ -352,8 +353,12 @@ MaybeLocal<Function> 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"),
Expand All @@ -366,16 +371,6 @@ MaybeLocal<Function> 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 = {
Expand All @@ -396,6 +391,76 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompile(
return maybe;
}

MaybeLocal<Value> BuiltinLoader::CompileAndCall(Local<Context> context,
const char* id,
Realm* realm) {
Isolate* isolate = context->GetIsolate();
// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
std::vector<Local<Value>> 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<Value> get_linked_binding;
Local<Value> 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<Value>();
}
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<Value> BuiltinLoader::CompileAndCall(Local<Context> context,
const char* id,
int argc,
Local<Value> argv[],
Environment* optional_env) {
// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
MaybeLocal<Function> maybe_fn = LookupAndCompile(context, id, optional_env);
Local<Function> fn;
if (!maybe_fn.ToLocal(&fn)) {
return MaybeLocal<Value>();
}
Local<Value> undefined = Undefined(context->GetIsolate());
return fn->Call(context, undefined, argc, argv);
}

bool BuiltinLoader::CompileAllBuiltins(Local<Context> context) {
BuiltinLoader* loader = GetInstance();
std::vector<std::string> ids = loader->GetBuiltinIds();
Expand Down
12 changes: 12 additions & 0 deletions src/node_builtins.h
Expand Up @@ -18,6 +18,8 @@ class PerProcessTest;
namespace node {
class SnapshotBuilder;
class ExternalReferenceRegistry;
class Realm;

namespace builtins {

using BuiltinSourceMap = std::map<std::string, UnionBytes>;
Expand Down Expand Up @@ -50,6 +52,16 @@ class NODE_EXTERN_PRIVATE BuiltinLoader {
const char* id,
Environment* optional_env);

static v8::MaybeLocal<v8::Value> CompileAndCall(
v8::Local<v8::Context> context,
const char* id,
int argc,
v8::Local<v8::Value> argv[],
Environment* optional_env);

static v8::MaybeLocal<v8::Value> CompileAndCall(
v8::Local<v8::Context> context, const char* id, Realm* realm);

static v8::Local<v8::Object> GetSourceObject(v8::Local<v8::Context> context);
// Returns config.gypi as a JSON string
static v8::Local<v8::String> GetConfigString(v8::Isolate* isolate);
Expand Down
46 changes: 7 additions & 39 deletions src/node_realm.cc
Expand Up @@ -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,
Expand Down Expand Up @@ -148,20 +147,10 @@ void Realm::DeserializeProperties(const RealmSerializeInfo* info) {
DoneBootstrapping();
}

MaybeLocal<Value> Realm::ExecuteBootstrapper(
const char* id, std::vector<Local<Value>>* arguments) {
MaybeLocal<Value> Realm::ExecuteBootstrapper(const char* id) {
EscapableHandleScope scope(isolate());
Local<Context> ctx = context();
MaybeLocal<Function> maybe_fn =
BuiltinLoader::LookupAndCompile(ctx, id, env());

Local<Function> fn;
if (!maybe_fn.ToLocal(&fn)) {
return MaybeLocal<Value>();
}

MaybeLocal<Value> result =
fn->Call(ctx, Undefined(isolate()), arguments->size(), arguments->data());
MaybeLocal<Value> 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
Expand All @@ -179,21 +168,9 @@ MaybeLocal<Value> Realm::ExecuteBootstrapper(
MaybeLocal<Value> Realm::BootstrapInternalLoaders() {
EscapableHandleScope scope(isolate_);

// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
std::vector<Local<Value>> loaders_args = {
process_object(),
NewFunctionTemplate(isolate_, binding::GetLinkedBinding)
->GetFunction(context())
.ToLocalChecked(),
NewFunctionTemplate(isolate_, binding::GetInternalBinding)
->GetFunction(context())
.ToLocalChecked(),
primordials()};

// Bootstrap internal loaders
Local<Value> loader_exports;
if (!ExecuteBootstrapper("internal/bootstrap/loaders", &loaders_args)
if (!ExecuteBootstrapper("internal/bootstrap/loaders")
.ToLocal(&loader_exports)) {
return MaybeLocal<Value>();
}
Expand All @@ -216,23 +193,14 @@ MaybeLocal<Value> Realm::BootstrapInternalLoaders() {
MaybeLocal<Value> Realm::BootstrapNode() {
EscapableHandleScope scope(isolate_);

// Arguments must match the parameters specified in
// BuiltinLoader::LookupAndCompile().
// process, require, internalBinding, primordials
std::vector<Local<Value>> node_args = {process_object(),
builtin_module_require(),
internal_binding_loader(),
primordials()};

MaybeLocal<Value> result =
ExecuteBootstrapper("internal/bootstrap/node", &node_args);
MaybeLocal<Value> result = ExecuteBootstrapper("internal/bootstrap/node");

if (result.IsEmpty()) {
return MaybeLocal<Value>();
}

if (!env_->no_browser_globals()) {
result = ExecuteBootstrapper("internal/bootstrap/browser", &node_args);
result = ExecuteBootstrapper("internal/bootstrap/browser");

if (result.IsEmpty()) {
return MaybeLocal<Value>();
Expand All @@ -243,7 +211,7 @@ MaybeLocal<Value> 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<Value>();
Expand All @@ -253,7 +221,7 @@ MaybeLocal<Value> 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<Value>();
Expand Down
3 changes: 1 addition & 2 deletions src/node_realm.h
Expand Up @@ -60,8 +60,7 @@ class Realm : public MemoryRetainer {
RealmSerializeInfo Serialize(v8::SnapshotCreator* creator);
void DeserializeProperties(const RealmSerializeInfo* info);

v8::MaybeLocal<v8::Value> ExecuteBootstrapper(
const char* id, std::vector<v8::Local<v8::Value>>* arguments);
v8::MaybeLocal<v8::Value> ExecuteBootstrapper(const char* id);
v8::MaybeLocal<v8::Value> BootstrapInternalLoaders();
v8::MaybeLocal<v8::Value> BootstrapNode();
v8::MaybeLocal<v8::Value> RunBootstrapping();
Expand Down