mirror of
https://github.com/nodejs/node.git
synced 2026-11-09 15:11:11 -05:00
Since SEA is very similar in principle to embedding functionality, it makes sense to share code paths where possible. This commit does so and addresses a `TODO` while doing so. It also adds a utility to directly run CJS code to the embedder startup callback, which comes in handy for this purpose. Finally, this commit is breaking because it aligns the behavior of `require()`ing internal modules; previously, embedders could use the `require` function that they received to do so. (If this is not considered breaking because accessing internals is not covered by the API, then this would need ABI compatibility patches for becoming fully non-breaking.) PR-URL: https://github.com/nodejs/node/pull/46825 Reviewed-By: Darshan Sen <raisinten@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
145 lines
4.2 KiB
C++
145 lines
4.2 KiB
C++
#include "node_main_instance.h"
|
|
#include <memory>
|
|
#if HAVE_OPENSSL
|
|
#include "crypto/crypto_util.h"
|
|
#endif // HAVE_OPENSSL
|
|
#include "debug_utils-inl.h"
|
|
#include "node_builtins.h"
|
|
#include "node_external_reference.h"
|
|
#include "node_internals.h"
|
|
#include "node_options-inl.h"
|
|
#include "node_realm.h"
|
|
#include "node_sea.h"
|
|
#include "node_snapshot_builder.h"
|
|
#include "node_snapshotable.h"
|
|
#include "node_v8_platform-inl.h"
|
|
#include "util-inl.h"
|
|
#if defined(LEAK_SANITIZER)
|
|
#include <sanitizer/lsan_interface.h>
|
|
#endif
|
|
|
|
#if HAVE_INSPECTOR
|
|
#include "inspector/worker_inspector.h" // ParentInspectorHandle
|
|
#endif
|
|
|
|
namespace node {
|
|
|
|
using v8::Context;
|
|
using v8::HandleScope;
|
|
using v8::Isolate;
|
|
using v8::Local;
|
|
using v8::Locker;
|
|
|
|
NodeMainInstance::NodeMainInstance(const SnapshotData* snapshot_data,
|
|
uv_loop_t* event_loop,
|
|
MultiIsolatePlatform* platform,
|
|
const std::vector<std::string>& args,
|
|
const std::vector<std::string>& exec_args)
|
|
: args_(args),
|
|
exec_args_(exec_args),
|
|
array_buffer_allocator_(ArrayBufferAllocator::Create()),
|
|
isolate_(nullptr),
|
|
platform_(platform),
|
|
isolate_data_(),
|
|
isolate_params_(std::make_unique<Isolate::CreateParams>()),
|
|
snapshot_data_(snapshot_data) {
|
|
isolate_params_->array_buffer_allocator = array_buffer_allocator_.get();
|
|
|
|
isolate_ =
|
|
NewIsolate(isolate_params_.get(), event_loop, platform, snapshot_data);
|
|
CHECK_NOT_NULL(isolate_);
|
|
|
|
// If the indexes are not nullptr, we are not deserializing
|
|
isolate_data_.reset(
|
|
CreateIsolateData(isolate_,
|
|
event_loop,
|
|
platform,
|
|
array_buffer_allocator_.get(),
|
|
snapshot_data->AsEmbedderWrapper().get()));
|
|
|
|
isolate_data_->max_young_gen_size =
|
|
isolate_params_->constraints.max_young_generation_size_in_bytes();
|
|
}
|
|
|
|
NodeMainInstance::~NodeMainInstance() {
|
|
if (isolate_params_ == nullptr) {
|
|
return;
|
|
}
|
|
// This should only be done on a main instance that owns its isolate.
|
|
platform_->UnregisterIsolate(isolate_);
|
|
isolate_->Dispose();
|
|
}
|
|
|
|
ExitCode NodeMainInstance::Run() {
|
|
Locker locker(isolate_);
|
|
Isolate::Scope isolate_scope(isolate_);
|
|
HandleScope handle_scope(isolate_);
|
|
|
|
ExitCode exit_code = ExitCode::kNoFailure;
|
|
DeleteFnPtr<Environment, FreeEnvironment> env =
|
|
CreateMainEnvironment(&exit_code);
|
|
CHECK_NOT_NULL(env);
|
|
|
|
Context::Scope context_scope(env->context());
|
|
Run(&exit_code, env.get());
|
|
return exit_code;
|
|
}
|
|
|
|
void NodeMainInstance::Run(ExitCode* exit_code, Environment* env) {
|
|
if (*exit_code == ExitCode::kNoFailure) {
|
|
bool is_sea = false;
|
|
#ifndef DISABLE_SINGLE_EXECUTABLE_APPLICATION
|
|
if (sea::IsSingleExecutable()) {
|
|
is_sea = true;
|
|
LoadEnvironment(env, sea::FindSingleExecutableCode());
|
|
}
|
|
#endif
|
|
if (!is_sea) {
|
|
LoadEnvironment(env, StartExecutionCallback{});
|
|
}
|
|
|
|
*exit_code =
|
|
SpinEventLoopInternal(env).FromMaybe(ExitCode::kGenericUserError);
|
|
}
|
|
|
|
#if defined(LEAK_SANITIZER)
|
|
__lsan_do_leak_check();
|
|
#endif
|
|
}
|
|
|
|
DeleteFnPtr<Environment, FreeEnvironment>
|
|
NodeMainInstance::CreateMainEnvironment(ExitCode* exit_code) {
|
|
*exit_code = ExitCode::kNoFailure; // Reset the exit code to 0
|
|
|
|
HandleScope handle_scope(isolate_);
|
|
|
|
// TODO(addaleax): This should load a real per-Isolate option, currently
|
|
// this is still effectively per-process.
|
|
if (isolate_data_->options()->track_heap_objects) {
|
|
isolate_->GetHeapProfiler()->StartTrackingHeapObjects(true);
|
|
}
|
|
|
|
Local<Context> context;
|
|
DeleteFnPtr<Environment, FreeEnvironment> env;
|
|
|
|
if (snapshot_data_ != nullptr) {
|
|
env.reset(CreateEnvironment(isolate_data_.get(),
|
|
Local<Context>(), // read from snapshot
|
|
args_,
|
|
exec_args_));
|
|
#if HAVE_OPENSSL
|
|
crypto::InitCryptoOnce(isolate_);
|
|
#endif // HAVE_OPENSSL
|
|
} else {
|
|
context = NewContext(isolate_);
|
|
CHECK(!context.IsEmpty());
|
|
Context::Scope context_scope(context);
|
|
env.reset(
|
|
CreateEnvironment(isolate_data_.get(), context, args_, exec_args_));
|
|
}
|
|
|
|
return env;
|
|
}
|
|
|
|
} // namespace node
|