{"$schema":"https://doc-kit.nodejs.org/schemas/api-doc/1.0.0.json","id":"embedding","path":"/embedding","type":"module","module":"embedding","title":"C++ embedder API","introducedIn":"v12.19.0","sourceLink":null,"stability":null,"added":[],"deprecated":[],"removed":[],"napiVersion":[],"changes":[],"description":"Node.js provides a number of C++ APIs that can be used to execute JavaScript\nin a Node.js environment from other C++ software.\n\nThe documentation for these APIs can be found in [src/node.h](https://github.com/nodejs/node/blob/HEAD/src/node.h) in the Node.js\nsource tree. In addition to the APIs exposed by Node.js, some required concepts\nare provided by the V8 embedder API.\n\nBecause using Node.js as an embedded library is different from writing code\nthat is executed by Node.js, breaking changes do not follow typical Node.js\n[deprecation policy](deprecations.html) and may occur on each semver-major release without prior\nwarning.","summary":"Node.js provides a number of C++ APIs that can be used to execute JavaScript in a Node.js environment from other C++ software.","examples":[],"children":[{"kind":"section","id":"example-embedding-application","name":"Example embedding application","title":"Example embedding application","scope":"module","overloadOf":null,"stability":null,"added":[],"deprecated":[],"removed":[],"napiVersion":[],"changes":[],"description":"The following sections will provide an overview over how to use these APIs\nto create an application from scratch that will perform the equivalent of\n`node -e <code>`, i.e. that will take a piece of JavaScript and run it in\na Node.js-specific environment.\n\nThe full code can be found [in the Node.js source tree](https://github.com/nodejs/node/blob/HEAD/test/embedding/embedtest.cc).","summary":"The following sections will provide an overview over how to use these APIs to create an application from scratch that will perform the equivalent of `node -e <code>`, i.e. that will take a piece of JavaScript and run it in a Node.js-specific environment.","examples":[],"children":[{"kind":"section","id":"setting-up-a-per-process-state","name":"Setting up a per-process state","title":"Setting up a per-process state","scope":"module","overloadOf":null,"stability":null,"added":[],"deprecated":[],"removed":[],"napiVersion":[],"changes":[],"description":"Node.js requires some per-process state management in order to run:\n\n* Arguments parsing for Node.js [CLI options](cli.html),\n* V8 per-process requirements, such as a `v8::Platform` instance.\n\nThe following example shows how these can be set up. Some class names are from\nthe `node` and `v8` C++ namespaces, respectively.\n\n```cpp\nint main(int argc, char** argv) {\n  argv = uv_setup_args(argc, argv);\n  std::vector<std::string> args(argv, argv + argc);\n  // Parse Node.js CLI options, and print any errors that have occurred while\n  // trying to parse them.\n  std::unique_ptr<node::InitializationResult> result =\n      node::InitializeOncePerProcess(args, {\n        node::ProcessInitializationFlags::kNoInitializeV8,\n        node::ProcessInitializationFlags::kNoInitializeNodeV8Platform\n      });\n\n  for (const std::string& error : result->errors())\n    fprintf(stderr, \"%s: %s\\n\", args[0].c_str(), error.c_str());\n  if (result->early_return() != 0) {\n    return result->exit_code();\n  }\n\n  // Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way\n  // to create a v8::Platform instance that Node.js can use when creating\n  // Worker threads. When no `MultiIsolatePlatform` instance is present,\n  // Worker threads are disabled.\n  std::unique_ptr<MultiIsolatePlatform> platform =\n      MultiIsolatePlatform::Create(4);\n  V8::InitializePlatform(platform.get());\n  V8::Initialize();\n\n  // See below for the contents of this function.\n  int ret = RunNodeInstance(\n      platform.get(), result->args(), result->exec_args());\n\n  V8::Dispose();\n  V8::DisposePlatform();\n\n  node::TearDownOncePerProcess();\n  return ret;\n}\n```","summary":"Node.js requires some per-process state management in order to run:","examples":[{"language":"cpp","displayName":null,"code":"int main(int argc, char** argv) {\n  argv = uv_setup_args(argc, argv);\n  std::vector<std::string> args(argv, argv + argc);\n  // Parse Node.js CLI options, and print any errors that have occurred while\n  // trying to parse them.\n  std::unique_ptr<node::InitializationResult> result =\n      node::InitializeOncePerProcess(args, {\n        node::ProcessInitializationFlags::kNoInitializeV8,\n        node::ProcessInitializationFlags::kNoInitializeNodeV8Platform\n      });\n\n  for (const std::string& error : result->errors())\n    fprintf(stderr, \"%s: %s\\n\", args[0].c_str(), error.c_str());\n  if (result->early_return() != 0) {\n    return result->exit_code();\n  }\n\n  // Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way\n  // to create a v8::Platform instance that Node.js can use when creating\n  // Worker threads. When no `MultiIsolatePlatform` instance is present,\n  // Worker threads are disabled.\n  std::unique_ptr<MultiIsolatePlatform> platform =\n      MultiIsolatePlatform::Create(4);\n  V8::InitializePlatform(platform.get());\n  V8::Initialize();\n\n  // See below for the contents of this function.\n  int ret = RunNodeInstance(\n      platform.get(), result->args(), result->exec_args());\n\n  V8::Dispose();\n  V8::DisposePlatform();\n\n  node::TearDownOncePerProcess();\n  return ret;\n}"}],"children":[]},{"kind":"section","id":"setting-up-a-per-instance-state","name":"Setting up a per-instance state","title":"Setting up a per-instance state","scope":"module","overloadOf":null,"stability":null,"added":[],"deprecated":[],"removed":[],"napiVersion":[],"changes":[{"versions":["v15.0.0"],"prUrl":"https://github.com/nodejs/node/pull/35597","commit":null,"description":"The `CommonEnvironmentSetup` and `SpinEventLoop` utilities were added."}],"description":"Node.js has a concept of a “Node.js instance”, that is commonly being referred\nto as `node::Environment`. Each `node::Environment` is associated with:\n\n* Exactly one `v8::Isolate`, i.e. one JS Engine instance,\n* Exactly one `uv_loop_t`, i.e. one event loop,\n* A number of `v8::Context`s, but exactly one main `v8::Context`, and\n* One `node::IsolateData` instance that contains information that could be\n  shared by multiple `node::Environment`s. The embedder should make sure\n  that `node::IsolateData` is shared only among `node::Environment`s that\n  use the same `v8::Isolate`, Node.js does not perform this check.\n\nIn order to set up a `v8::Isolate`, an `v8::ArrayBuffer::Allocator` needs\nto be provided. One possible choice is the default Node.js allocator, which\ncan be created through `node::ArrayBufferAllocator::Create()`. Using the Node.js\nallocator allows minor performance optimizations when addons use the Node.js\nC++ `Buffer` API, and is required in order to track `ArrayBuffer` memory in\n[`process.memoryUsage()`](process.html#processmemoryusage).\n\nAdditionally, each `v8::Isolate` that is used for a Node.js instance needs to\nbe registered and unregistered with the `MultiIsolatePlatform` instance, if one\nis being used, in order for the platform to know which event loop to use\nfor tasks scheduled by the `v8::Isolate`.\n\nThe `node::NewIsolate()` helper function creates a `v8::Isolate`,\nsets it up with some Node.js-specific hooks (e.g. the Node.js error handler),\nand registers it with the platform automatically.\n\n```cpp\nint RunNodeInstance(MultiIsolatePlatform* platform,\n                    const std::vector<std::string>& args,\n                    const std::vector<std::string>& exec_args) {\n  int exit_code = 0;\n\n  // Set up a libuv event loop, v8::Isolate, and Node.js Environment.\n  std::vector<std::string> errors;\n  std::unique_ptr<CommonEnvironmentSetup> setup =\n      CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);\n  if (!setup) {\n    for (const std::string& err : errors)\n      fprintf(stderr, \"%s: %s\\n\", args[0].c_str(), err.c_str());\n    return 1;\n  }\n\n  Isolate* isolate = setup->isolate();\n  Environment* env = setup->env();\n\n  {\n    Locker locker(isolate);\n    Isolate::Scope isolate_scope(isolate);\n    HandleScope handle_scope(isolate);\n    // The v8::Context needs to be entered when node::CreateEnvironment() and\n    // node::LoadEnvironment() are being called.\n    Context::Scope context_scope(setup->context());\n\n    // Set up the Node.js instance for execution, and run code inside of it.\n    // There is also a variant that takes a callback and provides it with\n    // the `require` and `process` objects, so that it can manually compile\n    // and run scripts as needed.\n    // The `require` function inside this script does *not* access the file\n    // system, and can only load built-in Node.js modules.\n    // `module.createRequire()` is being used to create one that is able to\n    // load files from the disk, and uses the standard CommonJS file loader\n    // instead of the internal-only `require` function.\n    MaybeLocal<Value> loadenv_ret = node::LoadEnvironment(\n        env,\n        \"const publicRequire =\"\n        \"  require('node:module').createRequire(process.cwd() + '/');\"\n        \"globalThis.require = publicRequire;\"\n        \"require('node:vm').runInThisContext(process.argv[1]);\");\n\n    if (loadenv_ret.IsEmpty())  // There has been a JS exception.\n      return 1;\n\n    exit_code = node::SpinEventLoop(env).FromMaybe(1);\n\n    // node::Stop() can be used to explicitly stop the event loop and keep\n    // further JavaScript from running. It can be called from any thread,\n    // and will act like worker.terminate() if called from another thread.\n    node::Stop(env);\n  }\n\n  return exit_code;\n}\n```","summary":"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:","examples":[{"language":"cpp","displayName":null,"code":"int RunNodeInstance(MultiIsolatePlatform* platform,\n                    const std::vector<std::string>& args,\n                    const std::vector<std::string>& exec_args) {\n  int exit_code = 0;\n\n  // Set up a libuv event loop, v8::Isolate, and Node.js Environment.\n  std::vector<std::string> errors;\n  std::unique_ptr<CommonEnvironmentSetup> setup =\n      CommonEnvironmentSetup::Create(platform, &errors, args, exec_args);\n  if (!setup) {\n    for (const std::string& err : errors)\n      fprintf(stderr, \"%s: %s\\n\", args[0].c_str(), err.c_str());\n    return 1;\n  }\n\n  Isolate* isolate = setup->isolate();\n  Environment* env = setup->env();\n\n  {\n    Locker locker(isolate);\n    Isolate::Scope isolate_scope(isolate);\n    HandleScope handle_scope(isolate);\n    // The v8::Context needs to be entered when node::CreateEnvironment() and\n    // node::LoadEnvironment() are being called.\n    Context::Scope context_scope(setup->context());\n\n    // Set up the Node.js instance for execution, and run code inside of it.\n    // There is also a variant that takes a callback and provides it with\n    // the `require` and `process` objects, so that it can manually compile\n    // and run scripts as needed.\n    // The `require` function inside this script does *not* access the file\n    // system, and can only load built-in Node.js modules.\n    // `module.createRequire()` is being used to create one that is able to\n    // load files from the disk, and uses the standard CommonJS file loader\n    // instead of the internal-only `require` function.\n    MaybeLocal<Value> loadenv_ret = node::LoadEnvironment(\n        env,\n        \"const publicRequire =\"\n        \"  require('node:module').createRequire(process.cwd() + '/');\"\n        \"globalThis.require = publicRequire;\"\n        \"require('node:vm').runInThisContext(process.argv[1]);\");\n\n    if (loadenv_ret.IsEmpty())  // There has been a JS exception.\n      return 1;\n\n    exit_code = node::SpinEventLoop(env).FromMaybe(1);\n\n    // node::Stop() can be used to explicitly stop the event loop and keep\n    // further JavaScript from running. It can be called from any thread,\n    // and will act like worker.terminate() if called from another thread.\n    node::Stop(env);\n  }\n\n  return exit_code;\n}"}],"children":[]}]}]}