src: split RunBootstrapping()
Split `RunBootstrapping()` into `BootstrapInternalLoaders()` and `BootstrapNode()` from so the two can be snapshotted incrementally. PR-URL: https://github.com/nodejs/node/pull/27539 Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
a0d86befb5
commit
077859948d
@ -287,7 +287,7 @@ Environment* CreateEnvironment(IsolateData* isolate_data,
|
||||
Environment::kOwnsProcessState |
|
||||
Environment::kOwnsInspector));
|
||||
env->InitializeLibuv(per_process::v8_is_profiling);
|
||||
if (RunBootstrapping(env).IsEmpty()) {
|
||||
if (env->RunBootstrapping().IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -809,6 +809,10 @@ class Environment : public MemoryRetainer {
|
||||
int InitializeInspector(inspector::ParentInspectorHandle* parent_handle);
|
||||
#endif
|
||||
|
||||
v8::MaybeLocal<v8::Value> BootstrapInternalLoaders();
|
||||
v8::MaybeLocal<v8::Value> BootstrapNode();
|
||||
v8::MaybeLocal<v8::Value> RunBootstrapping();
|
||||
|
||||
inline size_t async_callback_scope_depth() const;
|
||||
inline void PushAsyncCallbackScope();
|
||||
inline void PopAsyncCallbackScope();
|
||||
|
139
src/node.cc
139
src/node.cc
@ -130,7 +130,6 @@ using options_parser::kAllowedInEnvironment;
|
||||
using options_parser::kDisallowedInEnvironment;
|
||||
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
using v8::EscapableHandleScope;
|
||||
using v8::Exception;
|
||||
using v8::Function;
|
||||
@ -277,99 +276,111 @@ void Environment::InitializeDiagnostics() {
|
||||
#endif
|
||||
}
|
||||
|
||||
MaybeLocal<Value> RunBootstrapping(Environment* env) {
|
||||
CHECK(!env->has_run_bootstrapping_code());
|
||||
|
||||
EscapableHandleScope scope(env->isolate());
|
||||
Isolate* isolate = env->isolate();
|
||||
Local<Context> context = env->context();
|
||||
|
||||
|
||||
// Add a reference to the global object
|
||||
Local<Object> global = context->Global();
|
||||
Local<Object> process = env->process_object();
|
||||
|
||||
// Setting global properties for the bootstrappers to use:
|
||||
// - global
|
||||
// Expose the global object as a property on itself
|
||||
// (Allows you to set stuff on `global` from anywhere in JavaScript.)
|
||||
global->Set(context, FIXED_ONE_BYTE_STRING(env->isolate(), "global"), global)
|
||||
.Check();
|
||||
|
||||
MaybeLocal<Value> Environment::BootstrapInternalLoaders() {
|
||||
EscapableHandleScope scope(isolate_);
|
||||
|
||||
// Create binding loaders
|
||||
std::vector<Local<String>> loaders_params = {
|
||||
env->process_string(),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "getLinkedBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "getInternalBinding"),
|
||||
env->primordials_string()};
|
||||
process_string(),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "getLinkedBinding"),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "getInternalBinding"),
|
||||
primordials_string()};
|
||||
std::vector<Local<Value>> loaders_args = {
|
||||
process,
|
||||
env->NewFunctionTemplate(binding::GetLinkedBinding)
|
||||
->GetFunction(context)
|
||||
process_object(),
|
||||
NewFunctionTemplate(binding::GetLinkedBinding)
|
||||
->GetFunction(context())
|
||||
.ToLocalChecked(),
|
||||
env->NewFunctionTemplate(binding::GetInternalBinding)
|
||||
->GetFunction(context)
|
||||
NewFunctionTemplate(binding::GetInternalBinding)
|
||||
->GetFunction(context())
|
||||
.ToLocalChecked(),
|
||||
env->primordials()};
|
||||
primordials()};
|
||||
|
||||
// Bootstrap internal loaders
|
||||
MaybeLocal<Value> loader_exports = ExecuteBootstrapper(
|
||||
env, "internal/bootstrap/loaders", &loaders_params, &loaders_args);
|
||||
if (loader_exports.IsEmpty()) {
|
||||
Local<Value> loader_exports;
|
||||
if (!ExecuteBootstrapper(
|
||||
this, "internal/bootstrap/loaders", &loaders_params, &loaders_args)
|
||||
.ToLocal(&loader_exports)) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
|
||||
Local<Object> loader_exports_obj =
|
||||
loader_exports.ToLocalChecked().As<Object>();
|
||||
CHECK(loader_exports->IsObject());
|
||||
Local<Object> loader_exports_obj = loader_exports.As<Object>();
|
||||
Local<Value> internal_binding_loader =
|
||||
loader_exports_obj->Get(context, env->internal_binding_string())
|
||||
loader_exports_obj->Get(context(), internal_binding_string())
|
||||
.ToLocalChecked();
|
||||
env->set_internal_binding_loader(internal_binding_loader.As<Function>());
|
||||
|
||||
CHECK(internal_binding_loader->IsFunction());
|
||||
set_internal_binding_loader(internal_binding_loader.As<Function>());
|
||||
Local<Value> require =
|
||||
loader_exports_obj->Get(context, env->require_string()).ToLocalChecked();
|
||||
env->set_native_module_require(require.As<Function>());
|
||||
loader_exports_obj->Get(context(), require_string()).ToLocalChecked();
|
||||
CHECK(require->IsFunction());
|
||||
set_native_module_require(require.As<Function>());
|
||||
|
||||
return scope.Escape(loader_exports);
|
||||
}
|
||||
|
||||
MaybeLocal<Value> Environment::BootstrapNode() {
|
||||
EscapableHandleScope scope(isolate_);
|
||||
|
||||
Local<Object> global = context()->Global();
|
||||
// TODO(joyeecheung): this can be done in JS land now.
|
||||
global->Set(context(), FIXED_ONE_BYTE_STRING(isolate_, "global"), global)
|
||||
.Check();
|
||||
|
||||
// process, require, internalBinding, isMainThread,
|
||||
// ownsProcessState, primordials
|
||||
std::vector<Local<String>> node_params = {
|
||||
env->process_string(),
|
||||
env->require_string(),
|
||||
env->internal_binding_string(),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "isMainThread"),
|
||||
FIXED_ONE_BYTE_STRING(isolate, "ownsProcessState"),
|
||||
env->primordials_string()};
|
||||
process_string(),
|
||||
require_string(),
|
||||
internal_binding_string(),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "isMainThread"),
|
||||
FIXED_ONE_BYTE_STRING(isolate_, "ownsProcessState"),
|
||||
primordials_string()};
|
||||
std::vector<Local<Value>> node_args = {
|
||||
process,
|
||||
require,
|
||||
internal_binding_loader,
|
||||
Boolean::New(isolate, env->is_main_thread()),
|
||||
Boolean::New(isolate, env->owns_process_state()),
|
||||
env->primordials()};
|
||||
process_object(),
|
||||
native_module_require(),
|
||||
internal_binding_loader(),
|
||||
Boolean::New(isolate_, is_main_thread()),
|
||||
Boolean::New(isolate_, owns_process_state()),
|
||||
primordials()};
|
||||
|
||||
MaybeLocal<Value> result = ExecuteBootstrapper(
|
||||
env, "internal/bootstrap/node", &node_params, &node_args);
|
||||
this, "internal/bootstrap/node", &node_params, &node_args);
|
||||
|
||||
Local<Object> env_var_proxy;
|
||||
if (!CreateEnvVarProxy(context, isolate, env->as_callback_data())
|
||||
if (!CreateEnvVarProxy(context(), isolate_, as_callback_data())
|
||||
.ToLocal(&env_var_proxy) ||
|
||||
process
|
||||
->Set(env->context(),
|
||||
FIXED_ONE_BYTE_STRING(env->isolate(), "env"),
|
||||
env_var_proxy)
|
||||
.IsNothing())
|
||||
process_object()
|
||||
->Set(
|
||||
context(), FIXED_ONE_BYTE_STRING(isolate_, "env"), env_var_proxy)
|
||||
.IsNothing()) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
|
||||
return scope.EscapeMaybe(result);
|
||||
}
|
||||
|
||||
MaybeLocal<Value> Environment::RunBootstrapping() {
|
||||
EscapableHandleScope scope(isolate_);
|
||||
|
||||
CHECK(!has_run_bootstrapping_code());
|
||||
|
||||
if (BootstrapInternalLoaders().IsEmpty()) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
|
||||
Local<Value> result;
|
||||
if (!BootstrapNode().ToLocal(&result)) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
|
||||
// Make sure that no request or handle is created during bootstrap -
|
||||
// if necessary those should be done in pre-execution.
|
||||
// TODO(joyeecheung): print handles/requests before aborting
|
||||
CHECK(env->req_wrap_queue()->IsEmpty());
|
||||
CHECK(env->handle_wrap_queue()->IsEmpty());
|
||||
CHECK(req_wrap_queue()->IsEmpty());
|
||||
CHECK(handle_wrap_queue()->IsEmpty());
|
||||
|
||||
env->set_has_run_bootstrapping_code(true);
|
||||
set_has_run_bootstrapping_code(true);
|
||||
|
||||
return scope.EscapeMaybe(result);
|
||||
return scope.Escape(result);
|
||||
}
|
||||
|
||||
void MarkBootstrapComplete(const FunctionCallbackInfo<Value>& args) {
|
||||
|
@ -275,7 +275,6 @@ void DefineZlibConstants(v8::Local<v8::Object> target);
|
||||
v8::Isolate* NewIsolate(v8::Isolate::CreateParams* params,
|
||||
uv_loop_t* event_loop,
|
||||
MultiIsolatePlatform* platform);
|
||||
v8::MaybeLocal<v8::Value> RunBootstrapping(Environment* env);
|
||||
v8::MaybeLocal<v8::Value> StartExecution(Environment* env,
|
||||
const char* main_script_id);
|
||||
v8::MaybeLocal<v8::Object> GetPerContextExports(v8::Local<v8::Context> context);
|
||||
|
@ -205,7 +205,7 @@ std::unique_ptr<Environment> NodeMainInstance::CreateMainEnvironment(
|
||||
return env;
|
||||
}
|
||||
|
||||
if (RunBootstrapping(env.get()).IsEmpty()) {
|
||||
if (env->RunBootstrapping().IsEmpty()) {
|
||||
*exit_code = 1;
|
||||
}
|
||||
|
||||
|
@ -271,7 +271,7 @@ void Worker::Run() {
|
||||
HandleScope handle_scope(isolate_);
|
||||
AsyncCallbackScope callback_scope(env_.get());
|
||||
env_->async_hooks()->push_async_ids(1, 0);
|
||||
if (!RunBootstrapping(env_.get()).IsEmpty()) {
|
||||
if (!env_->RunBootstrapping().IsEmpty()) {
|
||||
CreateEnvMessagePort(env_.get());
|
||||
if (is_stopped()) return;
|
||||
Debug(this, "Created message port for worker %llu", thread_id_);
|
||||
|
Loading…
x
Reference in New Issue
Block a user