diff options
author | Anna Henningsen <anna@addaleax.net> | 2020-10-11 16:13:19 +0300 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2020-10-14 21:08:19 +0300 |
commit | 9fd6122659c4067b0d8bd2c590f4ba01b48c93a3 (patch) | |
tree | 89cdbb73d84f5ae87e1399f95aa0fba392b43f7f /doc/api/embedding.md | |
parent | ef1645e2b3f609492af7f25e4468db9b7801f4aa (diff) |
src: add embedding helpers to reduce boilerplate code
Provide helpers for a) spinning the event loop and
b) setting up and tearing down the objects involved in a single
Node.js instance, as they would typically be used.
The former helper is also usable inside Node.js itself,
for both Worker and main threads.
PR-URL: https://github.com/nodejs/node/pull/35597
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Diffstat (limited to 'doc/api/embedding.md')
-rw-r--r-- | doc/api/embedding.md | 105 |
1 files changed, 21 insertions, 84 deletions
diff --git a/doc/api/embedding.md b/doc/api/embedding.md index f38d5a7cabc..82c87f5890f 100644 --- a/doc/api/embedding.md +++ b/doc/api/embedding.md @@ -67,6 +67,13 @@ int main(int argc, char** argv) { ``` ### Per-instance state +<!-- YAML +changes: + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/35597 + description: + The `CommonEnvironmentSetup` and `SpinEventLoop` utilities were added. +--> Node.js has a concept of a “Node.js instance”, that is commonly being referred to as `node::Environment`. Each `node::Environment` is associated with: @@ -99,52 +106,26 @@ int RunNodeInstance(MultiIsolatePlatform* platform, const std::vector<std::string>& args, const std::vector<std::string>& exec_args) { int exit_code = 0; - // Set up a libuv event loop. - 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<ArrayBufferAllocator> 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()); + // Setup up a libuv event loop, v8::Isolate, and Node.js Environment. + std::vector<std::string> errors; + std::unique_ptr<CommonEnvironmentSetup> setup = + CommonEnvironmentSetup::Create(platform, &errors, args, exec_args); + if (!setup) { + for (const std::string& err : errors) + fprintf(stderr, "%s: %s\n", args[0].c_str(), err.c_str()); return 1; } + Isolate* isolate = setup->isolate(); + Environment* env = setup->env(); + { Locker locker(isolate); Isolate::Scope isolate_scope(isolate); - - // Create a node::IsolateData instance that will later be released using - // node::FreeIsolateData(). - std::unique_ptr<IsolateData, decltype(&node::FreeIsolateData)> isolate_data( - node::CreateIsolateData(isolate, &loop, platform, allocator.get()), - node::FreeIsolateData); - - // Set up a new v8::Context. - HandleScope handle_scope(isolate); - Local<Context> context = node::NewContext(isolate); - if (context.IsEmpty()) { - fprintf(stderr, "%s: Failed to initialize V8 Context\n", args[0].c_str()); - return 1; - } - // The v8::Context needs to be entered when node::CreateEnvironment() and // node::LoadEnvironment() are being called. - Context::Scope context_scope(context); - - // Create a node::Environment instance that will later be released using - // node::FreeEnvironment(). - std::unique_ptr<Environment, decltype(&node::FreeEnvironment)> env( - node::CreateEnvironment(isolate_data.get(), context, args, exec_args), - node::FreeEnvironment); + Context::Scope context_scope(setup->context()); // Set up the Node.js instance for execution, and run code inside of it. // There is also a variant that takes a callback and provides it with @@ -156,7 +137,7 @@ int RunNodeInstance(MultiIsolatePlatform* platform, // load files from the disk, and uses the standard CommonJS file loader // instead of the internal-only `require` function. MaybeLocal<Value> loadenv_ret = node::LoadEnvironment( - env.get(), + env, "const publicRequire =" " require('module').createRequire(process.cwd() + '/');" "globalThis.require = publicRequire;" @@ -165,58 +146,14 @@ int RunNodeInstance(MultiIsolatePlatform* platform, if (loadenv_ret.IsEmpty()) // There has been a JS exception. return 1; - { - // SealHandleScope protects against handle leaks from callbacks. - SealHandleScope seal(isolate); - bool more; - do { - uv_run(&loop, UV_RUN_DEFAULT); - - // V8 tasks on background threads may end up scheduling new tasks in the - // foreground, which in turn can keep the event loop going. For example, - // WebAssembly.compile() may do so. - platform->DrainTasks(isolate); - - // If there are new tasks, continue. - more = uv_loop_alive(&loop); - if (more) continue; - - // node::EmitProcessBeforeExit() is used to emit the 'beforeExit' event - // on the `process` object. - if (node::EmitProcessBeforeExit(env.get()).IsNothing()) - break; - - // 'beforeExit' can also schedule new work that keeps the event loop - // running. - more = uv_loop_alive(&loop); - } while (more == true); - } - - // node::EmitProcessExit() returns the current exit code. - exit_code = node::EmitProcessExit(env.get()).FromMaybe(1); + exit_code = node::SpinEventLoop(env).FromMaybe(1); // node::Stop() can be used to explicitly stop the event loop and keep // further JavaScript from running. It can be called from any thread, // and will act like worker.terminate() if called from another thread. - node::Stop(env.get()); + node::Stop(env); } - // Unregister the Isolate with the platform and add a listener that is called - // when the Platform is done cleaning up any state it had associated with - // the Isolate. - bool platform_finished = false; - platform->AddIsolateFinishedCallback(isolate, [](void* data) { - *static_cast<bool*>(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; } ``` |