#include "node.h" #include "uv.h" #include // Note: This file is being referred to from doc/api/embedding.md, and excerpts // from it are included in the documentation. Try to keep these in sync. using node::ArrayBufferAllocator; using node::Environment; using node::IsolateData; using node::MultiIsolatePlatform; using v8::Context; using v8::HandleScope; using v8::Isolate; using v8::Local; using v8::Locker; using v8::MaybeLocal; using v8::SealHandleScope; using v8::Value; using v8::V8; static int RunNodeInstance(MultiIsolatePlatform* platform, const std::vector& args, const std::vector& exec_args); int main(int argc, char** argv) { std::vector args(argv, argv + argc); std::vector exec_args; std::vector errors; int exit_code = node::InitializeNodeWithArgs(&args, &exec_args, &errors); for (const std::string& error : errors) fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str()); if (exit_code != 0) { return exit_code; } std::unique_ptr platform = MultiIsolatePlatform::Create(4); V8::InitializePlatform(platform.get()); V8::Initialize(); int ret = RunNodeInstance(platform.get(), args, exec_args); V8::Dispose(); V8::ShutdownPlatform(); return ret; } int RunNodeInstance(MultiIsolatePlatform* platform, const std::vector& args, const std::vector& exec_args) { int exit_code = 0; uv_loop_t loop; int ret = uv_loop_init(&loop); if (ret != 0) { fprintf(stderr, "%s: Failed to initialize loop: %s\n", args[0].c_str(), uv_err_name(ret)); return 1; } std::shared_ptr allocator = ArrayBufferAllocator::Create(); Isolate* isolate = NewIsolate(allocator, &loop, platform); if (isolate == nullptr) { fprintf(stderr, "%s: Failed to initialize V8 Isolate\n", args[0].c_str()); return 1; } { Locker locker(isolate); Isolate::Scope isolate_scope(isolate); std::unique_ptr isolate_data( node::CreateIsolateData(isolate, &loop, platform, allocator.get()), node::FreeIsolateData); HandleScope handle_scope(isolate); Local context = node::NewContext(isolate); if (context.IsEmpty()) { fprintf(stderr, "%s: Failed to initialize V8 Context\n", args[0].c_str()); return 1; } Context::Scope context_scope(context); std::unique_ptr env( node::CreateEnvironment(isolate_data.get(), context, args, exec_args), node::FreeEnvironment); MaybeLocal loadenv_ret = node::LoadEnvironment( env.get(), "const publicRequire =" " require('module').createRequire(process.cwd() + '/');" "globalThis.require = publicRequire;" "require('vm').runInThisContext(process.argv[1]);"); if (loadenv_ret.IsEmpty()) // There has been a JS exception. return 1; { SealHandleScope seal(isolate); bool more; do { uv_run(&loop, UV_RUN_DEFAULT); platform->DrainTasks(isolate); more = uv_loop_alive(&loop); if (more) continue; node::EmitBeforeExit(env.get()); more = uv_loop_alive(&loop); } while (more == true); } exit_code = node::EmitExit(env.get()); node::Stop(env.get()); } bool platform_finished = false; platform->AddIsolateFinishedCallback(isolate, [](void* data) { *static_cast(data) = true; }, &platform_finished); platform->UnregisterIsolate(isolate); isolate->Dispose(); // Wait until the platform has cleaned up all relevant resources. while (!platform_finished) uv_run(&loop, UV_RUN_ONCE); int err = uv_loop_close(&loop); assert(err == 0); return exit_code; }