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 - モジュール: パッケージ
- Net
- OS
- パス
- パフォーマンスフック
- パーミッション
- プロセス
- Punycode
- クエリ文字列
- Readline
- REPL
- レポート
- 単一実行可能アプリケーション
- ストリーム
- 文字列デコーダ
- テストランナー
- タイマー
- TLS/SSL
- トレースイベント
- TTY
- UDP/データグラム
- URL
- ユーティリティ
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- ワーカースレッド
- Zlib
- ► 他のバージョン
- ► オプション
C++ 埋め込みAPI#
Node.js は、他の C++ ソフトウェアから Node.js 環境で JavaScript を実行するために使用できる、多数の C++ API を提供しています。
これらの API のドキュメントは、Node.js ソースツリーの src/node.h にあります。Node.js によって公開されている API に加えて、V8 埋め込み API によっていくつかの必要な概念が提供されています。
Node.js を埋め込みライブラリとして使用することは、Node.js によって実行されるコードを記述することとは異なるため、破壊的な変更は、典型的な Node.js の 非推奨ポリシー に従わず、事前の警告なしに各セマンティックメジャーリリースで発生する可能性があります。
埋め込みアプリケーションの例#
以下のセクションでは、これらの API を使用して、node -e <code>
と同等の処理を実行するアプリケーション(つまり、JavaScript の一部を取得して Node.js 固有の環境で実行するアプリケーション)をゼロから作成する方法の概要を説明します。
完全なコードは、Node.js ソースツリー にあります。
プロセスごとの状態の設定#
Node.js を実行するには、プロセスごとの状態管理が必要です
- Node.js の CLI オプション の引数解析、
v8::Platform
インスタンスなど、V8 プロセスごとの要件。
次の例は、これらをセットアップする方法を示しています。一部のクラス名は、それぞれ 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
は、
- 正確に 1 つの
v8::Isolate
、つまり 1 つの JS エンジンインスタンス、 - 正確に 1 つの
uv_loop_t
、つまり 1 つのイベントループ、および - 多数の
v8::Context
ですが、正確に 1 つのメインv8::Context
に関連付けられています。 - 同じ
v8::Isolate
を使用する複数のnode::Environment
で共有できる情報を含む 1 つのnode::IsolateData
インスタンス。現在、このシナリオのテストは行われていません。
v8::Isolate
をセットアップするには、v8::ArrayBuffer::Allocator
を提供する必要があります。1 つの選択肢は、デフォルトの Node.js アロケータです。これは、node::ArrayBufferAllocator::Create()
を介して作成できます。Node.js アロケータを使用すると、アドオンが Node.js C++ Buffer
API を使用する場合にマイナーなパフォーマンスの最適化が可能になり、process.memoryUsage()
で ArrayBuffer
メモリを追跡するために必要です。
さらに、Node.js インスタンスに使用される各 v8::Isolate
は、プラットフォームが v8::Isolate
によってスケジュールされたタスクに使用するイベントループを知るために、MultiIsolatePlatform
インスタンス(使用されている場合)に登録および登録解除する必要があります。
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;
}