in shell/app/node_main.cc [140:303]
int NodeMain(int argc, char* argv[]) {
base::CommandLine::Init(argc, argv);
#if defined(OS_WIN)
v8_crashpad_support::SetUp();
#endif
#if !defined(MAS_BUILD)
ElectronCrashReporterClient::Create();
#endif
#if defined(OS_WIN) || (defined(OS_MAC) && !defined(MAS_BUILD))
crash_reporter::InitializeCrashpad(false, "node");
#endif
#if !defined(MAS_BUILD)
crash_keys::SetCrashKeysFromCommandLine(
*base::CommandLine::ForCurrentProcess());
crash_keys::SetPlatformCrashKey();
#endif
int exit_code = 1;
{
// Feed gin::PerIsolateData with a task runner.
uv_loop_t* loop = uv_default_loop();
auto uv_task_runner = base::MakeRefCounted<UvTaskRunner>(loop);
base::ThreadTaskRunnerHandle handle(uv_task_runner);
// Initialize feature list.
auto feature_list = std::make_unique<base::FeatureList>();
feature_list->InitializeFromCommandLine("", "");
base::FeatureList::SetInstance(std::move(feature_list));
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
// Parse and set Node.js cli flags.
int flags_exit_code = SetNodeCliFlags();
if (flags_exit_code != 0)
exit(flags_exit_code);
node::InitializationSettingsFlags flags = node::kRunPlatformInit;
node::InitializationResult result =
node::InitializeOncePerProcess(argc, argv, flags);
if (result.early_return)
exit(result.exit_code);
gin::V8Initializer::LoadV8Snapshot(
gin::V8SnapshotFileType::kWithAdditionalContext);
// V8 requires a task scheduler.
base::ThreadPoolInstance::CreateAndStartWithDefaultParams("Electron");
// Allow Node.js to track the amount of time the event loop has spent
// idle in the kernel’s event provider .
uv_loop_configure(loop, UV_METRICS_IDLE_TIME);
// Initialize gin::IsolateHolder.
JavascriptEnvironment gin_env(loop);
v8::Isolate* isolate = gin_env.isolate();
v8::Isolate::Scope isolate_scope(isolate);
v8::Locker locker(isolate);
node::Environment* env = nullptr;
node::IsolateData* isolate_data = nullptr;
{
v8::HandleScope scope(isolate);
isolate_data = node::CreateIsolateData(isolate, loop, gin_env.platform());
CHECK_NE(nullptr, isolate_data);
uint64_t flags = node::EnvironmentFlags::kDefaultFlags |
node::EnvironmentFlags::kHideConsoleWindows;
env = node::CreateEnvironment(
isolate_data, gin_env.context(), result.args, result.exec_args,
static_cast<node::EnvironmentFlags::Flags>(flags));
CHECK_NE(nullptr, env);
node::IsolateSettings is;
node::SetIsolateUpForNode(isolate, is);
gin_helper::Dictionary process(isolate, env->process_object());
process.SetMethod("crash", &ElectronBindings::Crash);
// Setup process.crashReporter in child node processes
gin_helper::Dictionary reporter = gin::Dictionary::CreateEmpty(isolate);
#if defined(OS_LINUX)
reporter.SetMethod("start", &CrashReporterStart);
#endif
reporter.SetMethod("getParameters", &GetParameters);
#if defined(MAS_BUILD)
reporter.SetMethod("addExtraParameter", &SetCrashKeyStub);
reporter.SetMethod("removeExtraParameter", &ClearCrashKeyStub);
#else
reporter.SetMethod("addExtraParameter",
&electron::crash_keys::SetCrashKey);
reporter.SetMethod("removeExtraParameter",
&electron::crash_keys::ClearCrashKey);
#endif
process.Set("crashReporter", reporter);
gin_helper::Dictionary versions;
if (process.Get("versions", &versions)) {
versions.SetReadOnly(ELECTRON_PROJECT_NAME, ELECTRON_VERSION_STRING);
}
}
v8::HandleScope scope(isolate);
node::LoadEnvironment(env, node::StartExecutionCallback{});
env->set_trace_sync_io(env->options()->trace_sync_io);
{
v8::SealHandleScope seal(isolate);
bool more;
env->performance_state()->Mark(
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
do {
uv_run(env->event_loop(), UV_RUN_DEFAULT);
gin_env.platform()->DrainTasks(isolate);
more = uv_loop_alive(env->event_loop());
if (more && !env->is_stopping())
continue;
if (!uv_loop_alive(env->event_loop())) {
EmitBeforeExit(env);
}
// Emit `beforeExit` if the loop became alive either after emitting
// event, or after running some callbacks.
more = uv_loop_alive(env->event_loop());
} while (more && !env->is_stopping());
env->performance_state()->Mark(
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
}
env->set_trace_sync_io(false);
exit_code = node::EmitExit(env);
node::ResetStdio();
node::Stop(env);
node::FreeEnvironment(env);
node::FreeIsolateData(isolate_data);
}
// According to "src/gin/shell/gin_main.cc":
//
// gin::IsolateHolder waits for tasks running in ThreadPool in its
// destructor and thus must be destroyed before ThreadPool starts skipping
// CONTINUE_ON_SHUTDOWN tasks.
base::ThreadPoolInstance::Get()->Shutdown();
v8::V8::Dispose();
return exit_code;
}