Node.js v21.7.2 文件
- Node.js v21.7.2
- ► 目錄
-
► 索引
- 斷言測試
- 非同步內容追蹤
- 非同步掛鉤
- 緩衝區
- C++ 附加元件
- 使用 Node-API 的 C/C++ 附加元件
- C++ 嵌入程式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯器
- 已棄用 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢視器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- Readline
- REPL
- 報告
- 單一可執行應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料報
- URL
- 公用程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
C++ 嵌入器 API#
Node.js 提供許多 C++ API,可從其他 C++ 軟體在 Node.js 環境中執行 JavaScript。
這些 API 的文件可以在 Node.js 原始碼樹中的 src/node.h 中找到。除了 Node.js 公開的 API 之外,V8 嵌入器 API 也提供了一些必要的概念。
由於將 Node.js 作為嵌入式函式庫與撰寫由 Node.js 執行的程式碼不同,因此重大變更不會遵循典型的 Node.js 不建議政策,且可能會在每個 semver 主要版本中發生,恕不另行通知。
範例嵌入式應用程式#
以下各節將概述如何使用這些 API 從頭開始建立一個應用程式,該應用程式將執行等同於 node -e <code>
的動作,亦即將擷取一段 JavaScript 並在 Node.js 特定的環境中執行它。
完整的程式碼可以在 Node.js 原始碼樹 中找到。
設定每個處理程序狀態#
Node.js 需要一些每個處理程序的狀態管理才能執行
- Node.js CLI 選項 的引數剖析,
- V8 每個處理程序的要求,例如
v8::Platform
實例。
以下範例顯示如何設定這些要求。有些類別名稱分別來自 node
和 v8
C++ 名稱空間。
int main(int argc, char** argv) {
argv = uv_setup_args(argc, argv);
std::vector<std::string> args(argv, argv + argc);
// Parse Node.js CLI options, and print any errors that have occurred while
// trying to parse them.
std::unique_ptr<node::InitializationResult> result =
node::InitializeOncePerProcess(args, {
node::ProcessInitializationFlags::kNoInitializeV8,
node::ProcessInitializationFlags::kNoInitializeNodeV8Platform
});
for (const std::string& error : result->errors())
fprintf(stderr, "%s: %s\n", args[0].c_str(), error.c_str());
if (result->early_return() != 0) {
return result->exit_code();
}
// Create a v8::Platform instance. `MultiIsolatePlatform::Create()` is a way
// to create a v8::Platform instance that Node.js can use when creating
// Worker threads. When no `MultiIsolatePlatform` instance is present,
// Worker threads are disabled.
std::unique_ptr<MultiIsolatePlatform> platform =
MultiIsolatePlatform::Create(4);
V8::InitializePlatform(platform.get());
V8::Initialize();
// See below for the contents of this function.
int ret = RunNodeInstance(
platform.get(), result->args(), result->exec_args());
V8::Dispose();
V8::DisposePlatform();
node::TearDownOncePerProcess();
return ret;
}
每個執行個體狀態#
Node.js 有「Node.js 執行個體」的概念,通常稱為 node::Environment
。每個 node::Environment
都與下列項目關聯:
- 完全一個
v8::Isolate
,也就是一個 JS 引擎執行個體, - 完全一個
uv_loop_t
,也就是一個事件迴圈,以及 - 多個
v8::Context
,但完全一個主要v8::Context
。 - 一個
node::IsolateData
執行個體,其中包含可由使用相同v8::Isolate
的多個node::Environment
共用的資訊。目前,尚未針對此情境執行任何測試。
若要設定 v8::Isolate
,需要提供一個 v8::ArrayBuffer::Allocator
。一個可能的選擇是預設的 Node.js 分配器,可透過 node::ArrayBufferAllocator::Create()
建立。使用 Node.js 分配器可以在外掛程式使用 Node.js C++ Buffer
API 時進行微小的效能最佳化,且為追蹤 process.memoryUsage()
中的 ArrayBuffer
記憶體所必需。
此外,如果正在使用 MultiIsolatePlatform
執行個體,則每個用於 Node.js 執行個體的 v8::Isolate
都需要向 MultiIsolatePlatform
執行個體註冊和取消註冊,以便平台知道要為 v8::Isolate
排程的任務使用哪個事件迴圈。
node::NewIsolate()
輔助函式會建立一個 v8::Isolate
,使用一些 Node.js 特定的掛鉤 (例如 Node.js 錯誤處理常式) 設定它,並自動向平台註冊它。
int RunNodeInstance(MultiIsolatePlatform* platform,
const std::vector<std::string>& args,
const std::vector<std::string>& exec_args) {
int exit_code = 0;
// 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);
HandleScope handle_scope(isolate);
// The v8::Context needs to be entered when node::CreateEnvironment() and
// node::LoadEnvironment() are being called.
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
// the `require` and `process` objects, so that it can manually compile
// and run scripts as needed.
// The `require` function inside this script does *not* access the file
// system, and can only load built-in Node.js modules.
// `module.createRequire()` is being used to create one that is able to
// 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,
"const publicRequire ="
" require('node:module').createRequire(process.cwd() + '/');"
"globalThis.require = publicRequire;"
"require('node:vm').runInThisContext(process.argv[1]);");
if (loadenv_ret.IsEmpty()) // There has been a JS exception.
return 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);
}
return exit_code;
}