Node-API#

安定度: 2 - 安定

Node-API (以前の N-API) は、ネイティブアドオンを構築するための API です。基盤となる JavaScript ランタイム (例: V8) から独立しており、Node.js 自体の一部としてメンテナンスされています。この API は、Node.js のバージョン間で Application Binary Interface (ABI) の安定性を保ちます。基盤となる JavaScript エンジンの変更からアドオンを保護し、あるメジャーバージョン用にコンパイルされたモジュールが、再コンパイルなしで Node.js の後続のメジャーバージョンで実行できるようにすることを目的としています。 ABI 安定性ガイドで、より詳細な説明を提供しています。

アドオンは、C++ アドオンというタイトルのセクションで概説されているのと同じアプローチ/ツールでビルド/パッケージ化されます。唯一の違いは、ネイティブコードで使用される API のセットです。V8 や Native Abstractions for Node.js API を使用する代わりに、Node-API で利用可能な関数が使用されます。

Node-API によって公開される API は、一般に JavaScript の値を作成および操作するために使用されます。概念と操作は、一般に ECMA-262 言語仕様で指定されているアイデアに対応します。API には次のプロパティがあります。

  • すべての Node-API 呼び出しは、napi_status 型のステータスコードを返します。このステータスは、API 呼び出しが成功したか失敗したかを示します。
  • API の戻り値は、出力パラメーターを介して渡されます。
  • すべての JavaScript 値は、napi_value という名前の不透明な型で抽象化されます。
  • エラーのステータスコードの場合、napi_get_last_error_info を使用して追加情報を取得できます。詳細については、エラー処理セクション エラー処理 を参照してください。

Node-API は、Node.js のバージョンと異なるコンパイラレベル間で ABI の安定性を確保する C API です。C++ API は使いやすくなります。C++ の使用をサポートするために、プロジェクトは node-addon-api という C++ ラッパーモジュールを保持しています。このラッパーは、インライン化可能な C++ API を提供します。 node-addon-api でビルドされたバイナリは、Node.js によってエクスポートされる Node-API C ベースの関数のシンボルに依存します。 node-addon-api は、Node-API を呼び出すコードを記述するより効率的な方法です。例として、次の node-addon-api コードを取り上げます。最初のセクションは node-addon-api コードを示し、2 番目のセクションはアドオンで実際に使用されるものを示しています。

Object obj = Object::New(env);
obj["foo"] = String::New(env, "bar"); 
napi_status status;
napi_value object, string;
status = napi_create_object(env, &object);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
}

status = napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, &string);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
}

status = napi_set_named_property(env, object, "foo", string);
if (status != napi_ok) {
  napi_throw_error(env, ...);
  return;
} 

最終的に、アドオンはエクスポートされたC APIのみを使用します。その結果、C APIによって提供されるABI安定性の恩恵を受けることができます。

C APIの代わりにnode-addon-apiを使用する場合は、まずnode-addon-apiAPIドキュメントを参照してください。

Node-APIリソースは、Node-APIとnode-addon-apiを使い始めたばかりの開発者にとって、優れたオリエンテーションとヒントを提供します。追加のメディアリソースは、Node-APIメディアページにあります。

ABI安定性の影響#

Node-APIはABI安定性を保証しますが、Node.jsの他の部分は保証しておらず、アドオンから使用される外部ライブラリも保証しない場合があります。特に、以下のAPIは、メジャーバージョン間でのABI安定性を保証しません。

  • 次のいずれかを介して利用可能なNode.js C++ API

    #include <node.h>
    #include <node_buffer.h>
    #include <node_version.h>
    #include <node_object_wrap.h> 
  • Node.jsに含まれており、以下を介して利用可能なlibuv API

    #include <uv.h> 
  • 以下を介して利用可能なV8 API

    #include <v8.h> 

したがって、アドオンがNode.jsのメジャーバージョン間でABI互換性を維持するためには、以下の使用に限定してNode-APIのみを使用する必要があります。

#include <node_api.h> 

また、使用するすべての外部ライブラリについて、外部ライブラリがNode-APIと同様のABI安定性の保証を行っていることを確認する必要があります。

ビルド#

JavaScriptで記述されたモジュールとは異なり、Node-APIを使用したNode.jsネイティブアドオンの開発とデプロイには、追加のツールセットが必要です。Node.jsの開発に必要な基本ツールに加えて、ネイティブアドオンの開発者は、CおよびC++コードをバイナリにコンパイルできるツールチェーンが必要です。さらに、ネイティブアドオンのデプロイ方法によっては、ネイティブアドオンの*ユーザー*もC/C++ツールチェーンをインストールする必要があります。

Linux開発者向けには、必要なC/C++ツールチェーンパッケージがすぐに利用できます。GCCは、さまざまなプラットフォームでビルドおよびテストするためにNode.jsコミュニティで広く使用されています。多くの開発者にとって、LLVMコンパイラインフラストラクチャも優れた選択肢です。

Mac開発者向けには、Xcodeが必要なコンパイラツールをすべて提供します。ただし、Xcode IDE全体をインストールする必要はありません。次のコマンドは、必要なツールチェーンをインストールします。

xcode-select --install 

Windows開発者向けには、Visual Studioが必要なコンパイラツールをすべて提供します。ただし、Visual Studio IDE全体をインストールする必要はありません。次のコマンドは、必要なツールチェーンをインストールします。

npm install --global windows-build-tools 

以下のセクションでは、Node.jsネイティブアドオンの開発とデプロイに使用できる追加のツールについて説明します。

ビルドツール#

ここにリストされている両方のツールは、ネイティブアドオンの*ユーザー*が、ネイティブアドオンを正常にインストールするためにC/C++ツールチェーンをインストールしている必要があることを前提としています。

node-gyp#

node-gypは、GoogleのGYPツールのgyp-nextフォークに基づくビルドシステムであり、npmにバンドルされています。GYP、したがってnode-gypは、Pythonがインストールされている必要があります。

歴史的に、node-gypはネイティブアドオンをビルドするためのツールとして選択されてきました。広く採用されており、ドキュメントも豊富です。ただし、一部の開発者はnode-gypに制限があることに気づいています。

CMake.js#

CMake.jsは、CMakeに基づいた代替ビルドシステムです。

CMake.jsは、すでにCMakeを使用しているプロジェクトや、node-gypの制限の影響を受けている開発者にとって、優れた選択肢です。build_with_cmakeは、CMakeベースのネイティブアドオンプロジェクトの例です。

プリコンパイル済みバイナリのアップロード#

ここにリストされている3つのツールを使用すると、ネイティブアドオンの開発者とメンテナーは、バイナリを作成して、パブリックまたはプライベートサーバーにアップロードできます。これらのツールは、通常、Travis CIAppVeyorなどのCI/CDビルドシステムと統合されており、さまざまなプラットフォームとアーキテクチャのバイナリをビルドおよびアップロードします。これらのバイナリは、C/C++ツールチェーンをインストールする必要のないユーザーがダウンロードできるようになります。

node-pre-gyp#

node-pre-gypは、node-gypに基づいており、開発者が選択したサーバーにバイナリをアップロードする機能を追加するツールです。node-pre-gypは、特にAmazon S3へのバイナリのアップロードを強力にサポートしています。

prebuild#

prebuildは、node-gypまたはCMake.jsのいずれかを使用したビルドをサポートするツールです。さまざまなサーバーをサポートするnode-pre-gypとは異なり、prebuildはバイナリをGitHubリリースにのみアップロードします。prebuildは、CMake.jsを使用するGitHubプロジェクトに適しています。

prebuildify#

prebuildifyは、node-gypに基づいたツールです。prebuildifyの利点は、構築されたバイナリがnpmにアップロードされるときに、ネイティブアドオンにバンドルされることです。バイナリはnpmからダウンロードされ、ネイティブアドオンがインストールされると、モジュールユーザーがすぐに利用できるようになります。

使い方#

Node-API関数を使用するには、node開発ツリーのsrcディレクトリにあるnode_api.hファイルを含めます。

#include <node_api.h> 

これにより、特定のNode.jsリリースにおけるデフォルトのNAPI_VERSIONが選択されます。特定のバージョンのNode-APIとの互換性を確保するために、ヘッダーを含める際にバージョンを明示的に指定できます。

#define NAPI_VERSION 3
#include <node_api.h> 

これにより、Node-APIサーフェスが、指定された(およびそれ以前の)バージョンで利用可能だった機能のみに制限されます。

Node-APIサーフェスの一部は実験的であり、明示的なオプトインが必要です。

#define NAPI_EXPERIMENTAL
#include <node_api.h> 

この場合、実験的なAPIを含むAPIサーフェス全体がモジュールコードで利用可能になります。

場合によっては、すでにリリースされて安定しているAPIに影響を与える実験的な機能が導入されることがあります。これらの機能は、オプトアウトによって無効にできます。

#define NAPI_EXPERIMENTAL
#define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT
#include <node_api.h> 

ここで、<FEATURE_NAME>は、実験的および安定したAPIの両方に影響を与える実験的な機能の名前です。

Node-APIバージョンマトリックス#

バージョン9までは、Node-APIバージョンは追加方式で、Node.jsとは独立してバージョン管理されていました。つまり、どのバージョンも以前のバージョンの拡張であり、以前のバージョンのすべてのAPIにいくつかの追加機能がありました。各Node.jsバージョンは、単一のNode-APIバージョンのみをサポートしていました。たとえば、v18.15.0はNode-APIバージョン8のみをサポートします。ABI安定性は、8が以前のすべてのバージョンの厳密なスーパーセットであったため達成されました。

バージョン9以降、Node-APIバージョンは引き続き独立してバージョン管理されますが、Node-APIバージョン9で実行されたアドオンは、Node-APIバージョン10で実行するためにコードの更新が必要になる場合があります。ただし、ABI安定性は維持されます。Node-APIバージョン8よりも高いバージョンをサポートするNode.jsバージョンは、8とサポートする最高バージョンまでのすべてのバージョンをサポートし、アドオンがより高いNode-APIバージョンを選択しない限り、デフォルトでバージョン8 APIを提供するためです。このアプローチは、ABI安定性を維持しながら、既存のNode-API関数をより最適化できる柔軟性を提供します。既存のアドオンは、以前のバージョンのNode-APIを使用して再コンパイルせずに引き続き実行できます。アドオンが新しいNode-APIバージョンからの機能を必要とする場合、既存のコードの変更と再コンパイルは、それらの新しい関数を使用するために必要になります。

Node-APIバージョン9以降をサポートするバージョンのNode.jsでは、NAPI_VERSION=Xを定義し、既存のアドオン初期化マクロを使用すると、実行時にアドオンで使用される要求されたNode-APIバージョンがアドオンに組み込まれます。NAPI_VERSIONが設定されていない場合は、デフォルトで8になります。

この表は、古いストリームでは最新ではない可能性があります。最新の情報は、Node-APIバージョンマトリックスの最新のAPIドキュメントにあります。

Node-APIバージョン サポートされているバージョン
9 v18.17.0+、20.3.0+、21.0.0、およびそれ以降のすべてのバージョン
8 v12.22.0+、v14.17.0+、v15.12.0+、16.0.0、およびそれ以降のすべてのバージョン
7 v10.23.0+、v12.19.0+、v14.12.0+、15.0.0、およびそれ以降のすべてのバージョン
6 v10.20.0+、v12.17.0+、14.0.0、およびそれ以降のすべてのバージョン
5 v10.17.0+、v12.11.0+、13.0.0、およびそれ以降のすべてのバージョン
4 v10.16.0+、v11.8.0+、12.0.0、およびそれ以降のすべてのバージョン
3 v6.14.2*、8.11.2+、v9.11.0*+、10.0.0、およびそれ以降のすべてのバージョン
2 v8.10.0*+、v9.3.0*+、10.0.0、およびそれ以降のすべてのバージョン
1 v8.6.0**+、v9.0.0*+、10.0.0、およびそれ以降のすべてのバージョン

* Node-APIは実験的でした。

** Node.js 8.0.0には、Node-APIが実験的に含まれていました。Node-APIバージョン1としてリリースされましたが、Node.js 8.6.0まで進化し続けました。APIはNode.js 8.6.0より前のバージョンでは異なります。Node-APIバージョン3以降をお勧めします。

Node-API用にドキュメント化された各APIには、added in:というヘッダーがあり、安定しているAPIには、追加のヘッダーNode-API version:があります。APIは、Node-API version:に示されているNode-APIバージョン以上をサポートするNode.jsバージョンを使用する場合に、直接使用できます。Node-API version:がリストされていないか、Node-API version:がリストされていないNode.jsバージョンを使用する場合、#define NAPI_EXPERIMENTALnode_api.hまたはjs_native_api.hのインクルードより前にある場合にのみ、APIを使用できます。APIがadded in:に示されているよりも後のバージョンのNode.jsで利用できないように見える場合、これはおそらく見かけ上の不在の理由です。

ネイティブコードからECMAScript機能にアクセスすることに厳密に関連付けられたNode-APIは、js_native_api.hおよびjs_native_api_types.hで個別に見つけることができます。これらのヘッダーで定義されているAPIは、node_api.hおよびnode_api_types.hに含まれています。ヘッダーは、Node.jsの外部でNode-APIの実装を許可するために、このように構造化されています。これらの実装では、Node.js固有のAPIは適用できない場合があります。

アドオンのNode.js固有の部分は、実際の機能をJavaScript環境に公開するコードから分離して、後者をNode-APIの複数の実装で使用できるようにすることができます。以下の例では、addon.caddon.hjs_native_api.hのみを参照します。これにより、addon.cがNode.jsのNode-API実装またはNode.js外部のNode-APIの実装に対してコンパイルするために再利用できることが保証されます。

addon_node.cは、アドオンへのNode.js固有のエントリポイントを含み、アドオンがNode.js環境にロードされるときにaddon.cを呼び出すことによってアドオンをインスタンス化する別のファイルです。

// addon.h
#ifndef _ADDON_H_
#define _ADDON_H_
#include <js_native_api.h>
napi_value create_addon(napi_env env);
#endif  // _ADDON_H_ 
// addon.c
#include "addon.h"

#define NODE_API_CALL(env, call)                                  \
  do {                                                            \
    napi_status status = (call);                                  \
    if (status != napi_ok) {                                      \
      const napi_extended_error_info* error_info = NULL;          \
      napi_get_last_error_info((env), &error_info);               \
      const char* err_message = error_info->error_message;        \
      bool is_pending;                                            \
      napi_is_exception_pending((env), &is_pending);              \
      /* If an exception is already pending, don't rethrow it */  \
      if (!is_pending) {                                          \
        const char* message = (err_message == NULL)               \
            ? "empty error message"                               \
            : err_message;                                        \
        napi_throw_error((env), NULL, message);                   \
      }                                                           \
      return NULL;                                                \
    }                                                             \
  } while(0)

static napi_value
DoSomethingUseful(napi_env env, napi_callback_info info) {
  // Do something useful.
  return NULL;
}

napi_value create_addon(napi_env env) {
  napi_value result;
  NODE_API_CALL(env, napi_create_object(env, &result));

  napi_value exported_function;
  NODE_API_CALL(env, napi_create_function(env,
                                          "doSomethingUseful",
                                          NAPI_AUTO_LENGTH,
                                          DoSomethingUseful,
                                          NULL,
                                          &exported_function));

  NODE_API_CALL(env, napi_set_named_property(env,
                                             result,
                                             "doSomethingUseful",
                                             exported_function));

  return result;
} 
// addon_node.c
#include <node_api.h>
#include "addon.h"

NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
  // This function body is expected to return a `napi_value`.
  // The variables `napi_env env` and `napi_value exports` may be used within
  // the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
  return create_addon(env);
} 

環境ライフサイクルAPI#

ECMAScript言語仕様セクション8.7では、JavaScriptコードが実行される自己完結型の環境としての「エージェント」の概念を定義しています。複数のこのようなエージェントを、プロセスによって並行または順番に開始および終了できます。

Node.js環境は、ECMAScriptエージェントに対応しています。メインプロセスでは、環境は起動時に作成され、追加の環境はワーカー スレッドとして機能するために別のスレッドで作成できます。Node.jsが別のアプリケーションに埋め込まれている場合、アプリケーションのメインスレッドは、アプリケーションプロセスのライフサイクル中にNode.js環境を複数回構築および破棄する可能性もあり、アプリケーションによって作成された各Node.js環境は、そのライフサイクル中に、ワーカー スレッドとして追加の環境を作成および破棄する可能性があります。

ネイティブアドオンの観点からすると、これは、それが提供するバインディングが複数のコンテキストから複数回呼び出され、さらには複数のスレッドから同時に呼び出される可能性があることを意味します。

ネイティブアドオンは、Node.js環境のライフサイクル中に使用するグローバルな状態を割り当てる必要がある場合があります。これにより、その状態がアドオンの各インスタンスで一意になるようにできます。

この目的のために、Node-APIは、そのライフサイクルがNode.js環境のライフサイクルに結びつくようにデータを関連付ける方法を提供します。

napi_set_instance_data#

napi_status napi_set_instance_data(node_api_nogc_env env,
                                   void* data,
                                   napi_finalize finalize_cb,
                                   void* finalize_hint); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] data: このインスタンスのバインディングで利用可能にするデータ項目。
  • [in] finalize_cb: 環境が破棄されるときに呼び出す関数。関数は、dataを受け取り、それを解放できます。詳細については、napi_finalizeを参照してください。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。

APIが成功した場合はnapi_okを返します。

このAPIは、dataを現在実行中のNode.js環境に関連付けます。dataは後でnapi_get_instance_data()を使用して取得できます。以前のnapi_set_instance_data()の呼び出しによって設定された、現在実行中のNode.js環境に関連付けられている既存のデータはすべて上書きされます。前の呼び出しでfinalize_cbが提供された場合、それは呼び出されません。

napi_get_instance_data#

napi_status napi_get_instance_data(node_api_nogc_env env,
                                   void** data); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [out] data: napi_set_instance_data()の呼び出しによって、以前に現在実行中のNode.js環境に関連付けられたデータ項目。

APIが成功した場合はnapi_okを返します。

このAPIは、以前にnapi_set_instance_data()を介して現在実行中のNode.js環境に関連付けられたデータを取得します。データが設定されていない場合、呼び出しは成功し、dataNULLに設定されます。

基本的なNode-APIデータ型#

Node-APIは、さまざまなAPIで使用される抽象化として、次の基本的なデータ型を公開します。これらのAPIは不透明として扱い、他のNode-API呼び出しでのみイントロスペクト可能にする必要があります。

napi_status#

Node-API呼び出しの成功または失敗を示す整数ステータスコード。現在、次のステータスコードがサポートされています。

typedef enum {
  napi_ok,
  napi_invalid_arg,
  napi_object_expected,
  napi_string_expected,
  napi_name_expected,
  napi_function_expected,
  napi_number_expected,
  napi_boolean_expected,
  napi_array_expected,
  napi_generic_failure,
  napi_pending_exception,
  napi_cancelled,
  napi_escape_called_twice,
  napi_handle_scope_mismatch,
  napi_callback_scope_mismatch,
  napi_queue_full,
  napi_closing,
  napi_bigint_expected,
  napi_date_expected,
  napi_arraybuffer_expected,
  napi_detachable_arraybuffer_expected,
  napi_would_deadlock,  /* unused */
  napi_no_external_buffers_allowed,
  napi_cannot_run_js
} napi_status; 

APIが失敗したステータスを返すときに、追加の情報が必要な場合は、napi_get_last_error_infoを呼び出すことで取得できます。

napi_extended_error_info#

typedef struct {
  const char* error_message;
  void* engine_reserved;
  uint32_t engine_error_code;
  napi_status error_code;
} napi_extended_error_info; 
  • error_message: エラーのVM中立的な説明を含むUTF8エンコードされた文字列。
  • engine_reserved: VM固有のエラー詳細のために予約されています。これは現在、どのVMにも実装されていません。
  • engine_error_code: VM固有のエラーコード。これは現在、どのVMにも実装されていません。
  • error_code: 最後のエラーで発生したNode-APIステータスコード。

詳細については、エラー処理セクションを参照してください。

napi_env#

napi_envは、基盤となるNode-API実装がVM固有の状態を永続化するために使用できるコンテキストを表すために使用されます。この構造は、ネイティブ関数が呼び出されるときに渡され、Node-API呼び出しを行うときに返される必要があります。具体的には、最初のネイティブ関数が呼び出されたときに渡されたのと同じnapi_envを、後続のネストされたNode-API呼び出しに渡す必要があります。一般的な再利用を目的としてnapi_envをキャッシュすること、および異なるWorkerスレッドで実行されている同じアドオンのインスタンス間でnapi_envを渡すことは許可されていません。ネイティブアドオンのインスタンスがアンロードされると、napi_envは無効になります。このイベントの通知は、napi_add_env_cleanup_hookおよびnapi_set_instance_dataに提供されるコールバックを通じて配信されます。

node_api_nogc_env#

安定性: 1 - 実験的

このnapi_envのバリアントは、同期ファイナライザー(node_api_nogc_finalize)に渡されます。最初の引数としてnode_api_nogc_env型のパラメータを受け入れるNode-APIのサブセットがあります。これらのAPIは、JavaScriptエンジンの状態にアクセスしないため、同期ファイナライザーから呼び出すのが安全です。これらのAPIにnapi_env型のパラメータを渡すことは許可されていますが、JavaScriptエンジンの状態にアクセスするAPIにnode_api_nogc_env型のパラメータを渡すことは許可されていません。キャストなしでそれを行おうとすると、アドオンがコンパイル時に、間違ったポインター型が関数に渡されたときに警告やエラーを発行するフラグを使用してコンパイルされた場合、コンパイラの警告またはエラーが発生します。同期ファイナライザーからそのようなAPIを呼び出すと、最終的にアプリケーションが終了します。

napi_value#

これは、JavaScriptの値を表すために使用される不透明なポインタです。

napi_threadsafe_function#

これは、napi_call_threadsafe_function()を介して複数のスレッドから非同期的に呼び出すことができるJavaScript関数を表す不透明なポインタです。

napi_threadsafe_function_release_mode#

スレッドセーフ関数をすぐに閉じる(napi_tsfn_abort)のか、単に解放する(napi_tsfn_release)のかを示すために、napi_release_threadsafe_function()に与える値。これにより、後でnapi_acquire_threadsafe_function()およびnapi_call_threadsafe_function()を介して使用できるようになります。

typedef enum {
  napi_tsfn_release,
  napi_tsfn_abort
} napi_threadsafe_function_release_mode; 

napi_threadsafe_function_call_mode#

スレッドセーフ関数に関連付けられたキューがいっぱいの場合に、呼び出しをブロックする必要があるかどうかを示すために、napi_call_threadsafe_function()に与える値。

typedef enum {
  napi_tsfn_nonblocking,
  napi_tsfn_blocking
} napi_threadsafe_function_call_mode; 

Node-APIメモリ管理型#

napi_handle_scope#

これは、特定のスコープ内で作成されたオブジェクトの寿命を制御および変更するために使用される抽象化です。一般に、Node-APIの値はハンドルスコープのコンテキスト内で作成されます。JavaScriptからネイティブメソッドが呼び出されると、デフォルトのハンドルスコープが存在します。ユーザーが明示的に新しいハンドルスコープを作成しない場合、Node-APIの値はデフォルトのハンドルスコープで作成されます。ネイティブメソッドの実行外のコードの呼び出し(たとえば、libuvコールバックの呼び出し中)の場合、モジュールはJavaScript値の作成につながる可能性のある関数を呼び出す前に、スコープを作成する必要があります。

ハンドルスコープは、napi_open_handle_scopeを使用して作成され、napi_close_handle_scopeを使用して破棄されます。スコープを閉じると、ハンドルスコープの有効期間中に作成されたすべてのnapi_valueが現在のスタックフレームから参照されなくなったことをGCに示すことができます。

詳細については、オブジェクトの寿命管理を確認してください。

napi_escapable_handle_scope#

エスケープ可能なハンドルスコープは、特定のハンドルスコープ内で作成された値を親スコープに返すための特別なタイプのハンドルスコープです。

napi_ref#

これは、napi_valueを参照するために使用する抽象化です。これにより、ユーザーはJavaScriptの値の寿命を管理でき、最小寿命を明示的に定義することもできます。

詳細については、オブジェクトの寿命管理を確認してください。

napi_type_tag#

2つの符号なし64ビット整数として格納された128ビットの値。これは、JavaScriptオブジェクトまたはexternalsが特定の型であることを保証するために「タグ付け」できるUUIDとして機能します。これは、オブジェクトのプロトタイプが操作された場合に誤検知を報告する可能性がある後者のnapi_instanceofよりも強力なチェックです。型タグ付けは、以前にJavaScriptオブジェクトに適用された型タグに対応するネイティブ型に、ラップされたオブジェクトから取得したポインタを安全にキャストできることを保証するため、napi_wrapと組み合わせて使用するのが最も役立ちます。

typedef struct {
  uint64_t lower;
  uint64_t upper;
} napi_type_tag; 
napi_async_cleanup_hook_handle#

napi_add_async_cleanup_hookによって返される不透明な値。非同期クリーンアップイベントのチェーンが完了したときに、napi_remove_async_cleanup_hookに渡す必要があります。

Node-APIコールバック型#

napi_callback_info#

コールバック関数に渡される不透明なデータ型。コールバックが呼び出されたコンテキストに関する追加情報を取得するために使用できます。

napi_callback#

Node-APIを介してJavaScriptに公開されるユーザー提供のネイティブ関数の関数ポインタ型。コールバック関数は、次のシグネチャを満たす必要があります。

typedef napi_value (*napi_callback)(napi_env, napi_callback_info); 

オブジェクトの寿命管理で説明されている理由がない限り、napi_callback内でハンドルまたはコールバックスコープを作成する必要はありません。

node_api_nogc_finalize#

安定性: 1 - 実験的

外部で所有されているデータが、関連付けられていたオブジェクトがガベージコレクションされたためにクリーンアップできる状態になったときに、ユーザーに通知できるようにするアドオン提供関数の関数ポインタ型。ユーザーは、オブジェクトのコレクション時に呼び出される次のシグネチャを満たす関数を提供する必要があります。現在、node_api_nogc_finalizeは、外部データを持つオブジェクトがいつ収集されるかを調べるために使用できます。

typedef void (*node_api_nogc_finalize)(node_api_nogc_env env,
                                      void* finalize_data,
                                      void* finalize_hint); 

オブジェクトのライフタイム管理で説明されている理由がない限り、関数本体内でハンドルやコールバックスコープを作成する必要はありません。

これらの関数は、JavaScriptエンジンがJavaScriptコードを実行できない状態のときに呼び出される可能性があるため、最初のパラメータとしてnode_api_nogc_envを受け入れるNode-APIのみを呼び出すことができます。現在のガベージコレクションサイクルが完了した後に実行するために、JavaScriptエンジンの状態へのアクセスが必要なNode-API呼び出しをスケジュールするには、node_api_post_finalizerを使用できます。

node_api_create_external_string_latin1およびnode_api_create_external_string_utf16の場合、外部文字列は環境シャットダウンの後期に収集される可能性があるため、envパラメータはnullになる可能性があります。

変更履歴

  • 実験的 (NAPI_EXPERIMENTAL)

    最初のパラメータとしてnode_api_nogc_envを受け入れるNode-APIのみを呼び出すことができます。そうしないと、アプリケーションは適切なエラーメッセージで終了します。この機能は、NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUTを定義することでオフにできます。

napi_finalize#

ガベージコレクションイベントに応じて、ガベージコレクションサイクルが完了した後に、Node-APIへの一連の呼び出しをスケジュールできるようにする、アドオンが提供する関数への関数ポインタ型。これらの関数ポインタは、node_api_post_finalizerで使用できます。

typedef void (*napi_finalize)(napi_env env,
                              void* finalize_data,
                              void* finalize_hint); 

変更履歴

  • 実験的 (NAPI_EXPERIMENTALが定義されている場合)

    この型の関数は、node_api_post_finalizer以外では、ファイナライザーとして使用できなくなりました。代わりにnode_api_nogc_finalizeを使用する必要があります。この機能は、NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUTを定義することでオフにできます。

napi_async_execute_callback#

非同期操作をサポートする関数で使用される関数ポインタ。コールバック関数は、次のシグネチャを満たす必要があります。

typedef void (*napi_async_execute_callback)(napi_env env, void* data); 

この関数の実装では、JavaScriptを実行したり、JavaScriptオブジェクトと対話したりするNode-API呼び出しを避ける必要があります。Node-API呼び出しは、代わりにnapi_async_complete_callbackで行う必要があります。napi_envパラメータを使用しないでください。JavaScriptの実行につながる可能性が高いためです。

napi_async_complete_callback#

非同期操作をサポートする関数で使用される関数ポインタ。コールバック関数は、次のシグネチャを満たす必要があります。

typedef void (*napi_async_complete_callback)(napi_env env,
                                             napi_status status,
                                             void* data); 

オブジェクトのライフタイム管理で説明されている理由がない限り、関数本体内でハンドルやコールバックスコープを作成する必要はありません。

napi_threadsafe_function_call_js#

非同期スレッドセーフ関数呼び出しで使用される関数ポインタ。コールバックはメインスレッドで呼び出されます。その目的は、セカンダリスレッドからのキューを介して到着するデータ項目を使用して、通常はnapi_call_functionを介してJavaScriptへの呼び出しに必要なパラメータを構築し、JavaScriptへの呼び出しを行うことです。

セカンダリスレッドからキューを介して到着したデータは、dataパラメータで提供され、呼び出すJavaScript関数はjs_callbackパラメータで提供されます。

Node-APIは、このコールバックを呼び出す前に環境を設定するため、napi_make_callbackではなく、napi_call_functionを介してJavaScript関数を呼び出すだけで十分です。

コールバック関数は、次のシグネチャを満たす必要があります。

typedef void (*napi_threadsafe_function_call_js)(napi_env env,
                                                 napi_value js_callback,
                                                 void* context,
                                                 void* data); 
  • [in] env: API呼び出しに使用する環境。スレッドセーフ関数の破棄中でdataを解放する必要がある場合はNULL
  • [in] js_callback: 呼び出すJavaScript関数。スレッドセーフ関数の破棄中でdataを解放する必要がある場合はNULL。また、スレッドセーフ関数がjs_callbackなしで作成された場合もNULLになる可能性があります。
  • [in] context: スレッドセーフ関数の作成に使用されたオプションデータ。
  • [in] data: セカンダリスレッドによって作成されたデータ。このネイティブデータをJavaScript値(Node-API関数を使用)に変換し、js_callbackが呼び出されたときにパラメータとして渡すのは、コールバックの責任です。このポインタは、スレッドとこのコールバックによって完全に管理されます。したがって、このコールバックはデータを解放する必要があります。

オブジェクトのライフタイム管理で説明されている理由がない限り、関数本体内でハンドルやコールバックスコープを作成する必要はありません。

napi_cleanup_hook#

napi_add_env_cleanup_hookで使用される関数ポインタ。環境が破棄されるときに呼び出されます。

コールバック関数は、次のシグネチャを満たす必要があります。

typedef void (*napi_cleanup_hook)(void* data); 
napi_async_cleanup_hook#

napi_add_async_cleanup_hookで使用される関数ポインタ。環境が破棄されるときに呼び出されます。

コールバック関数は、次のシグネチャを満たす必要があります。

typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
                                        void* data); 

関数の本体では、非同期クリーンアップアクションを開始し、その最後に、napi_remove_async_cleanup_hookの呼び出しでhandleを渡す必要があります。

エラー処理#

Node-APIでは、エラー処理に、戻り値とJavaScript例外の両方を使用します。次のセクションでは、それぞれのケースのアプローチについて説明します。

戻り値#

すべてのNode-API関数は、同じエラー処理パターンを共有しています。すべてのAPI関数の戻り型はnapi_statusです。

リクエストが成功し、キャッチされないJavaScript例外がスローされなかった場合、戻り値はnapi_okになります。エラーが発生し、例外がスローされた場合、エラーのnapi_status値が返されます。例外がスローされ、エラーが発生しなかった場合、napi_pending_exceptionが返されます。

napi_okまたはnapi_pending_exception以外の戻り値が返された場合は、例外が保留されているかどうかを確認するために、napi_is_exception_pendingを呼び出す必要があります。詳細については、例外に関するセクションを参照してください。

可能なnapi_status値の完全なセットは、napi_api_types.hで定義されています。

napi_status戻り値は、発生したエラーのVMに依存しない表現を提供します。場合によっては、エラーを表す文字列やVM(エンジン)固有の情報など、より詳細な情報を取得できると便利です。

この情報を取得するために、napi_extended_error_info構造体を返すnapi_get_last_error_infoが提供されています。napi_extended_error_info構造体の形式は次のとおりです。

typedef struct napi_extended_error_info {
  const char* error_message;
  void* engine_reserved;
  uint32_t engine_error_code;
  napi_status error_code;
}; 
  • error_message: 発生したエラーのテキスト表現。
  • engine_reserved: エンジン専用の予約された不透明ハンドル。
  • engine_error_code: VM固有のエラーコード。
  • error_code: 最後のエラーのNode-APIステータスコード。

napi_get_last_error_infoは、最後に行われたNode-API呼び出しの情報を返します。

拡張情報のコンテンツまたは形式はSemVerの対象ではなく、いつでも変更される可能性があるため、依存しないでください。これはロギングのみを目的としています。

napi_get_last_error_info#
napi_status
napi_get_last_error_info(node_api_nogc_env env,
                         const napi_extended_error_info** result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: エラーに関する詳細情報を含むnapi_extended_error_info構造体。

APIが成功した場合はnapi_okを返します。

このAPIは、発生した最後のエラーに関する情報を含むnapi_extended_error_info構造体を取得します。

返されたnapi_extended_error_infoの内容は、同じenvでNode-API関数が呼び出されるまでのみ有効です。これにはnapi_is_exception_pendingの呼び出しも含まれるため、後で使用できるように、情報のコピーを作成する必要がある場合があります。error_messageで返されたポインタは静的に定義された文字列を指しているため、別のNode-API関数が呼び出される前に、error_messageフィールド(上書きされます)からコピーアウトしていれば、そのポインタを使用しても安全です。

拡張情報のコンテンツまたは形式はSemVerの対象ではなく、いつでも変更される可能性があるため、依存しないでください。これはロギングのみを目的としています。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

例外#

Node-API関数の呼び出しは、保留中のJavaScript例外になる可能性があります。これは、JavaScriptの実行を引き起こさない可能性のあるAPI関数であっても同様です。

関数によって返されたnapi_statusnapi_okの場合、例外は保留されておらず、追加のアクションは必要ありません。返されたnapi_statusnapi_okまたはnapi_pending_exception以外のいずれかである場合、すぐに戻るのではなく、回復して続行するために、napi_is_exception_pendingを呼び出して、例外が保留されているかどうかを判断する必要があります。

多くの場合、Node-API関数が呼び出され、例外がすでに保留されている場合、関数はnapi_pending_exceptionnapi_statusですぐに戻ります。ただし、これはすべての関数に当てはまるわけではありません。Node-APIでは、JavaScriptに戻る前に最小限のクリーンアップを許可するために、関数の一部を呼び出すことができます。その場合、napi_statusは関数のステータスを反映します。以前に保留中の例外は反映しません。混乱を避けるために、すべての関数呼び出し後にエラー状態を確認してください。

例外が保留中の場合は、次の2つのアプローチのいずれかを採用できます。

最初のアプローチは、適切なクリーンアップを行い、JavaScriptに実行を戻すことです。JavaScriptへの移行の一部として、ネイティブメソッドが呼び出されたJavaScriptコードの箇所で例外がスローされます。例外が保留されている間、ほとんどのNode-API呼び出しの動作は規定されておらず、多くの場合、単にnapi_pending_exceptionを返すだけなので、できるだけ処理を少なくし、例外が処理できるJavaScriptに戻るようにしてください。

2番目のアプローチは、例外を処理しようとすることです。ネイティブコードが例外をキャッチし、適切なアクションを実行してから続行できる場合があります。これは、例外が安全に処理できることがわかっている特定のケースでのみ推奨されます。このような場合、napi_get_and_clear_last_exceptionを使用して例外を取得し、クリアすることができます。成功した場合、resultには最後にスローされたJavaScriptのObjectへのハンドルが含まれます。例外を取得した後、例外を処理できないと判断された場合は、napi_throwを使用して再度スローできます。ここで、errorはスローされるJavaScriptの値です。

ネイティブコードが例外をスローする必要がある場合や、napi_valueがJavaScriptのErrorオブジェクトのインスタンスであるかどうかを判断する必要がある場合に、次のユーティリティ関数も使用できます:napi_throw_errornapi_throw_type_errornapi_throw_range_errornode_api_throw_syntax_error、およびnapi_is_error

ネイティブコードがErrorオブジェクトを作成する必要がある場合に、次のユーティリティ関数も使用できます:napi_create_errornapi_create_type_errornapi_create_range_error、およびnode_api_create_syntax_error。ここで、resultは、新しく作成されたJavaScriptのErrorオブジェクトを参照するnapi_valueです。

Node.jsプロジェクトは、内部で生成されるすべてのエラーにエラーコードを追加しています。目標は、アプリケーションがすべてのエラーチェックにこれらのエラーコードを使用することです。関連するエラーメッセージは残りますが、ログと表示のみに使用されることを意図しており、メッセージはSemVerを適用せずに変更できると想定されます。Node-APIでこのモデルを(内部機能として、またモジュール固有の機能として(良い習慣として))サポートするために、throw_およびcreate_関数は、エラーオブジェクトに追加されるコードの文字列であるオプションのcodeパラメーターを受け取ります。オプションのパラメーターがNULLの場合、エラーに関連付けられるコードはありません。コードが指定されている場合、エラーに関連付けられた名前も次のように更新されます。

originalName [code] 

ここで、originalNameはエラーに関連付けられた元の名前であり、codeは提供されたコードです。たとえば、コードが'ERR_ERROR_1'で、TypeErrorが作成されている場合、名前は次のようになります。

TypeError [ERR_ERROR_1] 
napi_throw#
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error); 
  • [in] env: APIが呼び出される環境。
  • [in] error: スローされるJavaScript値。

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたJavaScript値をスローします。

napi_throw_error#
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
                                         const char* code,
                                         const char* msg); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに設定されるオプションのエラーコード。
  • [in] msg: エラーに関連付けられるテキストを表すC文字列。

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのErrorをスローします。

napi_throw_type_error#
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
                                              const char* code,
                                              const char* msg); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに設定されるオプションのエラーコード。
  • [in] msg: エラーに関連付けられるテキストを表すC文字列。

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのTypeErrorをスローします。

napi_throw_range_error#
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
                                               const char* code,
                                               const char* msg); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに設定されるオプションのエラーコード。
  • [in] msg: エラーに関連付けられるテキストを表すC文字列。

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのRangeErrorをスローします。

node_api_throw_syntax_error#
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
                                                    const char* code,
                                                    const char* msg); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに設定されるオプションのエラーコード。
  • [in] msg: エラーに関連付けられるテキストを表すC文字列。

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのSyntaxErrorをスローします。

napi_is_error#
NAPI_EXTERN napi_status napi_is_error(napi_env env,
                                      napi_value value,
                                      bool* result); 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックされるnapi_value
  • [out] result: napi_valueがエラーを表す場合はtrueに、それ以外の場合はfalseに設定されるブール値。

APIが成功した場合はnapi_okを返します。

このAPIは、napi_valueがエラーオブジェクトを表すかどうかをチェックするためにクエリします。

napi_create_error#
NAPI_EXTERN napi_status napi_create_error(napi_env env,
                                          napi_value code,
                                          napi_value msg,
                                          napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに関連付けられるエラーコードの文字列を持つオプションのnapi_value
  • [in] msg: Errorのメッセージとして使用されるJavaScriptのstringを参照するnapi_value
  • [out] result: 作成されたエラーを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのErrorを返します。

napi_create_type_error#
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
                                               napi_value code,
                                               napi_value msg,
                                               napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに関連付けられるエラーコードの文字列を持つオプションのnapi_value
  • [in] msg: Errorのメッセージとして使用されるJavaScriptのstringを参照するnapi_value
  • [out] result: 作成されたエラーを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのTypeErrorを返します。

napi_create_range_error#
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
                                                napi_value code,
                                                napi_value msg,
                                                napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに関連付けられるエラーコードの文字列を持つオプションのnapi_value
  • [in] msg: Errorのメッセージとして使用されるJavaScriptのstringを参照するnapi_value
  • [out] result: 作成されたエラーを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのRangeErrorを返します。

node_api_create_syntax_error#
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
                                                     napi_value code,
                                                     napi_value msg,
                                                     napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] code: エラーに関連付けられるエラーコードの文字列を持つオプションのnapi_value
  • [in] msg: Errorのメッセージとして使用されるJavaScriptのstringを参照するnapi_value
  • [out] result: 作成されたエラーを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、指定されたテキストを含むJavaScriptのSyntaxErrorを返します。

napi_get_and_clear_last_exception#
napi_status napi_get_and_clear_last_exception(napi_env env,
                                              napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: 保留中の例外がある場合は例外、それ以外の場合はNULL

APIが成功した場合はnapi_okを返します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_is_exception_pending#
napi_status napi_is_exception_pending(napi_env env, bool* result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: 例外が保留中の場合はtrueに設定されるブール値。

APIが成功した場合はnapi_okを返します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_fatal_exception#
napi_status napi_fatal_exception(napi_env env, napi_value err); 
  • [in] env: APIが呼び出される環境。
  • [in] err: 'uncaughtException'に渡されるエラー。

JavaScriptで'uncaughtException'をトリガーします。非同期コールバックが回復する方法のない例外をスローする場合に役立ちます。

致命的なエラー#

ネイティブアドオンで回復不能なエラーが発生した場合、致命的なエラーをスローしてプロセスをすぐに終了させることができます。

napi_fatal_error#
NAPI_NO_RETURN void napi_fatal_error(const char* location,
                                     size_t location_len,
                                     const char* message,
                                     size_t message_len); 
  • [in] location: エラーが発生したオプションの場所。
  • [in] location_len: 場所の長さ(バイト単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [in] message: エラーに関連付けられたメッセージ。
  • [in] message_len: メッセージの長さ(バイト単位)。null終端の場合はNAPI_AUTO_LENGTH

関数呼び出しは戻らず、プロセスは終了します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

オブジェクトのライフタイム管理#

Node-API呼び出しが行われると、基になるVMのヒープ内のオブジェクトへのハンドルがnapi_valuesとして返される場合があります。これらのハンドルは、ネイティブコードで不要になるまでオブジェクトを「ライブ」に保持する必要があります。そうしないと、ネイティブコードが使用を完了する前にオブジェクトが回収される可能性があります。

オブジェクトハンドルが返されると、「スコープ」に関連付けられます。デフォルトのスコープの寿命は、ネイティブメソッド呼び出しの寿命に関連付けられています。結果として、デフォルトでは、ハンドルは有効なままであり、これらのハンドルに関連付けられたオブジェクトは、ネイティブメソッド呼び出しの寿命の間、ライブに保持されます。

ただし、多くの場合、ハンドルはネイティブメソッドの寿命よりも短い寿命または長い寿命で有効なままである必要があります。次のセクションでは、ハンドル寿命をデフォルトから変更するために使用できるNode-API関数について説明します。

ハンドル寿命をネイティブメソッドの寿命よりも短くする#

多くの場合、ハンドルの寿命をネイティブメソッドの寿命よりも短くする必要があります。たとえば、大きな配列内の要素を反復処理するループを持つネイティブメソッドについて考えてみましょう。

for (int i = 0; i < 1000000; i++) {
  napi_value result;
  napi_status status = napi_get_element(env, object, i, &result);
  if (status != napi_ok) {
    break;
  }
  // do something with element
} 

これにより、大量のハンドルが作成され、かなりのリソースが消費されます。さらに、ネイティブコードは最新のハンドルしか使用できませんが、関連付けられたすべてのオブジェクトも同じスコープを共有するため、ライブに保たれます。

このケースに対処するために、Node-APIは、新しく作成されたハンドルが関連付けられる新しい「スコープ」を確立する機能を提供します。これらのハンドルが不要になったら、スコープを「閉じる」ことができ、スコープに関連付けられたハンドルはすべて無効になります。スコープを開閉するために利用できるメソッドは、napi_open_handle_scopenapi_close_handle_scopeです。

Node-APIは、単一の入れ子になったスコープの階層のみをサポートしています。常にアクティブなスコープは1つだけであり、アクティブな間は、すべての新しいハンドルがそのスコープに関連付けられます。スコープは、開かれた順序とは逆の順序で閉じる必要があります。さらに、ネイティブメソッド内で作成されたすべてのスコープは、そのメソッドから戻る前に閉じる必要があります。

前の例を使用すると、napi_open_handle_scopenapi_close_handle_scopeへの呼び出しを追加すると、ループの実行全体を通して最大で1つのハンドルが有効になることが保証されます。

for (int i = 0; i < 1000000; i++) {
  napi_handle_scope scope;
  napi_status status = napi_open_handle_scope(env, &scope);
  if (status != napi_ok) {
    break;
  }
  napi_value result;
  status = napi_get_element(env, object, i, &result);
  if (status != napi_ok) {
    break;
  }
  // do something with element
  status = napi_close_handle_scope(env, scope);
  if (status != napi_ok) {
    break;
  }
} 

スコープをネストする場合、内側のスコープからのハンドルがそのスコープの寿命を超えて存在する必要がある場合があります。Node-API は、このケースをサポートするために「エスケープ可能なスコープ」をサポートしています。エスケープ可能なスコープを使用すると、1 つのハンドルを「昇格」させることができ、それによって現在のスコープから「エスケープ」し、ハンドルの寿命が現在のスコープから外側のスコープの寿命に変わります。

エスケープ可能なスコープを開閉するために使用できるメソッドは、napi_open_escapable_handle_scope および napi_close_escapable_handle_scope です。

ハンドルを昇格させるリクエストは、napi_escape_handle を介して行われます。これは一度しか呼び出すことができません。

napi_open_handle_scope#
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
                                               napi_handle_scope* result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: 新しいスコープを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、新しいスコープを開きます。

napi_close_handle_scope#
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
                                                napi_handle_scope scope); 
  • [in] env: APIが呼び出される環境。
  • [in] scope: 閉じるスコープを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、渡されたスコープを閉じます。スコープは、作成された順序の逆順で閉じる必要があります。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_open_escapable_handle_scope#
NAPI_EXTERN napi_status
    napi_open_escapable_handle_scope(napi_env env,
                                     napi_handle_scope* result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: 新しいスコープを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、1 つのオブジェクトを外側のスコープに昇格させることができる新しいスコープを開きます。

napi_close_escapable_handle_scope#
NAPI_EXTERN napi_status
    napi_close_escapable_handle_scope(napi_env env,
                                      napi_handle_scope scope); 
  • [in] env: APIが呼び出される環境。
  • [in] scope: 閉じるスコープを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、渡されたスコープを閉じます。スコープは、作成された順序の逆順で閉じる必要があります。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_escape_handle#
napi_status napi_escape_handle(napi_env env,
                               napi_escapable_handle_scope scope,
                               napi_value escapee,
                               napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] scope: 現在のスコープを表す napi_value
  • [in] escapee: エスケープする JavaScript Object を表す napi_value
  • [out] result: 外側のスコープ内のエスケープされた Object へのハンドルを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、JavaScript オブジェクトへのハンドルを昇格させ、外側のスコープの寿命の間有効にします。スコープごとに 1 回しか呼び出すことができません。複数回呼び出すとエラーが返されます。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

ネイティブメソッドの寿命よりも長い寿命を持つ値への参照#

場合によっては、アドオンが単一のネイティブメソッドの呼び出しよりも長い寿命を持つ値を作成して参照できるようにする必要があります。たとえば、コンストラクタを作成し、後でインスタンスを作成するリクエストでそのコンストラクタを使用するには、多くの異なるインスタンス作成リクエストでコンストラクタオブジェクトを参照できる必要があります。これは、前のセクションで説明したように、napi_value として返される通常のハンドルでは不可能です。通常のハンドルの寿命はスコープによって管理され、ネイティブメソッドの終了前にすべてのスコープを閉じる必要があります。

Node-API は、値への永続的な参照を作成するためのメソッドを提供します。現在、Node-API では、オブジェクト、外部、関数、シンボルを含む、限られた値タイプに対してのみ参照を作成できます。

各参照には、0 以上の値を持つ関連付けられたカウントがあり、参照が対応する値を存続させるかどうかを決定します。カウントが 0 の参照は、値が収集されるのを防ぎません。オブジェクト (オブジェクト、関数、外部) およびシンボル型の値は「弱い」参照になり、収集されていない間もアクセスできます。カウントが 0 より大きいと、値が収集されるのを防ぎます。

シンボル値には異なる種類があります。真の弱い参照の動作は、napi_create_symbol 関数または JavaScript Symbol() コンストラクタの呼び出しで作成されたローカルシンボルでのみサポートされています。node_api_symbol_for 関数または JavaScript Symbol.for() 関数の呼び出しで作成されたグローバルに登録されたシンボルは、ガベージコレクタがそれらを収集しないため、常に強い参照のままです。Symbol.iterator などの既知のシンボルも同様です。これらもガベージコレクタによって収集されることはありません。

参照は、初期参照カウントを使用して作成できます。その後、カウントは napi_reference_ref および napi_reference_unref を介して変更できます。参照のカウントが 0 の間にオブジェクトが収集された場合、参照に関連付けられたオブジェクトを取得するための後続のすべての呼び出し napi_get_reference_value は、返された napi_value に対して NULL を返します。オブジェクトが収集された参照に対して napi_reference_ref を呼び出そうとすると、エラーが発生します。

参照は、アドオンで不要になったら削除する必要があります。参照が削除されると、対応するオブジェクトが収集されるのを防ぐことはなくなります。永続的な参照を削除しないと、永続的な参照のネイティブメモリとヒープ上の対応するオブジェクトの両方が永久に保持される「メモリリーク」が発生します。

同じオブジェクトを参照する複数の永続的な参照を作成できます。それぞれが個々のカウントに基づいてオブジェクトを存続させるかどうかを決定します。同じオブジェクトへの複数の永続的な参照は、予期せずネイティブメモリを存続させる可能性があります。永続的な参照のネイティブ構造は、参照されるオブジェクトのファイナライザが実行されるまで存続させておく必要があります。同じオブジェクトに対して新しい永続的な参照が作成された場合、そのオブジェクトのファイナライザは実行されず、以前の永続的な参照によって示されるネイティブメモリは解放されません。これは、可能な場合は napi_reference_unref に加えて napi_delete_reference を呼び出すことで回避できます。

変更履歴

  • 実験的 (NAPI_EXPERIMENTAL が定義されている場合)

    参照はすべての値タイプに対して作成できます。新しくサポートされる値タイプは弱い参照セマンティクスをサポートしておらず、これらのタイプの値は参照カウントが 0 になると解放され、参照からアクセスできなくなります。

napi_create_reference#
NAPI_EXTERN napi_status napi_create_reference(napi_env env,
                                              napi_value value,
                                              uint32_t initial_refcount,
                                              napi_ref* result); 
  • [in] env: APIが呼び出される環境。
  • [in] value: 参照が作成される napi_value
  • [in] initial_refcount: 新しい参照の初期参照カウント。
  • [out] result: 新しい参照を指す napi_ref

APIが成功した場合はnapi_okを返します。

この API は、渡された値への指定された参照カウントを持つ新しい参照を作成します。

napi_delete_reference#
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref); 
  • [in] env: APIが呼び出される環境。
  • [in] ref: 削除する napi_ref

APIが成功した場合はnapi_okを返します。

この API は、渡された参照を削除します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_reference_ref#
NAPI_EXTERN napi_status napi_reference_ref(napi_env env,
                                           napi_ref ref,
                                           uint32_t* result); 
  • [in] env: APIが呼び出される環境。
  • [in] ref: 参照カウントが増加する napi_ref
  • [out] result: 新しい参照カウント。

APIが成功した場合はnapi_okを返します。

この API は、渡された参照の参照カウントをインクリメントし、結果の参照カウントを返します。

napi_reference_unref#
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
                                             napi_ref ref,
                                             uint32_t* result); 
  • [in] env: APIが呼び出される環境。
  • [in] ref: 参照カウントがデクリメントされる napi_ref
  • [out] result: 新しい参照カウント。

APIが成功した場合はnapi_okを返します。

この API は、渡された参照の参照カウントをデクリメントし、結果の参照カウントを返します。

napi_get_reference_value#
NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,
                                                 napi_ref ref,
                                                 napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] ref: 対応する値が要求される napi_ref
  • [out] result: napi_ref によって参照される napi_value

APIが成功した場合はnapi_okを返します。

まだ有効な場合、この API は napi_ref に関連付けられた JavaScript 値を表す napi_value を返します。それ以外の場合、result は NULL になります。

現在の Node.js 環境の終了時のクリーンアップ#

Node.js プロセスは通常、終了時にすべてのリソースを解放しますが、Node.js の埋め込みまたは将来の Worker のサポートでは、現在 Node.js 環境が終了したときに実行されるクリーンアップフックをアドオンが登録する必要があります。

Node-API は、そのようなコールバックを登録および登録解除するための関数を提供します。これらのコールバックが実行されると、アドオンによって保持されているすべてのリソースを解放する必要があります。

napi_add_env_cleanup_hook#
NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_nogc_env env,
                                                  napi_cleanup_hook fun,
                                                  void* arg); 

現在の Node.js 環境が終了したときに、arg パラメータを使用して実行される関数として fun を登録します。

関数は、異なる arg 値で複数回安全に指定できます。その場合、複数回も呼び出されます。同じ fun および arg 値を複数回指定することは許可されておらず、プロセスが中止されます。

フックは逆順で呼び出されます。つまり、最後に追加されたフックが最初に呼び出されます。

このフックの削除は、napi_remove_env_cleanup_hook を使用して行うことができます。通常、このフックが追加されたリソースが破棄されるときに発生します。

非同期クリーンアップには、napi_add_async_cleanup_hook が利用できます。

napi_remove_env_cleanup_hook#
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_nogc_env env,
                                                     void (*fun)(void* arg),
                                                     void* arg); 

現在の Node.js 環境が終了したときに、arg パラメータを使用して実行される関数として fun の登録を解除します。引数と関数値の両方が完全に一致する必要があります。

関数は、元々 napi_add_env_cleanup_hook で登録されている必要があります。そうでない場合、プロセスは中止されます。

napi_add_async_cleanup_hook#
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
    node_api_nogc_env env,
    napi_async_cleanup_hook hook,
    void* arg,
    napi_async_cleanup_hook_handle* remove_handle); 
  • [in] env: APIが呼び出される環境。
  • [in] hook: 環境の破棄時に呼び出す関数ポインタ。
  • [in] arg: hook が呼び出される際に渡されるポインター。
  • [out] remove_handle: 非同期クリーンアップフックを参照するオプションのハンドル。

現在の Node.js 環境が終了した際に、remove_handle パラメーターと arg パラメーターとともに実行される関数として、napi_async_cleanup_hook 型の関数である hook を登録します。

napi_add_env_cleanup_hook とは異なり、このフックは非同期処理を行うことが許可されています。

それ以外の場合、動作は一般的に napi_add_env_cleanup_hook の動作と一致します。

remove_handleNULL でない場合、不透明な値が格納されます。この値は、フックが既に呼び出されているかどうかにかかわらず、後で napi_remove_async_cleanup_hook に渡す必要があります。通常、これは、このフックが追加されたリソースが破棄されるときに行われます。

napi_remove_async_cleanup_hook#
NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(
    napi_async_cleanup_hook_handle remove_handle); 

remove_handle に対応するクリーンアップフックの登録を解除します。これにより、フックが既に実行を開始している場合を除き、フックの実行が防止されます。これは、napi_add_async_cleanup_hook から取得したすべての napi_async_cleanup_hook_handle 値に対して呼び出す必要があります。

Node.js 環境終了時のファイナライゼーション#

Node.js 環境は、worker.terminate() のリクエストのように、JavaScript の実行が禁止され次第、可能な限り任意のタイミングで破棄される可能性があります。環境が破棄されると、JavaScript オブジェクト、スレッドセーフ関数、および環境インスタンスデータに登録された napi_finalize コールバックが、直ちに個別で呼び出されます。

napi_finalize コールバックの呼び出しは、手動で登録されたクリーンアップフックの後でスケジュールされます。環境シャットダウン中のアドオンのファイナライゼーションの適切な順序を確保し、napi_finalize コールバックでの use-after-free を回避するために、アドオンは napi_add_env_cleanup_hook および napi_add_async_cleanup_hook を使用してクリーンアップフックを登録し、割り当てられたリソースを適切な順序で手動で解放する必要があります。

モジュールの登録#

Node-API モジュールは、NODE_MODULE マクロを使用する代わりに、以下の方法を使用することを除いて、他のモジュールと同様の方法で登録されます。

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

次の違いは、Init メソッドのシグネチャです。Node-API モジュールの場合、以下のようになります。

napi_value Init(napi_env env, napi_value exports); 

Init からの戻り値は、モジュールの exports オブジェクトとして扱われます。便宜上、Init メソッドには、exports パラメーターを介して空のオブジェクトが渡されます。InitNULL を返す場合、exports として渡されたパラメーターがモジュールによってエクスポートされます。Node-API モジュールは module オブジェクトを変更することはできませんが、モジュールの exports プロパティとして任意のものを指定できます。

アドオンによって提供されるメソッドとして呼び出すことができるように、メソッド hello を関数として追加するには

napi_value Init(napi_env env, napi_value exports) {
  napi_status status;
  napi_property_descriptor desc = {
    "hello",
    NULL,
    Method,
    NULL,
    NULL,
    NULL,
    napi_writable | napi_enumerable | napi_configurable,
    NULL
  };
  status = napi_define_properties(env, exports, 1, &desc);
  if (status != napi_ok) return NULL;
  return exports;
} 

アドオンの require() によって返される関数を設定するには

napi_value Init(napi_env env, napi_value exports) {
  napi_value method;
  napi_status status;
  status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method);
  if (status != napi_ok) return NULL;
  return method;
} 

新しいインスタンスを作成できるようにクラスを定義するには(多くの場合、Object wrap と共に使用されます)

// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
  napi_status status;
  napi_property_descriptor properties[] = {
    { "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
    DECLARE_NAPI_METHOD("plusOne", PlusOne),
    DECLARE_NAPI_METHOD("multiply", Multiply),
  };

  napi_value cons;
  status =
      napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
  if (status != napi_ok) return NULL;

  status = napi_create_reference(env, cons, 1, &constructor);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "MyObject", cons);
  if (status != napi_ok) return NULL;

  return exports;
} 

NAPI_MODULE のショートハンドとして機能し、Init 関数を定義する NAPI_MODULE_INIT マクロを使用することもできます。

NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
  napi_value answer;
  napi_status result;

  status = napi_create_int64(env, 42, &answer);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "answer", answer);
  if (status != napi_ok) return NULL;

  return exports;
} 

パラメーター env および exports は、NAPI_MODULE_INIT マクロの本体に提供されます。

すべての Node-API アドオンはコンテキスト対応であり、複数回ロードされる可能性があります。そのようなモジュールを宣言する際には、いくつかの設計上の考慮事項があります。コンテキスト対応アドオンに関するドキュメントで、詳細を確認してください。

変数 env および exports は、マクロ呼び出しに続く関数本体内で使用できます。

オブジェクトのプロパティの設定に関する詳細については、JavaScript プロパティの操作に関するセクションを参照してください。

アドオンモジュールの構築に関する一般的な詳細については、既存の API を参照してください。

JavaScript 値の操作#

Node-API は、すべての種類の JavaScript 値を作成するための一連の API を公開しています。これらの型のいくつかは、ECMAScript 言語仕様のセクション 6 でドキュメント化されています。

基本的に、これらの API は次のいずれかを行うために使用されます。

  1. 新しい JavaScript オブジェクトを作成する
  2. プリミティブ C 型から Node-API 値に変換する
  3. Node-API 値からプリミティブ C 型に変換する
  4. undefined および null を含むグローバルインスタンスを取得する

Node-API 値は、型 napi_value で表されます。JavaScript 値を必要とするすべての Node-API 呼び出しは、napi_value を受け取ります。場合によっては、API は napi_value の型を事前にチェックします。ただし、パフォーマンスを向上させるためには、呼び出し元が問題の napi_value が API で想定されている JavaScript 型であることを確認することをお勧めします。

列挙型#

napi_key_collection_mode#
typedef enum {
  napi_key_include_prototypes,
  napi_key_own_only
} napi_key_collection_mode; 

Keys/Properties フィルター列挙型を記述します

napi_key_collection_mode は、収集されるプロパティの範囲を制限します。

napi_key_own_only は、収集されるプロパティを与えられたオブジェクトのみに制限します。napi_key_include_prototypes は、オブジェクトのプロトタイプチェーンのすべてのキーも含まれます。

napi_key_filter#
typedef enum {
  napi_key_all_properties = 0,
  napi_key_writable = 1,
  napi_key_enumerable = 1 << 1,
  napi_key_configurable = 1 << 2,
  napi_key_skip_strings = 1 << 3,
  napi_key_skip_symbols = 1 << 4
} napi_key_filter; 

プロパティフィルタービット。それらは、合成フィルターを構築するために or 演算子で結合できます。

napi_key_conversion#
typedef enum {
  napi_key_keep_numbers,
  napi_key_numbers_to_strings
} napi_key_conversion; 

napi_key_numbers_to_strings は、整数インデックスを文字列に変換します。napi_key_keep_numbers は、整数インデックスの数値を返します。

napi_valuetype#
typedef enum {
  // ES6 types (corresponds to typeof)
  napi_undefined,
  napi_null,
  napi_boolean,
  napi_number,
  napi_string,
  napi_symbol,
  napi_object,
  napi_function,
  napi_external,
  napi_bigint,
} napi_valuetype; 

napi_value の型を記述します。これは一般的に、ECMAScript 言語仕様のセクション 6.1 で説明されている型に対応します。そのセクションの型に加えて、napi_valuetype は外部データを持つ FunctionObject も表すことができます。

napi_external の JavaScript 値は、プロパティを設定できず、プロトタイプがないプレーンなオブジェクトとして JavaScript に表示されます。

napi_typedarray_type#
typedef enum {
  napi_int8_array,
  napi_uint8_array,
  napi_uint8_clamped_array,
  napi_int16_array,
  napi_uint16_array,
  napi_int32_array,
  napi_uint32_array,
  napi_float32_array,
  napi_float64_array,
  napi_bigint64_array,
  napi_biguint64_array,
} napi_typedarray_type; 

これは、TypedArray の基になるバイナリスカラーデータ型を表します。この列挙型の要素は、ECMAScript 言語仕様のセクション 22.2 に対応します。

オブジェクト作成関数#

napi_create_array#
napi_status napi_create_array(napi_env env, napi_value* result) 
  • [in] env: Node-API呼び出しが実行される環境。
  • [out] result: JavaScript の Array を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、JavaScript の Array 型に対応する Node-API 値を返します。JavaScript 配列は、ECMAScript 言語仕様のセクション 22.1で説明されています。

napi_create_array_with_length#
napi_status napi_create_array_with_length(napi_env env,
                                          size_t length,
                                          napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] length: Array の初期の長さ。
  • [out] result: JavaScript の Array を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、JavaScript の Array 型に対応する Node-API 値を返します。Array の length プロパティは、渡された length パラメーターに設定されます。ただし、配列が作成されるときに、基になるバッファーが VM によって事前割り当てられることは保証されていません。その動作は、基になる VM 実装に任されています。バッファーが、C を介して直接読み書きできる連続したメモリブロックである必要がある場合は、napi_create_external_arraybuffer の使用を検討してください。

JavaScript 配列は、ECMAScript 言語仕様のセクション 22.1で説明されています。

napi_create_arraybuffer#
napi_status napi_create_arraybuffer(napi_env env,
                                    size_t byte_length,
                                    void** data,
                                    napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] length: 作成する配列バッファーの長さ(バイト単位)。
  • [out] data: ArrayBuffer の基になるバイトバッファーへのポインター。data は、NULL を渡すことでオプションで無視できます。
  • [out] result: JavaScript の ArrayBuffer を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、JavaScript の ArrayBuffer に対応する Node-API 値を返します。ArrayBuffer は、固定長のバイナリデータバッファーを表すために使用されます。通常、これらは TypedArray オブジェクトのバッキングバッファーとして使用されます。割り当てられた ArrayBuffer は、渡された length パラメーターによってサイズが決まる、基になるバイトバッファーを持ちます。呼び出し元がバッファーを直接操作する場合に備えて、基になるバッファーはオプションで呼び出し元に返されます。このバッファーは、ネイティブコードから直接書き込むことしかできません。JavaScript からこのバッファーに書き込むには、型付き配列または DataView オブジェクトを作成する必要があります。

JavaScript ArrayBuffer オブジェクトは、ECMAScript 言語仕様のセクション 24.1で説明されています。

napi_create_buffer#
napi_status napi_create_buffer(napi_env env,
                               size_t size,
                               void** data,
                               napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] size: 基になるバッファーのサイズ(バイト単位)。
  • [out] data: 基になるバッファーへの生のポインター。data は、NULL を渡すことでオプションで無視できます。
  • [out] result: node::Buffer を表す napi_value

APIが成功した場合はnapi_okを返します。

このAPIは、node::Bufferオブジェクトを割り当てます。これは引き続き完全にサポートされているデータ構造ですが、ほとんどの場合、TypedArrayを使用すれば十分です。

napi_create_buffer_copy#
napi_status napi_create_buffer_copy(napi_env env,
                                    size_t length,
                                    const void* data,
                                    void** result_data,
                                    napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] size: 入力バッファのサイズ(バイト単位)(新しいバッファのサイズと同じである必要があります)。
  • [in] data: コピー元の基になるバッファへの生のポインタ。
  • [out] result_data: 新しいBufferの基になるデータバッファへのポインタ。result_dataは、NULLを渡すことでオプションで無視できます。
  • [out] result: node::Buffer を表す napi_value

APIが成功した場合はnapi_okを返します。

このAPIは、node::Bufferオブジェクトを割り当て、渡されたバッファからコピーしたデータで初期化します。これは引き続き完全にサポートされているデータ構造ですが、ほとんどの場合、TypedArrayを使用すれば十分です。

napi_create_date#
napi_status napi_create_date(napi_env env,
                             double time,
                             napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] time: 1970年1月1日UTCからのミリ秒単位のECMAScript時間値。
  • [out] result: JavaScriptのDateを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIはうるう秒を考慮しません。ECMAScriptはPOSIX時間仕様に準拠しているため、無視されます。

このAPIは、JavaScriptのDateオブジェクトを割り当てます。

JavaScriptのDateオブジェクトについては、ECMAScript言語仕様のセクション20.3で説明されています。

napi_create_external#
napi_status napi_create_external(napi_env env,
                                 void* data,
                                 napi_finalize finalize_cb,
                                 void* finalize_hint,
                                 napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] data: 外部データへの生のポインタ。
  • [in] finalize_cb: 外部値が収集されるときに呼び出すオプションのコールバック。napi_finalizeで詳細を説明しています。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。
  • [out] result: 外部値を表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、外部データが添付されたJavaScript値を割り当てます。これは、JavaScriptコードを通じて外部データを渡し、後でnapi_get_value_externalを使用してネイティブコードで取得できるようにするために使用されます。

このAPIは、作成されたJavaScriptオブジェクトがガベージコレクションされたときに呼び出されるnapi_finalizeコールバックを追加します。

作成された値はオブジェクトではないため、追加のプロパティはサポートされていません。これは異なる値の型と見なされます。外部値を使用してnapi_typeof()を呼び出すと、napi_externalが返されます。

napi_create_external_arraybuffer#
napi_status
napi_create_external_arraybuffer(napi_env env,
                                 void* external_data,
                                 size_t byte_length,
                                 napi_finalize finalize_cb,
                                 void* finalize_hint,
                                 napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] external_data: ArrayBufferの基になるバイトバッファへのポインタ。
  • [in] byte_length: 基になるバッファのバイト単位の長さ。
  • [in] finalize_cb: ArrayBufferが収集されるときに呼び出すオプションのコールバック。napi_finalizeで詳細を説明しています。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。
  • [out] result: JavaScript の ArrayBuffer を表す napi_value

APIが成功した場合はnapi_okを返します。

Node.js以外のいくつかのランタイムでは、外部バッファのサポートが終了しています。Node.js以外のランタイムでは、外部バッファがサポートされていないことを示すために、このメソッドがnapi_no_external_buffers_allowedを返す場合があります。このようなランタイムの1つは、electron/issues/35801で説明されているように、Electronです。

すべてのランタイムとの幅広い互換性を維持するために、node-apiヘッダーを含める前に、アドオンでNODE_API_NO_EXTERNAL_BUFFERS_ALLOWEDを定義できます。そうすることで、外部バッファを作成する2つの関数が非表示になります。これにより、これらのメソッドの1つを誤って使用した場合にコンパイルエラーが発生することが保証されます。

このAPIは、JavaScriptのArrayBufferに対応するNode-API値を返します。ArrayBufferの基になるバイトバッファは外部で割り当てられ、管理されます。呼び出し元は、finalizeコールバックが呼び出されるまで、バイトバッファが有効なままであることを保証する必要があります。

このAPIは、作成されたJavaScriptオブジェクトがガベージコレクションされたときに呼び出されるnapi_finalizeコールバックを追加します。

JavaScriptのArrayBufferについては、ECMAScript言語仕様のセクション24.1で説明されています。

napi_create_external_buffer#
napi_status napi_create_external_buffer(napi_env env,
                                        size_t length,
                                        void* data,
                                        napi_finalize finalize_cb,
                                        void* finalize_hint,
                                        napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] length: 入力バッファのサイズ(バイト単位)(新しいバッファのサイズと同じである必要があります)。
  • [in] data: JavaScriptに公開する基になるバッファへの生のポインタ。
  • [in] finalize_cb: ArrayBufferが収集されるときに呼び出すオプションのコールバック。napi_finalizeで詳細を説明しています。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。
  • [out] result: node::Buffer を表す napi_value

APIが成功した場合はnapi_okを返します。

Node.js以外のいくつかのランタイムでは、外部バッファのサポートが終了しています。Node.js以外のランタイムでは、外部バッファがサポートされていないことを示すために、このメソッドがnapi_no_external_buffers_allowedを返す場合があります。このようなランタイムの1つは、electron/issues/35801で説明されているように、Electronです。

すべてのランタイムとの幅広い互換性を維持するために、node-apiヘッダーを含める前に、アドオンでNODE_API_NO_EXTERNAL_BUFFERS_ALLOWEDを定義できます。そうすることで、外部バッファを作成する2つの関数が非表示になります。これにより、これらのメソッドの1つを誤って使用した場合にコンパイルエラーが発生することが保証されます。

このAPIは、node::Bufferオブジェクトを割り当て、渡されたバッファによってバッキングされたデータで初期化します。これは引き続き完全にサポートされているデータ構造ですが、ほとんどの場合、TypedArrayを使用すれば十分です。

このAPIは、作成されたJavaScriptオブジェクトがガベージコレクションされたときに呼び出されるnapi_finalizeコールバックを追加します。

Node.js >=4の場合、BuffersUint8Arrayです。

napi_create_object#
napi_status napi_create_object(napi_env env, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [out] result: JavaScriptのObjectを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、デフォルトのJavaScriptのObjectを割り当てます。これは、JavaScriptでnew Object()を実行するのと同じです。

JavaScriptのObject型については、ECMAScript言語仕様のセクション6.1.7で説明されています。

napi_create_symbol#
napi_status napi_create_symbol(napi_env env,
                               napi_value description,
                               napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] description: シンボルの説明として設定されるJavaScriptのstringを参照するオプションのnapi_value
  • [out] result: JavaScriptのsymbolを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、UTF8エンコードされたC文字列からJavaScriptのsymbol値を作成します。

JavaScriptのsymbol型については、ECMAScript言語仕様のセクション19.4で説明されています。

node_api_symbol_for#
napi_status node_api_symbol_for(napi_env env,
                                const char* utf8description,
                                size_t length,
                                napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] utf8description: シンボルの説明として使用されるテキストを表すUTF-8 C文字列。
  • [in] length: 説明文字列の長さ(バイト単位)、またはnullで終了する場合はNAPI_AUTO_LENGTH
  • [out] result: JavaScriptのsymbolを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、指定された説明を持つ既存のシンボルをグローバルレジストリで検索します。シンボルが既に存在する場合はそれが返され、それ以外の場合は新しいシンボルがレジストリに作成されます。

JavaScriptのsymbol型については、ECMAScript言語仕様のセクション19.4で説明されています。

napi_create_typedarray#
napi_status napi_create_typedarray(napi_env env,
                                   napi_typedarray_type type,
                                   size_t length,
                                   napi_value arraybuffer,
                                   size_t byte_offset,
                                   napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] type: TypedArray内の要素のスカラーデータ型。
  • [in] length: TypedArray内の要素の数。
  • [in] arraybuffer: 型付き配列の基になるArrayBuffer
  • [in] byte_offset: TypedArrayの投影を開始するArrayBuffer内のバイトオフセット。
  • [out] result: JavaScriptのTypedArrayを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、既存のArrayBufferの上にJavaScriptのTypedArrayオブジェクトを作成します。TypedArrayオブジェクトは、各要素が同じ基になるバイナリスカラーデータ型を持つ、基になるデータバッファ上の配列のようなビューを提供します。

(length * size_of_element) + byte_offsetが、渡された配列のバイト単位のサイズ以下である必要があります。そうでない場合は、RangeError例外が発生します。

JavaScriptのTypedArrayオブジェクトについては、ECMAScript言語仕様のセクション22.2で説明されています。

napi_create_dataview#
napi_status napi_create_dataview(napi_env env,
                                 size_t byte_length,
                                 napi_value arraybuffer,
                                 size_t byte_offset,
                                 napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] length: DataView内の要素の数。
  • [in] arraybuffer: DataViewの基になるArrayBuffer
  • [in] byte_offset: DataViewの投影を開始するArrayBuffer内のバイトオフセット。
  • [out] result: JavaScriptのDataViewを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、既存のArrayBufferの上にJavaScriptのDataViewオブジェクトを作成します。DataViewオブジェクトは、基になるデータバッファ上の配列のようなビューを提供しますが、ArrayBuffer内で異なるサイズと型の項目を許可するビューです。

byte_length + byte_offsetが、渡された配列のバイト単位のサイズ以下である必要があります。そうでない場合は、RangeError例外が発生します。

JavaScriptのDataViewオブジェクトについては、ECMAScript言語仕様のセクション24.3で説明されています。

C型からNode-APIに変換する関数#

napi_create_int32#
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される整数値。
  • [out] result: JavaScriptのnumberを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのint32_t型からJavaScriptのnumber型に変換するために使用されます。

JavaScriptのnumber型については、ECMAScript言語仕様のセクション6.1.6で説明されています。

napi_create_uint32#
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される符号なし整数値。
  • [out] result: JavaScriptのnumberを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのuint32_t型からJavaScriptのnumber型に変換するために使用されます。

JavaScriptのnumber型については、ECMAScript言語仕様のセクション6.1.6で説明されています。

napi_create_int64#
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される整数値。
  • [out] result: JavaScriptのnumberを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのint64_t型からJavaScriptのnumber型に変換するために使用されます。

JavaScriptのnumber型については、ECMAScript言語仕様のセクション6.1.6で説明されています。JavaScriptでは、int64_tの完全な範囲を完全な精度で表現できないことに注意してください。Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1)の範囲外の整数値は、精度が失われます。

napi_create_double#
napi_status napi_create_double(napi_env env, double value, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される倍精度値。
  • [out] result: JavaScriptのnumberを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのdouble型からJavaScriptのnumber型に変換するために使用されます。

JavaScriptのnumber型については、ECMAScript言語仕様のセクション6.1.6で説明されています。

napi_create_bigint_int64#
napi_status napi_create_bigint_int64(napi_env env,
                                     int64_t value,
                                     napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される整数値。
  • [out] result: JavaScriptのBigIntを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのint64_t型をJavaScriptのBigInt型に変換します。

napi_create_bigint_uint64#
napi_status napi_create_bigint_uint64(napi_env env,
                                      uint64_t value,
                                      napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptで表現される符号なし整数値。
  • [out] result: JavaScriptのBigIntを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、Cのuint64_t型をJavaScriptのBigInt型に変換します。

napi_create_bigint_words#
napi_status napi_create_bigint_words(napi_env env,
                                     int sign_bit,
                                     size_t word_count,
                                     const uint64_t* words,
                                     napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] sign_bit: 結果のBigIntが正または負になるかを決定します。
  • [in] word_count: words配列の長さ。
  • [in] words: uint64_tリトルエンディアン64ビットワードの配列。
  • [out] result: JavaScriptのBigIntを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、符号なし64ビットワードの配列を単一のBigInt値に変換します。

結果のBigIntは、次のように計算されます。(-1)sign_bitwords[0]×(2640 + words[1]×(2641 + …)

napi_create_string_latin1#
napi_status napi_create_string_latin1(napi_env env,
                                      const char* str,
                                      size_t length,
                                      napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] str: ISO-8859-1エンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(バイト単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [out] result: JavaScriptのstringを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、ISO-8859-1エンコードされたC文字列からJavaScriptのstring値を生成します。ネイティブ文字列はコピーされます。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

node_api_create_external_string_latin1#

安定性: 1 - 実験的

napi_status
node_api_create_external_string_latin1(napi_env env,
                                       char* str,
                                       size_t length,
                                       napi_finalize finalize_callback,
                                       void* finalize_hint,
                                       napi_value* result,
                                       bool* copied); 
  • [in] env: APIが呼び出される環境。
  • [in] str: ISO-8859-1エンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(バイト単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [in] finalize_callback: 文字列が収集されるときに呼び出す関数。この関数は、以下のパラメータで呼び出されます。
    • [in] env: アドオンが実行されている環境。文字列がワーカーまたはメインのNode.jsインスタンスの終了の一部として収集されている場合、この値はnullになる可能性があります。
    • [in] data: これは、void*ポインタとしての値strです。
    • [in] finalize_hint: これは、APIに与えられた値finalize_hintです。napi_finalizeで詳細を確認できます。このパラメータはオプションです。null値を渡すことは、対応するJavaScript文字列が収集されたときにアドオンに通知する必要がないことを意味します。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。
  • [out] result: JavaScriptのstringを表すnapi_value
  • [out] copied: 文字列がコピーされたかどうか。コピーされた場合、ファイナライザはすでにstrを破棄するために呼び出されています。

APIが成功した場合はnapi_okを返します。

このAPIは、ISO-8859-1エンコードされたC文字列からJavaScriptのstring値を生成します。ネイティブ文字列はコピーされない可能性があり、したがってJavaScript値のライフサイクル全体にわたって存在する必要があります。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

napi_create_string_utf16#
napi_status napi_create_string_utf16(napi_env env,
                                     const char16_t* str,
                                     size_t length,
                                     napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] str: UTF16-LEエンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(2バイトコード単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [out] result: JavaScriptのstringを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、UTF16-LEエンコードされたC文字列からJavaScriptのstring値を生成します。ネイティブ文字列はコピーされます。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

node_api_create_external_string_utf16#

安定性: 1 - 実験的

napi_status
node_api_create_external_string_utf16(napi_env env,
                                      char16_t* str,
                                      size_t length,
                                      napi_finalize finalize_callback,
                                      void* finalize_hint,
                                      napi_value* result,
                                      bool* copied); 
  • [in] env: APIが呼び出される環境。
  • [in] str: UTF16-LEエンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(2バイトコード単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [in] finalize_callback: 文字列が収集されるときに呼び出す関数。この関数は、以下のパラメータで呼び出されます。
    • [in] env: アドオンが実行されている環境。文字列がワーカーまたはメインのNode.jsインスタンスの終了の一部として収集されている場合、この値はnullになる可能性があります。
    • [in] data: これは、void*ポインタとしての値strです。
    • [in] finalize_hint: これは、APIに与えられた値finalize_hintです。napi_finalizeで詳細を確認できます。このパラメータはオプションです。null値を渡すことは、対応するJavaScript文字列が収集されたときにアドオンに通知する必要がないことを意味します。
  • [in] finalize_hint: コレクション中にfinalizeコールバックに渡すオプションのヒント。
  • [out] result: JavaScriptのstringを表すnapi_value
  • [out] copied: 文字列がコピーされたかどうか。コピーされた場合、ファイナライザはすでにstrを破棄するために呼び出されています。

APIが成功した場合はnapi_okを返します。

このAPIは、UTF16-LEエンコードされたC文字列からJavaScriptのstring値を生成します。ネイティブ文字列はコピーされない可能性があり、したがってJavaScript値のライフサイクル全体にわたって存在する必要があります。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

napi_create_string_utf8#
napi_status napi_create_string_utf8(napi_env env,
                                    const char* str,
                                    size_t length,
                                    napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] str: UTF8エンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(バイト単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [out] result: JavaScriptのstringを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、UTF8エンコードされたC文字列からJavaScriptのstring値を生成します。ネイティブ文字列はコピーされます。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

node_api_create_property_key_utf16#

安定性: 1 - 実験的

napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env,
                                                          const char16_t* str,
                                                          size_t length,
                                                          napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] str: UTF16-LEエンコードされた文字列を表す文字バッファ。
  • [in] length: 文字列の長さ(2バイトコード単位)。null終端の場合はNAPI_AUTO_LENGTH
  • [out] result: オブジェクトのプロパティキーとして使用される最適化されたJavaScriptのstringを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIは、オブジェクトのプロパティキーとして使用される最適化されたJavaScriptのstring値を、UTF16-LEエンコードされたC文字列から生成します。ネイティブ文字列はコピーされます。

V8を含む多くのJavaScriptエンジンは、プロパティ値を設定および取得するためのキーとして内部化された文字列を使用しています。通常、ハッシュテーブルを使用して、そのような文字列を作成および検索します。キーの作成ごとに多少のコストがかかりますが、文字列全体ではなく文字列ポインタの比較を可能にすることで、その後のパフォーマンスが向上します。

新しいJavaScript文字列をプロパティキーとして使用する場合、一部のJavaScriptエンジンではnode_api_create_property_key_utf16関数を使用する方が効率的です。それ以外の場合は、napi_create_string_utf16またはnode_api_create_external_string_utf16関数を使用してください。この方法で文字列を作成/保存する際に、追加のオーバーヘッドが発生する可能性があるためです。

JavaScriptのstring型は、ECMAScript言語仕様のセクション6.1.4で説明されています。

Node-APIからC型に変換する関数#

napi_get_array_length#
napi_status napi_get_array_length(napi_env env,
                                  napi_value value,
                                  uint32_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 長さをクエリしているJavaScriptのArrayを表すnapi_value
  • [out] result: 配列の長さを表すuint32

APIが成功した場合はnapi_okを返します。

このAPIは、配列の長さを返します。

Arrayの長さは、ECMAScript言語仕様のセクション22.1.4.1で説明されています。

napi_get_arraybuffer_info#
napi_status napi_get_arraybuffer_info(napi_env env,
                                      napi_value arraybuffer,
                                      void** data,
                                      size_t* byte_length) 
  • [in] env: APIが呼び出される環境。
  • [in] arraybuffer: クエリしているArrayBufferを表すnapi_value
  • [out] data: ArrayBufferの基になるデータバッファ。byte_lengthが0の場合、これはNULLまたはその他のポインタ値になる可能性があります。
  • [out] byte_length: 基になるデータバッファの長さ(バイト単位)。

APIが成功した場合はnapi_okを返します。

このAPIは、ArrayBufferの基になるデータバッファとその長さを取得するために使用されます。

警告: このAPIを使用する際には注意してください。基になるデータバッファのライフタイムは、返された後でもArrayBufferによって管理されます。このAPIを使用する可能性のある安全な方法は、napi_create_referenceと組み合わせて使用することです。これは、ArrayBufferのライフタイムの制御を保証するために使用できます。また、他のGCをトリガーする可能性のあるAPIを呼び出さない限り、同じコールバック内で返されたデータバッファを使用することも安全です。

napi_get_buffer_info#
napi_status napi_get_buffer_info(napi_env env,
                                 napi_value value,
                                 void** data,
                                 size_t* length) 
  • [in] env: APIが呼び出される環境。
  • [in] value: クエリしているnode::BufferまたはUint8Arrayを表すnapi_value
  • [out] data: node::BufferまたはUint8Arrayの基になるデータバッファ。lengthが0の場合、これはNULLまたはその他のポインタ値になる可能性があります。
  • [out] length: 基になるデータバッファの長さ(バイト単位)。

APIが成功した場合はnapi_okを返します。

このメソッドは、napi_get_typedarray_infoと同じdatabyte_lengthを返します。また、napi_get_typedarray_infoは、値としてnode::Buffer(Uint8Array)も受け入れます。

このAPIは、node::Bufferの基になるデータバッファとその長さを取得するために使用されます。

警告: 基になるデータバッファのライフタイムがVMによって管理されている場合、保証されないため、このAPIを使用する際には注意してください。

napi_get_prototype#
napi_status napi_get_prototype(napi_env env,
                               napi_value object,
                               napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] object: プロトタイプを返すJavaScriptのObjectを表すnapi_value。これは、Object.getPrototypeOf(関数のprototypeプロパティと同じではありません)と同等のものを返します。
  • [out] result: 指定されたオブジェクトのプロトタイプを表すnapi_value

APIが成功した場合はnapi_okを返します。

napi_get_typedarray_info#
napi_status napi_get_typedarray_info(napi_env env,
                                     napi_value typedarray,
                                     napi_typedarray_type* type,
                                     size_t* length,
                                     void** data,
                                     napi_value* arraybuffer,
                                     size_t* byte_offset) 
  • [in] env: APIが呼び出される環境。
  • [in] typedarray: プロパティをクエリするTypedArrayを表すnapi_value
  • [out] type: TypedArray内の要素のスカラーデータ型。
  • [out] length: TypedArray内の要素の数。
  • [out] data: TypedArrayの最初の要素を指すようにbyte_offset値で調整されたTypedArrayの基になるデータバッファ。配列の長さが0の場合、これはNULLまたはその他のポインタ値になる可能性があります。
  • [out] arraybuffer: TypedArrayの基になるArrayBuffer
  • [out] byte_offset: 配列の最初の要素が配置されている、基になるネイティブ配列内のバイトオフセット。dataパラメータの値は、dataが配列の最初の要素を指すようにすでに調整されています。したがって、ネイティブ配列の最初のバイトはdata - byte_offsetになります。

APIが成功した場合はnapi_okを返します。

このAPIは、型付き配列のさまざまなプロパティを返します。

そのプロパティが不要な場合、出力パラメータのいずれかがNULLになる可能性があります。

警告: 基になるデータバッファはVMによって管理されるため、このAPIを使用する際には注意してください。

napi_get_dataview_info#
napi_status napi_get_dataview_info(napi_env env,
                                   napi_value dataview,
                                   size_t* byte_length,
                                   void** data,
                                   napi_value* arraybuffer,
                                   size_t* byte_offset) 
  • [in] env: APIが呼び出される環境。
  • [in] dataview: プロパティをクエリするDataViewを表すnapi_value
  • [out] byte_length: DataView内のバイト数。
  • [out] data: DataViewの基になるデータバッファ。byte_lengthが0の場合、これはNULLまたはその他のポインタ値になる可能性があります。
  • [out] arraybuffer: DataViewの基になるArrayBuffer
  • [out] byte_offset: DataViewの投影を開始するデータバッファ内のバイトオフセット。

APIが成功した場合はnapi_okを返します。

そのプロパティが不要な場合、出力パラメータのいずれかがNULLになる可能性があります。

このAPIは、DataViewのさまざまなプロパティを返します。

napi_get_date_value#
napi_status napi_get_date_value(napi_env env,
                                napi_value value,
                                double* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptのDateを表すnapi_value
  • [out] result: 1970年1月1日UTCの午前0時からの経過時間をミリ秒単位で表したdoubleとしての時間値。

このAPIはうるう秒を考慮しません。ECMAScriptはPOSIX時間仕様に準拠しているため、無視されます。

APIが成功した場合はnapi_okを返します。日付以外のnapi_valueが渡された場合はnapi_date_expectedを返します。

このAPIは、指定されたJavaScriptのDateの時間値のCのdoubleプリミティブを返します。

napi_get_value_bool#
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScriptのBooleanを表すnapi_value
  • [out] result: 指定されたJavaScriptのBooleanと同等のCのブールプリミティブ。

APIが成功した場合はnapi_okを返します。ブール値以外のnapi_valueが渡された場合はnapi_boolean_expectedを返します。

このAPIは、指定されたJavaScriptのBooleanと同等のCのブールプリミティブを返します。

napi_get_value_double#
napi_status napi_get_value_double(napi_env env,
                                  napi_value value,
                                  double* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の number を表す napi_value
  • [out] result: 指定された JavaScript の number に相当する C の double 型プリミティブ。

API が成功した場合は napi_ok を返します。数値以外の napi_value が渡された場合は、napi_number_expected を返します。

この API は、指定された JavaScript の number に相当する C の double 型プリミティブを返します。

napi_get_value_bigint_int64#
napi_status napi_get_value_bigint_int64(napi_env env,
                                        napi_value value,
                                        int64_t* result,
                                        bool* lossless); 
  • [in] env: API が呼び出される環境。
  • [in] value: JavaScript の BigInt を表す napi_value
  • [out] result: 指定された JavaScript の BigInt に相当する C の int64_t 型プリミティブ。
  • [out] lossless: BigInt 値が損失なく変換されたかどうかを示します。

API が成功した場合は napi_ok を返します。BigInt 以外の値が渡された場合は、napi_bigint_expected を返します。

この API は、指定された JavaScript の BigInt に相当する C の int64_t 型プリミティブを返します。必要に応じて値を切り捨て、losslessfalse に設定します。

napi_get_value_bigint_uint64#
napi_status napi_get_value_bigint_uint64(napi_env env,
                                        napi_value value,
                                        uint64_t* result,
                                        bool* lossless); 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の BigInt を表す napi_value
  • [out] result: 指定された JavaScript の BigInt に相当する C の uint64_t 型プリミティブ。
  • [out] lossless: BigInt 値が損失なく変換されたかどうかを示します。

API が成功した場合は napi_ok を返します。BigInt 以外の値が渡された場合は、napi_bigint_expected を返します。

この API は、指定された JavaScript の BigInt に相当する C の uint64_t 型プリミティブを返します。必要に応じて値を切り捨て、losslessfalse に設定します。

napi_get_value_bigint_words#
napi_status napi_get_value_bigint_words(napi_env env,
                                        napi_value value,
                                        int* sign_bit,
                                        size_t* word_count,
                                        uint64_t* words); 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の BigInt を表す napi_value
  • [out] sign_bit: JavaScript の BigInt が正か負かを示す整数。
  • [in/out] word_count: words 配列の長さに初期化する必要があります。戻り時に、この BigInt を格納するために必要な実際のワード数が設定されます。
  • [out] words: 事前に割り当てられた 64 ビットワード配列へのポインタ。

APIが成功した場合はnapi_okを返します。

この API は、単一の BigInt 値を符号ビット、64 ビットリトルエンディアン配列、および配列内の要素数に変換します。word_count のみを取得するために、sign_bitwords の両方を NULL に設定できます。

napi_get_value_external#
napi_status napi_get_value_external(napi_env env,
                                    napi_value value,
                                    void** result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の外部値を表す napi_value
  • [out] result: JavaScript の外部値によってラップされたデータへのポインタ。

API が成功した場合は napi_ok を返します。外部値以外の napi_value が渡された場合は、napi_invalid_arg を返します。

この API は、以前に napi_create_external() に渡された外部データポインタを取得します。

napi_get_value_int32#
napi_status napi_get_value_int32(napi_env env,
                                 napi_value value,
                                 int32_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の number を表す napi_value
  • [out] result: 指定された JavaScript の number に相当する C の int32 型プリミティブ。

API が成功した場合は napi_ok を返します。数値以外の napi_value が渡された場合は、napi_number_expected を返します。

この API は、指定された JavaScript の number に相当する C の int32 型プリミティブを返します。

数値が 32 ビット整数の範囲を超える場合、結果は下位 32 ビットに相当する値に切り捨てられます。値が 231 - 1 を超える場合、大きな正の数が負の数になる可能性があります。

非有限数値 (NaN, +Infinity, または -Infinity) の場合、結果は 0 に設定されます。

napi_get_value_int64#
napi_status napi_get_value_int64(napi_env env,
                                 napi_value value,
                                 int64_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の number を表す napi_value
  • [out] result: 指定された JavaScript の number に相当する C の int64 型プリミティブ。

API が成功した場合は napi_ok を返します。数値以外の napi_value が渡された場合は、napi_number_expected を返します。

この API は、指定された JavaScript の number に相当する C の int64 型プリミティブを返します。

Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) の範囲外の number 値は、精度が失われます。

非有限数値 (NaN, +Infinity, または -Infinity) の場合、結果は 0 に設定されます。

napi_get_value_string_latin1#
napi_status napi_get_value_string_latin1(napi_env env,
                                         napi_value value,
                                         char* buf,
                                         size_t bufsize,
                                         size_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の文字列を表す napi_value
  • [in] buf: ISO-8859-1 でエンコードされた文字列を書き込むためのバッファ。NULL が渡された場合、文字列の長さ (バイト単位、null 終端文字を除く) が result で返されます。
  • [in] bufsize: 宛先バッファのサイズ。この値が不十分な場合、返される文字列は切り詰められ、null で終端されます。
  • [out] result: バッファにコピーされたバイト数(null 終端文字を除く)。

API が成功した場合は napi_ok を返します。string 以外の napi_value が渡された場合は、napi_string_expected を返します。

この API は、渡された値に対応する ISO-8859-1 エンコード文字列を返します。

napi_get_value_string_utf8#
napi_status napi_get_value_string_utf8(napi_env env,
                                       napi_value value,
                                       char* buf,
                                       size_t bufsize,
                                       size_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の文字列を表す napi_value
  • [in] buf: UTF8 エンコード文字列を書き込むためのバッファ。NULL が渡された場合、文字列の長さ (バイト単位、null 終端文字を除く) が result で返されます。
  • [in] bufsize: 宛先バッファのサイズ。この値が不十分な場合、返される文字列は切り詰められ、null で終端されます。
  • [out] result: バッファにコピーされたバイト数(null 終端文字を除く)。

API が成功した場合は napi_ok を返します。string 以外の napi_value が渡された場合は、napi_string_expected を返します。

この API は、渡された値に対応する UTF8 エンコード文字列を返します。

napi_get_value_string_utf16#
napi_status napi_get_value_string_utf16(napi_env env,
                                        napi_value value,
                                        char16_t* buf,
                                        size_t bufsize,
                                        size_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の文字列を表す napi_value
  • [in] buf: UTF16-LE エンコード文字列を書き込むためのバッファ。NULL が渡された場合、文字列の長さ (2 バイトコード単位、null 終端文字を除く) が返されます。
  • [in] bufsize: 宛先バッファのサイズ。この値が不十分な場合、返される文字列は切り詰められ、null で終端されます。
  • [out] result: バッファにコピーされた 2 バイトコード単位の数 (null 終端文字を除く)。

API が成功した場合は napi_ok を返します。string 以外の napi_value が渡された場合は、napi_string_expected を返します。

この API は、渡された値に対応する UTF16 エンコード文字列を返します。

napi_get_value_uint32#
napi_status napi_get_value_uint32(napi_env env,
                                  napi_value value,
                                  uint32_t* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: JavaScript の number を表す napi_value
  • [out] result: 指定された napi_value に相当する C プリミティブ (uint32_t 型)。

API が成功した場合は napi_ok を返します。数値以外の napi_value が渡された場合は、napi_number_expected を返します。

この API は、指定された napi_value に相当する C プリミティブ (uint32_t 型) を返します。

グローバルインスタンスを取得する関数#

napi_get_boolean#
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 取得するブール値。
  • [out] result: 取得する JavaScript の Boolean シングルトンを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、指定されたブール値を表すために使用される JavaScript シングルトンオブジェクトを返すために使用されます。

napi_get_global#
napi_status napi_get_global(napi_env env, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [out] result: JavaScript の global オブジェクトを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、global オブジェクトを返します。

napi_get_null#
napi_status napi_get_null(napi_env env, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [out] result: JavaScript の null オブジェクトを表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、null オブジェクトを返します。

napi_get_undefined#
napi_status napi_get_undefined(napi_env env, napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [out] result: JavaScript の Undefined 値を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、Undefined オブジェクトを返します。

JavaScript 値と抽象的な操作の扱い#

Node-API は、JavaScript 値に対していくつかの抽象的な操作を実行するための API セットを公開します。これらの操作の一部は、ECMAScript 言語仕様第 7 章 で文書化されています。

これらの API は、次のいずれかの実行をサポートします。

  1. JavaScript の値を特定の JavaScript 型 (numberstring など) に強制変換します。
  2. JavaScript 値の型を確認します。
  3. 2 つの JavaScript 値の等価性を確認します。

napi_coerce_to_bool#

napi_status napi_coerce_to_bool(napi_env env,
                                napi_value value,
                                napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 強制変換する JavaScript 値。
  • [out] result: 強制変換された JavaScript の Boolean を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 7.1.2 章 で定義されている抽象的な操作 ToBoolean() を実装します。

napi_coerce_to_number#

napi_status napi_coerce_to_number(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 強制変換する JavaScript 値。
  • [out] result: 強制変換された JavaScript の number を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 7.1.3 章 で定義されている抽象的な操作 ToNumber() を実装します。この関数は、渡された値がオブジェクトの場合、JS コードを実行する可能性があります。

napi_coerce_to_object#

napi_status napi_coerce_to_object(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 強制変換する JavaScript 値。
  • [out] result: 強制変換された JavaScript の Object を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 7.1.13 章 で定義されている抽象的な操作 ToObject() を実装します。

napi_coerce_to_string#

napi_status napi_coerce_to_string(napi_env env,
                                  napi_value value,
                                  napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 強制変換する JavaScript 値。
  • [out] result: 強制変換された JavaScript の string を表す napi_value

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 7.1.13 章 で定義されている抽象的な操作 ToString() を実装します。この関数は、渡された値がオブジェクトの場合、JS コードを実行する可能性があります。

napi_typeof#

napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: 型を照会する JavaScript 値。
  • [out] result: JavaScript 値の型。

APIが成功した場合はnapi_okを返します。

  • value の型が既知の ECMAScript 型ではなく、value が外部値でもない場合は、napi_invalid_arg が返されます。

この API は、ECMAScript 言語仕様の 第 12.5.5 章 で定義されているオブジェクトに対して typeof 演算子を呼び出すのと同様の動作を表します。ただし、いくつかの違いがあります。

  1. 外部値の検出をサポートしています。
  2. null を別の型として検出しますが、ECMAScript の typeofobject を検出します。

value に無効な型がある場合、エラーが返されます。

napi_instanceof#

napi_status napi_instanceof(napi_env env,
                            napi_value object,
                            napi_value constructor,
                            bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] object: チェックする JavaScript 値。
  • [in] constructor: チェック対象のコンストラクタ関数の JavaScript 関数オブジェクト。
  • [out] result: object instanceof constructor が true の場合に true に設定されるブール値。

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 12.10.4 章 で定義されているオブジェクトに対して instanceof 演算子を呼び出すのを表します。

napi_is_array#

napi_status napi_is_array(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたオブジェクトが配列であるかどうか。

APIが成功した場合はnapi_okを返します。

この API は、ECMAScript 言語仕様の 第 7.2.2 章 で定義されているオブジェクトに対して IsArray 操作を呼び出すのを表します。

napi_is_arraybuffer#

napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたオブジェクトがArrayBufferであるかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectが配列バッファであるかどうかをチェックします。

napi_is_buffer#

napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたnapi_valuenode::BufferまたはUint8Arrayオブジェクトを表すかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectがバッファまたはUint8Arrayであるかどうかをチェックします。値がUint8Arrayであるかどうかをチェックする必要がある場合は、napi_is_typedarrayを優先する必要があります。

napi_is_date#

napi_status napi_is_date(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたnapi_valueがJavaScriptのDateオブジェクトを表すかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectが日付であるかどうかをチェックします。

napi_is_error#

napi_status napi_is_error(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたnapi_valueErrorオブジェクトを表すかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectErrorであるかどうかをチェックします。

napi_is_typedarray#

napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたnapi_valueTypedArrayを表すかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectが型付き配列であるかどうかをチェックします。

napi_is_dataview#

napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] value: チェックする JavaScript 値。
  • [out] result: 指定されたnapi_valueDataViewを表すかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectDataViewであるかどうかをチェックします。

napi_strict_equals#

napi_status napi_strict_equals(napi_env env,
                               napi_value lhs,
                               napi_value rhs,
                               bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] lhs: チェックするJavaScriptの値。
  • [in] rhs: チェック対象のJavaScriptの値。
  • [out] result: 2つのnapi_valueオブジェクトが等しいかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、ECMAScript言語仕様のセクション7.2.14で定義されている厳密等価性アルゴリズムの呼び出しを表します。

napi_detach_arraybuffer#

napi_status napi_detach_arraybuffer(napi_env env,
                                    napi_value arraybuffer) 
  • [in] env: APIが呼び出される環境。
  • [in] arraybuffer: デタッチされるJavaScriptのArrayBuffer

APIが成功した場合はnapi_okを返します。デタッチ不可能なArrayBufferが渡された場合は、napi_detachable_arraybuffer_expectedを返します。

一般的に、ArrayBufferは以前にデタッチされている場合はデタッチ不可能です。エンジンは、ArrayBufferがデタッチ可能かどうかについて追加の条件を課す場合があります。たとえば、V8では、ArrayBufferが外部であること、つまりnapi_create_external_arraybufferで作成されている必要があります。

このAPIは、ECMAScript言語仕様のセクション24.1.1.3で定義されているArrayBufferのデタッチ操作の呼び出しを表します。

napi_is_detached_arraybuffer#

napi_status napi_is_detached_arraybuffer(napi_env env,
                                         napi_value arraybuffer,
                                         bool* result) 
  • [in] env: APIが呼び出される環境。
  • [in] arraybuffer: チェックするJavaScriptのArrayBuffer
  • [out] result: arraybufferがデタッチされているかどうか。

APIが成功した場合はnapi_okを返します。

内部データがnullの場合、ArrayBufferはデタッチされていると見なされます。

このAPIは、ECMAScript言語仕様のセクション24.1.1.2で定義されているArrayBufferIsDetachedBuffer操作の呼び出しを表します。

JavaScriptプロパティの操作#

Node-APIは、JavaScriptオブジェクトのプロパティを取得および設定するための一連のAPIを公開しています。これらの型のいくつかは、セクション7ECMAScript言語仕様に記載されています。

JavaScriptのプロパティは、キーと値のタプルとして表されます。基本的に、Node-APIのすべてのプロパティキーは、次のいずれかの形式で表すことができます。

  • 名前付き: 単純なUTF8エンコード文字列
  • 整数インデックス: uint32_tで表されるインデックス値
  • JavaScriptの値: これらはNode-APIではnapi_valueで表されます。これは、stringnumber、またはsymbolを表すnapi_valueである可能性があります。

Node-APIの値は、型napi_valueで表されます。JavaScriptの値を必要とするNode-API呼び出しは、napi_valueを受け取ります。ただし、問題のnapi_valueがAPIで想定されているJavaScriptの型であることを確認するのは、呼び出し側の責任です。

このセクションで説明するAPIは、napi_valueで表される任意のJavaScriptオブジェクトのプロパティを取得および設定するための簡単なインターフェースを提供します。

たとえば、次のJavaScriptコードスニペットを考えてみましょう

const obj = {};
obj.myProp = 123; 

同様のことは、次のスニペットを使用してNode-APIの値を使用して行うことができます

napi_status status = napi_generic_failure;

// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;

// Create a napi_value for 123
status = napi_create_int32(env, 123, &value);
if (status != napi_ok) return status;

// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status; 

インデックス付きプロパティも同様の方法で設定できます。次のJavaScriptスニペットを考えてみましょう

const arr = [];
arr[123] = 'hello'; 

同様のことは、次のスニペットを使用してNode-APIの値を使用して行うことができます

napi_status status = napi_generic_failure;

// const arr = [];
napi_value arr, value;
status = napi_create_array(env, &arr);
if (status != napi_ok) return status;

// Create a napi_value for 'hello'
status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &value);
if (status != napi_ok) return status;

// arr[123] = 'hello';
status = napi_set_element(env, arr, 123, value);
if (status != napi_ok) return status; 

プロパティは、このセクションで説明するAPIを使用して取得できます。次のJavaScriptスニペットを考えてみましょう

const arr = [];
const value = arr[123]; 

以下は、Node-APIの対応物のほぼ同等のものです

napi_status status = napi_generic_failure;

// const arr = []
napi_value arr, value;
status = napi_create_array(env, &arr);
if (status != napi_ok) return status;

// const value = arr[123]
status = napi_get_element(env, arr, 123, &value);
if (status != napi_ok) return status; 

最後に、パフォーマンス上の理由から、オブジェクトに複数のプロパティを定義することもできます。次のJavaScriptを考えてみましょう

const obj = {};
Object.defineProperties(obj, {
  'foo': { value: 123, writable: true, configurable: true, enumerable: true },
  'bar': { value: 456, writable: true, configurable: true, enumerable: true },
}); 

以下は、Node-APIの対応物のほぼ同等のものです

napi_status status = napi_status_generic_failure;

// const obj = {};
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;

// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_int32(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_int32(env, 456, &barValue);
if (status != napi_ok) return status;

// Set the properties
napi_property_descriptor descriptors[] = {
  { "foo", NULL, NULL, NULL, NULL, fooValue, napi_writable | napi_configurable, NULL },
  { "bar", NULL, NULL, NULL, NULL, barValue, napi_writable | napi_configurable, NULL }
}
status = napi_define_properties(env,
                                obj,
                                sizeof(descriptors) / sizeof(descriptors[0]),
                                descriptors);
if (status != napi_ok) return status; 

構造体#

napi_property_attributes#
typedef enum {
  napi_default = 0,
  napi_writable = 1 << 0,
  napi_enumerable = 1 << 1,
  napi_configurable = 1 << 2,

  // Used with napi_define_class to distinguish static properties
  // from instance properties. Ignored by napi_define_properties.
  napi_static = 1 << 10,

  // Default for class methods.
  napi_default_method = napi_writable | napi_configurable,

  // Default for object properties, like in JS obj[prop].
  napi_default_jsproperty = napi_writable |
                          napi_enumerable |
                          napi_configurable,
} napi_property_attributes; 

napi_property_attributesは、JavaScriptオブジェクトに設定されたプロパティの動作を制御するために使用されるフラグです。napi_static以外は、セクション6.1.7.1ECMAScript言語仕様にリストされている属性に対応します。これらは、次の1つ以上のビットフラグにすることができます。

  • napi_default: プロパティに明示的な属性は設定されていません。デフォルトでは、プロパティは読み取り専用で、列挙可能ではなく、構成可能ではありません。
  • napi_writable: プロパティは書き込み可能です。
  • napi_enumerable: プロパティは列挙可能です。
  • napi_configurable: プロパティは、セクション6.1.7.1ECMAScript言語仕様で定義されているように、構成可能です。
  • napi_static: プロパティは、デフォルトのインスタンスプロパティではなく、クラスの静的プロパティとして定義されます。これは、napi_define_classでのみ使用されます。napi_define_propertiesでは無視されます。
  • napi_default_method: JSクラスのメソッドと同様に、プロパティは構成可能で書き込み可能ですが、列挙可能ではありません。
  • napi_default_jsproperty: JavaScriptでの代入によって設定されたプロパティと同様に、プロパティは書き込み可能、列挙可能、および構成可能です。
napi_property_descriptor#
typedef struct {
  // One of utf8name or name should be NULL.
  const char* utf8name;
  napi_value name;

  napi_callback method;
  napi_callback getter;
  napi_callback setter;
  napi_value value;

  napi_property_attributes attributes;
  void* data;
} napi_property_descriptor; 
  • utf8name: プロパティのキーを記述するオプションの文字列(UTF8エンコード)。プロパティには、utf8nameまたはnameのいずれかを指定する必要があります。
  • name: プロパティのキーとして使用されるJavaScript文字列またはシンボルを指すオプションのnapi_value。プロパティには、utf8nameまたはnameのいずれかを指定する必要があります。
  • value: プロパティがデータプロパティの場合、プロパティの取得アクセスによって取得される値。これを渡す場合は、gettersettermethod、およびdataNULLに設定します(これらのメンバーは使用されないため)。
  • getter: プロパティの取得アクセスが実行されたときに呼び出す関数。これを渡す場合は、valuemethodNULLに設定します(これらのメンバーは使用されないため)。指定された関数は、JavaScriptコードからプロパティにアクセスした場合(またはNode-API呼び出しを使用してプロパティで取得が実行された場合)に、ランタイムによって暗黙的に呼び出されます。napi_callbackは詳細を提供します。
  • setter: プロパティの設定アクセスが実行されたときに呼び出す関数。これを渡す場合は、valuemethodNULLに設定します(これらのメンバーは使用されないため)。指定された関数は、JavaScriptコードからプロパティが設定された場合(またはNode-API呼び出しを使用してプロパティで設定が実行された場合)に、ランタイムによって暗黙的に呼び出されます。napi_callbackは詳細を提供します。
  • method: これを設定して、プロパティ記述子オブジェクトのvalueプロパティがmethodで表されるJavaScript関数になるようにします。これを渡す場合は、valuegetter、およびsetterNULLに設定します(これらのメンバーは使用されないため)。 napi_callbackは詳細を提供します。
  • attributes: 特定のプロパティに関連付けられている属性。napi_property_attributesを参照してください。
  • data: この関数が呼び出された場合、methodgetter、およびsetterに渡されるコールバックデータ。

関数#

napi_get_property_names#
napi_status napi_get_property_names(napi_env env,
                                    napi_value object,
                                    napi_value* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [out] result: オブジェクトのプロパティ名を表現するJavaScript値の配列を表すnapi_value。APIを使用して、napi_get_array_lengthおよびnapi_get_elementを使用してresultを反復処理できます。

APIが成功した場合はnapi_okを返します。

このAPIは、objectの列挙可能なプロパティの名前を文字列の配列として返します。キーがシンボルであるobjectのプロパティは含まれません。

napi_get_all_property_names#
napi_get_all_property_names(napi_env env,
                            napi_value object,
                            napi_key_collection_mode key_mode,
                            napi_key_filter key_filter,
                            napi_key_conversion key_conversion,
                            napi_value* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [in] key_mode: プロトタイププロパティも取得するかどうか。
  • [in] key_filter: 取得するプロパティ(列挙可能/読み取り可能/書き込み可能)。
  • [in] key_conversion: 番号付きプロパティキーを文字列に変換するかどうか。
  • [out] result: オブジェクトのプロパティ名を表現するJavaScript値の配列を表すnapi_valuenapi_get_array_lengthおよびnapi_get_elementを使用してresultを反復処理できます。

APIが成功した場合はnapi_okを返します。

このAPIは、このオブジェクトの使用可能なプロパティの名前を含む配列を返します。

napi_set_property#
napi_status napi_set_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              napi_value value); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを設定するオブジェクト。
  • [in] key: 設定するプロパティの名前。
  • [in] value: プロパティの値。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectにプロパティを設定します。

napi_get_property#
napi_status napi_get_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              napi_value* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [in] key: 取得するプロパティの名前。
  • [out] result: プロパティの値。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectから要求されたプロパティを取得します。

napi_has_property#
napi_status napi_has_property(napi_env env,
                              napi_value object,
                              napi_value key,
                              bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] key: 存在を確認するプロパティの名前。
  • [out] result: プロパティがオブジェクトに存在するかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectに指定された名前のプロパティがあるかどうかをチェックします。

napi_delete_property#
napi_status napi_delete_property(napi_env env,
                                 napi_value object,
                                 napi_value key,
                                 bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] key: 削除するプロパティの名前。
  • [out] result: プロパティの削除が成功したかどうか。resultは、NULLを渡すことでオプションで無視できます。

APIが成功した場合はnapi_okを返します。

このAPIは、objectからkey自身のプロパティを削除しようとします。

napi_has_own_property#
napi_status napi_has_own_property(napi_env env,
                                  napi_value object,
                                  napi_value key,
                                  bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] key: チェックする自身のプロパティの名前。
  • [out] result: オブジェクトに自身のプロパティが存在するかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectが指定された名前の自身のプロパティを持っているかどうかをチェックします。keystringまたはsymbolでなければならず、そうでなければエラーがスローされます。Node-APIはデータ型間の変換を行いません。

napi_set_named_property#
napi_status napi_set_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    napi_value value); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを設定するオブジェクト。
  • [in] utf8Name: 設定するプロパティの名前。
  • [in] value: プロパティの値。

APIが成功した場合はnapi_okを返します。

このメソッドは、utf8Nameとして渡された文字列から作成されたnapi_valuenapi_set_propertyを呼び出すことと同等です。

napi_get_named_property#
napi_status napi_get_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    napi_value* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [in] utf8Name: 取得するプロパティの名前。
  • [out] result: プロパティの値。

APIが成功した場合はnapi_okを返します。

このメソッドは、utf8Nameとして渡された文字列から作成されたnapi_valuenapi_get_propertyを呼び出すことと同等です。

napi_has_named_property#
napi_status napi_has_named_property(napi_env env,
                                    napi_value object,
                                    const char* utf8Name,
                                    bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] utf8Name: 存在を確認するプロパティの名前。
  • [out] result: プロパティがオブジェクトに存在するかどうか。

APIが成功した場合はnapi_okを返します。

このメソッドは、utf8Nameとして渡された文字列から作成されたnapi_valuenapi_has_propertyを呼び出すことと同等です。

napi_set_element#
napi_status napi_set_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             napi_value value); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを設定するオブジェクト。
  • [in] index: 設定するプロパティのインデックス。
  • [in] value: プロパティの値。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectの要素を設定します。

napi_get_element#
napi_status napi_get_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             napi_value* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [in] index: 取得するプロパティのインデックス。
  • [out] result: プロパティの値。

APIが成功した場合はnapi_okを返します。

このAPIは、要求されたインデックスの要素を取得します。

napi_has_element#
napi_status napi_has_element(napi_env env,
                             napi_value object,
                             uint32_t index,
                             bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] index: 存在を確認するプロパティのインデックス。
  • [out] result: プロパティがオブジェクトに存在するかどうか。

APIが成功した場合はnapi_okを返します。

このAPIは、渡されたObjectが要求されたインデックスに要素を持っているかどうかを返します。

napi_delete_element#
napi_status napi_delete_element(napi_env env,
                                napi_value object,
                                uint32_t index,
                                bool* result); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: クエリを実行するオブジェクト。
  • [in] index: 削除するプロパティのインデックス。
  • [out] result: 要素の削除が成功したかどうか。resultは、NULLを渡すことでオプションで無視できます。

APIが成功した場合はnapi_okを返します。

このAPIは、objectから指定されたindexを削除しようとします。

napi_define_properties#
napi_status napi_define_properties(napi_env env,
                                   napi_value object,
                                   size_t property_count,
                                   const napi_property_descriptor* properties); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: プロパティを取得するオブジェクト。
  • [in] property_count: properties配列内の要素数。
  • [in] properties: プロパティ記述子の配列。

APIが成功した場合はnapi_okを返します。

このメソッドは、指定されたオブジェクトに複数のプロパティを効率的に定義できるようにします。プロパティはプロパティ記述子(napi_property_descriptorを参照)を使用して定義されます。このようなプロパティ記述子の配列が与えられた場合、このAPIは、DefineOwnProperty()(ECMA-262仕様のセクション9.1.6で説明)で定義されているように、一度に1つずつオブジェクトにプロパティを設定します。

napi_object_freeze#
napi_status napi_object_freeze(napi_env env,
                               napi_value object); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: フリーズするオブジェクト。

APIが成功した場合はnapi_okを返します。

このメソッドは、与えられたオブジェクトをフリーズします。これにより、新しいプロパティが追加されるのを防ぎ、既存のプロパティが削除されるのを防ぎ、既存のプロパティの列挙可能性、構成可能性、または書き込み可能性を変更するのを防ぎ、既存のプロパティの値が変更されるのを防ぎます。また、オブジェクトのプロトタイプが変更されるのも防ぎます。これは、ECMA-262仕様のセクション19.1.2.6で説明されています。

napi_object_seal#
napi_status napi_object_seal(napi_env env,
                             napi_value object); 
  • [in] env: Node-API呼び出しが実行される環境。
  • [in] object: シールするオブジェクト。

APIが成功した場合はnapi_okを返します。

このメソッドは、与えられたオブジェクトをシールします。これにより、新しいプロパティが追加されるのを防ぎ、既存のすべてのプロパティを構成不可としてマークします。これは、ECMA-262仕様のセクション19.1.2.20で説明されています。

JavaScript関数を操作する#

Node-APIは、JavaScriptコードがネイティブコードにコールバックできるようにするAPIのセットを提供します。ネイティブコードへのコールバックをサポートするNode-APIは、napi_callback型で表されるコールバック関数を受け入れます。JavaScript VMがネイティブコードにコールバックすると、提供されたnapi_callback関数が呼び出されます。このセクションで説明するAPIを使用すると、コールバック関数は次のことができます。

  • コールバックが呼び出されたコンテキストに関する情報を取得します。
  • コールバックに渡された引数を取得します。
  • コールバックからnapi_valueを返します。

さらに、Node-APIは、ネイティブコードからJavaScript関数を呼び出すことができる一連の関数を提供します。関数を通常のJavaScript関数呼び出しのように呼び出すことも、コンストラクター関数として呼び出すこともできます。

napi_property_descriptor項目のdataフィールドを介してこのAPIに渡される非NULLデータは、objectに関連付けることができ、objectとデータをnapi_add_finalizerに渡すことによって、objectがガベージコレクションされるたびに解放できます。

napi_call_function#

NAPI_EXTERN napi_status napi_call_function(napi_env env,
                                           napi_value recv,
                                           napi_value func,
                                           size_t argc,
                                           const napi_value* argv,
                                           napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] recv: 呼び出される関数に渡されるthis値。
  • [in] func: 呼び出すJavaScript関数を表すnapi_value
  • [in] argc: argv配列内の要素数。
  • [in] argv: 関数への引数として渡されるJavaScript値を表すnapi_valueの配列。
  • [out] result: 返されたJavaScriptオブジェクトを表すnapi_value

APIが成功した場合はnapi_okを返します。

このメソッドを使用すると、JavaScript関数オブジェクトをネイティブアドオンから呼び出すことができます。これは、アドオンのネイティブコードからJavaScriptにコールバックする主要なメカニズムです。非同期操作後にJavaScriptを呼び出す特殊なケースについては、napi_make_callbackを参照してください。

サンプル使用例は次のようになります。次のJavaScriptスニペットを考えてみましょう。

function AddTwo(num) {
  return num + 2;
}
global.AddTwo = AddTwo; 

次に、上記関数は、次のコードを使用してネイティブアドオンから呼び出すことができます。

// Get the function named "AddTwo" on the global object
napi_value global, add_two, arg;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;

status = napi_get_named_property(env, global, "AddTwo", &add_two);
if (status != napi_ok) return;

// const arg = 1337
status = napi_create_int32(env, 1337, &arg);
if (status != napi_ok) return;

napi_value* argv = &arg;
size_t argc = 1;

// AddTwo(arg);
napi_value return_val;
status = napi_call_function(env, global, add_two, argc, argv, &return_val);
if (status != napi_ok) return;

// Convert the result back to a native type
int32_t result;
status = napi_get_value_int32(env, return_val, &result);
if (status != napi_ok) return; 

napi_create_function#

napi_status napi_create_function(napi_env env,
                                 const char* utf8name,
                                 size_t length,
                                 napi_callback cb,
                                 void* data,
                                 napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] utf8Name: UTF8としてエンコードされた関数のオプションの名前。これは、新しい関数オブジェクトのnameプロパティとしてJavaScript内で表示されます。
  • [in] length: バイト単位のutf8nameの長さ。null終端の場合はNAPI_AUTO_LENGTH
  • [in] cb: この関数オブジェクトが呼び出されたときに呼び出す必要があるネイティブ関数。napi_callbackは詳細を提供します。
  • [in] data: ユーザー提供のデータコンテキスト。これは、後で呼び出されたときに関数に渡されます。
  • [out] result: 新しく作成された関数のJavaScript関数オブジェクトを表すnapi_value

APIが成功した場合はnapi_okを返します。

このAPIを使用すると、アドオン作成者はネイティブコードで関数オブジェクトを作成できます。これは、JavaScriptからアドオンのネイティブコードに呼び出すための主要なメカニズムです。

新しく作成された関数は、この呼び出し後、スクリプトから自動的に表示されるわけではありません。代わりに、スクリプトから関数にアクセスできるようにするために、JavaScriptに表示される任意のオブジェクトにプロパティを明示的に設定する必要があります。

アドオンのモジュールエクスポートの一部として関数を公開するには、エクスポートオブジェクトに新しく作成された関数を設定します。サンプルモジュールは次のようになります。

napi_value SayHello(napi_env env, napi_callback_info info) {
  printf("Hello\n");
  return NULL;
}

napi_value Init(napi_env env, napi_value exports) {
  napi_status status;

  napi_value fn;
  status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
  if (status != napi_ok) return NULL;

  status = napi_set_named_property(env, exports, "sayHello", fn);
  if (status != napi_ok) return NULL;

  return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 

上記のコードが与えられた場合、アドオンはJavaScriptから次のように使用できます。

const myaddon = require('./addon');
myaddon.sayHello(); 

require()に渡される文字列は、.nodeファイルの作成を担当するbinding.gyp内のターゲットの名前です。

dataパラメーターを介してこのAPIに渡される非NULLデータは、結果のJavaScript関数(resultパラメーターで返されます)に関連付けることができ、JavaScript関数とデータをnapi_add_finalizerに渡すことによって、関数がガベージコレクションされるたびに解放できます。

JavaScriptのFunctionについては、ECMAScript言語仕様のセクション19.2で説明されています。

napi_get_cb_info#

napi_status napi_get_cb_info(napi_env env,
                             napi_callback_info cbinfo,
                             size_t* argc,
                             napi_value* argv,
                             napi_value* thisArg,
                             void** data) 
  • [in] env: APIが呼び出される環境。
  • [in] cbinfo: コールバック関数に渡されたコールバック情報。
  • [in-out] argc: 提供されたargv配列の長さを指定し、実際の引数の数を取得します。argcは、NULLを渡すことでオプションで無視できます。
  • [out] argv: 引数がコピーされるnapi_valueのC配列。提供された数よりも多くの引数がある場合は、要求された数の引数のみがコピーされます。主張された数よりも少ない引数が提供された場合、残りのargvundefinedを表すnapi_value値で埋められます。argvは、NULLを渡すことでオプションで無視できます。
  • [out] thisArg: 呼び出しのJavaScript this引数を受け取ります。thisArgは、NULLを渡すことでオプションで無視できます。
  • [out] data: コールバックのデータポインターを受け取ります。dataは、NULLを渡すことでオプションで無視できます。

APIが成功した場合はnapi_okを返します。

このメソッドは、指定されたコールバック情報から引数やthisポインターのような呼び出しに関する詳細を取得するために、コールバック関数内で使用されます。

napi_get_new_target#

napi_status napi_get_new_target(napi_env env,
                                napi_callback_info cbinfo,
                                napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] cbinfo: コールバック関数に渡されたコールバック情報。
  • [out] result: コンストラクター呼び出しのnew.target

APIが成功した場合はnapi_okを返します。

このAPIは、コンストラクター呼び出しのnew.targetを返します。現在のコールバックがコンストラクター呼び出しではない場合、結果はNULLです。

napi_new_instance#

napi_status napi_new_instance(napi_env env,
                              napi_value cons,
                              size_t argc,
                              napi_value* argv,
                              napi_value* result) 
  • [in] env: APIが呼び出される環境。
  • [in] cons: コンストラクターとして呼び出される JavaScript 関数を表すnapi_value
  • [in] argc: argv配列内の要素数。
  • [in] argv: コンストラクターへの引数を表す napi_value としての JavaScript 値の配列。argc がゼロの場合、このパラメーターは NULL を渡すことで省略できます。
  • [out] result: 返される JavaScript オブジェクトを表す napi_value。この場合は構築されたオブジェクトです。

このメソッドは、オブジェクトのコンストラクターを表す指定された napi_value を使用して、新しい JavaScript 値をインスタンス化するために使用されます。たとえば、次のスニペットを考えてみてください。

function MyObject(param) {
  this.param = param;
}

const arg = 'hello';
const value = new MyObject(arg); 

次を Node-API で近似することができます。

// Get the constructor function MyObject
napi_value global, constructor, arg, value;
napi_status status = napi_get_global(env, &global);
if (status != napi_ok) return;

status = napi_get_named_property(env, global, "MyObject", &constructor);
if (status != napi_ok) return;

// const arg = "hello"
status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &arg);
if (status != napi_ok) return;

napi_value* argv = &arg;
size_t argc = 1;

// const value = new MyObject(arg)
status = napi_new_instance(env, constructor, argc, argv, &value); 

APIが成功した場合はnapi_okを返します。

オブジェクトのラップ#

Node-API は、C++ クラスとインスタンスを「ラップ」し、クラスのコンストラクターとメソッドを JavaScript から呼び出せるようにする方法を提供します。

  1. napi_define_class API は、C++ クラスに対応するコンストラクター、静的プロパティとメソッド、インスタンスプロパティとメソッドを持つ JavaScript クラスを定義します。
  2. JavaScript コードがコンストラクターを呼び出すと、コンストラクターのコールバックは napi_wrap を使用して、新しい C++ インスタンスを JavaScript オブジェクトでラップし、ラッパーオブジェクトを返します。
  3. JavaScript コードがクラスのメソッドまたはプロパティアクセサーを呼び出すと、対応する napi_callback C++ 関数が呼び出されます。インスタンスコールバックの場合、napi_unwrap は、呼び出しのターゲットである C++ インスタンスを取得します。

ラップされたオブジェクトの場合、クラスプロトタイプで呼び出された関数と、クラスのインスタンスで呼び出された関数を区別することが難しい場合があります。この問題に対処するために使用される一般的なパターンは、後で instanceof チェックを行うためにクラスコンストラクターへの永続的な参照を保存することです。

napi_value MyClass_constructor = NULL;
status = napi_get_reference_value(env, MyClass::es_constructor, &MyClass_constructor);
assert(napi_ok == status);
bool is_instance = false;
status = napi_instanceof(env, es_this, MyClass_constructor, &is_instance);
assert(napi_ok == status);
if (is_instance) {
  // napi_unwrap() ...
} else {
  // otherwise...
} 

参照は、不要になったら解放する必要があります。

JavaScript オブジェクトが特定のネイティブ型のラッパーであることを確認するために napi_instanceof() では不十分な場合があります。これは、ラップされた JavaScript オブジェクトがプロトタイプメソッドの this 値としてではなく、静的メソッドを介してアドオンに渡される場合に特に当てはまります。このような場合、それらが誤ってアンラップされる可能性があります。

const myAddon = require('./build/Release/my_addon.node');

// `openDatabase()` returns a JavaScript object that wraps a native database
// handle.
const dbHandle = myAddon.openDatabase();

// `query()` returns a JavaScript object that wraps a native query handle.
const queryHandle = myAddon.query(dbHandle, 'Gimme ALL the things!');

// There is an accidental error in the line below. The first parameter to
// `myAddon.queryHasRecords()` should be the database handle (`dbHandle`), not
// the query handle (`query`), so the correct condition for the while-loop
// should be
//
// myAddon.queryHasRecords(dbHandle, queryHandle)
//
while (myAddon.queryHasRecords(queryHandle, dbHandle)) {
  // retrieve records
} 

上記の例では、myAddon.queryHasRecords() は 2 つの引数を受け入れるメソッドです。1 つ目はデータベースハンドル、2 つ目はクエリハンドルです。内部的には、最初引数をアンラップし、結果のポインターをネイティブデータベースハンドルにキャストします。次に、2 番目の引数をアンラップし、結果のポインターをクエリハンドルにキャストします。引数が間違った順序で渡された場合、キャストは機能しますが、基礎となるデータベース操作が失敗するか、無効なメモリアクセスが発生する可能性が高くなります。

最初の引数から取得したポインターが実際にデータベースハンドルへのポインターであり、同様に、2 番目の引数から取得したポインターが実際にクエリハンドルへのポインターであることを保証するために、queryHasRecords() の実装は型検証を実行する必要があります。データベースハンドルがインスタンス化された JavaScript クラスコンストラクターと、napi_ref の中でクエリハンドルがインスタンス化されたコンストラクターを保持すると、napi_instanceof() を使用して、queryHashRecords() に渡されたインスタンスが確かに正しい型であることを確認できるため、役立ちます。

残念ながら、napi_instanceof() はプロトタイプの操作から保護されません。たとえば、データベースハンドルインスタンスのプロトタイプは、クエリハンドルインスタンスのコンストラクターのプロトタイプに設定できます。この場合、データベースハンドルインスタンスはクエリハンドルインスタンスとして表示され、クエリハンドルインスタンスの napi_instanceof() テストに合格しますが、依然としてデータベースハンドルへのポインターが含まれています。

この目的のために、Node-API はタイプタグ機能を提供します。

タイプタグは、アドオンに固有の 128 ビット整数です。Node-API は、タイプタグを格納するための napi_type_tag 構造体を提供します。このような値が JavaScript オブジェクトまたは napi_value に格納された 外部 とともに napi_type_tag_object() に渡されると、JavaScript オブジェクトはタイプタグで「マーク」されます。「マーク」は JavaScript 側では見えません。JavaScript オブジェクトがネイティブバインディングに到着すると、napi_check_object_type_tag() を元のタイプタグとともに使用して、JavaScript オブジェクトが以前にタイプタグで「マーク」されていたかどうかを判断できます。これにより、napi_instanceof() が提供できるよりも忠実度の高い型チェック機能が作成されます。これは、このようなタイプタグ付けがプロトタイプの操作とアドオンのアンロード/再ロードを生き残るためです。

上記の例を続けると、次のスケルトンアドオンの実装は、napi_type_tag_object()napi_check_object_type_tag() の使用法を示しています。

// This value is the type tag for a database handle. The command
//
//   uuidgen | sed -r -e 's/-//g' -e 's/(.{16})(.*)/0x\1, 0x\2/'
//
// can be used to obtain the two values with which to initialize the structure.
static const napi_type_tag DatabaseHandleTypeTag = {
  0x1edf75a38336451d, 0xa5ed9ce2e4c00c38
};

// This value is the type tag for a query handle.
static const napi_type_tag QueryHandleTypeTag = {
  0x9c73317f9fad44a3, 0x93c3920bf3b0ad6a
};

static napi_value
openDatabase(napi_env env, napi_callback_info info) {
  napi_status status;
  napi_value result;

  // Perform the underlying action which results in a database handle.
  DatabaseHandle* dbHandle = open_database();

  // Create a new, empty JS object.
  status = napi_create_object(env, &result);
  if (status != napi_ok) return NULL;

  // Tag the object to indicate that it holds a pointer to a `DatabaseHandle`.
  status = napi_type_tag_object(env, result, &DatabaseHandleTypeTag);
  if (status != napi_ok) return NULL;

  // Store the pointer to the `DatabaseHandle` structure inside the JS object.
  status = napi_wrap(env, result, dbHandle, NULL, NULL, NULL);
  if (status != napi_ok) return NULL;

  return result;
}

// Later when we receive a JavaScript object purporting to be a database handle
// we can use `napi_check_object_type_tag()` to ensure that it is indeed such a
// handle.

static napi_value
query(napi_env env, napi_callback_info info) {
  napi_status status;
  size_t argc = 2;
  napi_value argv[2];
  bool is_db_handle;

  status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
  if (status != napi_ok) return NULL;

  // Check that the object passed as the first parameter has the previously
  // applied tag.
  status = napi_check_object_type_tag(env,
                                      argv[0],
                                      &DatabaseHandleTypeTag,
                                      &is_db_handle);
  if (status != napi_ok) return NULL;

  // Throw a `TypeError` if it doesn't.
  if (!is_db_handle) {
    // Throw a TypeError.
    return NULL;
  }
} 

napi_define_class#

napi_status napi_define_class(napi_env env,
                              const char* utf8name,
                              size_t length,
                              napi_callback constructor,
                              void* data,
                              size_t property_count,
                              const napi_property_descriptor* properties,
                              napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] utf8name: JavaScript コンストラクター関数の名前。わかりやすくするために、C++ クラスをラップするときは C++ クラス名を使用することをお勧めします。
  • [in] length: バイト単位のutf8nameの長さ。null終端の場合はNAPI_AUTO_LENGTH
  • [in] constructor: クラスのインスタンスの構築を処理するコールバック関数。C++ クラスをラップする場合、このメソッドは napi_callback シグネチャを持つ静的メンバーである必要があります。C++ クラスコンストラクターは使用できません。napi_callback に詳細が記載されています。
  • [in] data: コールバック情報の data プロパティとしてコンストラクターコールバックに渡されるオプションのデータ。
  • [in] property_count: properties 配列引数の項目の数。
  • [in] properties: クラスの静的およびインスタンスのデータプロパティ、アクセサー、およびメソッドを記述するプロパティ記述子の配列。napi_property_descriptor を参照してください。
  • [out] result: クラスのコンストラクター関数を表す napi_value

APIが成功した場合はnapi_okを返します。

以下を含む JavaScript クラスを定義します。

  • クラス名を持つ JavaScript コンストラクター関数。対応する C++ クラスをラップする場合、constructor を介して渡されるコールバックを使用して、新しい C++ クラスインスタンスをインスタンス化できます。その後、napi_wrap を使用して構築中の JavaScript オブジェクトインスタンス内に配置できます。
  • 実装が C++ クラスの対応する静的データプロパティ、アクセサー、およびメソッドを呼び出すことができるコンストラクター関数のプロパティ (napi_static 属性を持つプロパティ記述子によって定義)。
  • コンストラクター関数の prototype オブジェクトのプロパティ。C++ クラスをラップする場合、C++ クラスの非静的データプロパティ、アクセサー、およびメソッドは、napi_unwrap を使用して JavaScript オブジェクトインスタンス内に配置された C++ クラスインスタンスを取得した後、napi_static 属性のないプロパティ記述子で指定された静的関数から呼び出すことができます。

C++ クラスをラップする場合、constructor を介して渡される C++ コンストラクターコールバックは、実際のクラスコンストラクターを呼び出し、新しい C++ インスタンスを JavaScript オブジェクトでラップし、ラッパーオブジェクトを返すクラスの静的メソッドである必要があります。詳細については、napi_wrap を参照してください。

napi_define_class から返される JavaScript コンストラクター関数は、多くの場合、後でネイティブコードからクラスの新しいインスタンスを構築したり、提供された値がクラスのインスタンスであるかどうかを確認したりするために保存および使用されます。その場合、関数値がガベージコレクションされるのを防ぐために、napi_create_reference を使用して、関数値への強力な永続的参照を作成できます。これにより、参照カウントが >= 1 に維持されます。

data パラメーターを介して、または napi_property_descriptor 配列項目の data フィールドを介して、この API に渡される非 NULL データは、結果の JavaScript コンストラクター (result パラメーターで返される) に関連付けることができ、クラスがガベージコレクションされるたびに、JavaScript 関数とデータの両方を napi_add_finalizer に渡すことによって解放できます。

napi_wrap#

napi_status napi_wrap(napi_env env,
                      napi_value js_object,
                      void* native_object,
                      napi_finalize finalize_cb,
                      void* finalize_hint,
                      napi_ref* result); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: ネイティブオブジェクトのラッパーになる JavaScript オブジェクト。
  • [in] native_object: JavaScript オブジェクトでラップされるネイティブインスタンス。
  • [in] finalize_cb: JavaScript オブジェクトがガベージコレクションされたときにネイティブインスタンスを解放するために使用できるオプションのネイティブコールバック。napi_finalize に詳細が記載されています。
  • [in] finalize_hint: ファイナライズコールバックに渡されるオプションのコンテキストヒント。
  • [out] result: ラップされたオブジェクトへのオプションの参照。

APIが成功した場合はnapi_okを返します。

JavaScript オブジェクトでネイティブインスタンスをラップします。ネイティブインスタンスは、後で napi_unwrap() を使用して取得できます。

JavaScript コードが napi_define_class() を使用して定義されたクラスのコンストラクターを呼び出すと、コンストラクターの napi_callback が呼び出されます。ネイティブクラスのインスタンスを構築した後、コールバックは napi_wrap() を呼び出して、コンストラクターコールバックへの this 引数である既に作成された JavaScript オブジェクトに、新しく構築されたインスタンスをラップする必要があります。(その this オブジェクトはコンストラクター関数の prototype から作成されたため、すでにすべてのインスタンスプロパティとメソッドの定義があります。)

通常、クラスインスタンスをラップする場合、ファイナライズコールバックは、ファイナライズコールバックへの data 引数として受信されるネイティブインスタンスを単に削除する必要があります。

オプションで返される参照は、最初は弱参照です。つまり、参照カウントは 0 です。通常、この参照カウントは、インスタンスを有効なままにする必要がある非同期操作中に一時的にインクリメントされます。

注意: オプションで返される参照 (取得した場合) は、ファイナライズコールバックの呼び出しに応答してのみ napi_delete_reference を介して削除する必要があります。それよりも前に削除すると、ファイナライズコールバックが呼び出されない可能性があります。したがって、参照を取得する場合は、参照を正しく破棄できるようにするためにファイナライズコールバックも必要です。

ファイナライザーコールバックは延期される可能性があり、オブジェクトがガベージコレクションされ (弱参照が無効になり)、ファイナライザーがまだ呼び出されていないウィンドウが残ります。napi_wrap() によって返される弱参照で napi_get_reference_value() を使用する場合でも、空の結果を処理する必要があります。

オブジェクトで napi_wrap() を 2 回目に呼び出すと、エラーが返されます。別のネイティブインスタンスをオブジェクトに関連付けるには、最初に napi_remove_wrap() を使用します。

napi_unwrap#

napi_status napi_unwrap(napi_env env,
                        napi_value js_object,
                        void** result); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: ネイティブインスタンスに関連付けられたオブジェクト。
  • [out] result: ラップされたネイティブインスタンスへのポインター。

APIが成功した場合はnapi_okを返します。

napi_wrap() を使用して、JavaScript オブジェクトで以前にラップされたネイティブインスタンスを取得します。

JavaScript コードがクラスのメソッドまたはプロパティアクセサーを呼び出すと、対応する napi_callback が呼び出されます。コールバックがインスタンスメソッドまたはアクセサー用である場合、コールバックへの this 引数はラッパーオブジェクトです。呼び出しのターゲットであるラップされた C++ インスタンスは、ラッパーオブジェクトで napi_unwrap() を呼び出すことによって取得できます。

napi_remove_wrap#

napi_status napi_remove_wrap(napi_env env,
                             napi_value js_object,
                             void** result); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: ネイティブインスタンスに関連付けられたオブジェクト。
  • [out] result: ラップされたネイティブインスタンスへのポインター。

APIが成功した場合はnapi_okを返します。

napi_wrap() を使用して JavaScript オブジェクト js_object に以前ラップされていたネイティブインスタンスを取得し、ラッピングを解除します。ファイナライズコールバックがラッピングに関連付けられている場合、JavaScript オブジェクトがガベージコレクションされたときに、そのコールバックは呼び出されなくなります。

napi_type_tag_object#

napi_status napi_type_tag_object(napi_env env,
                                 napi_value js_object,
                                 const napi_type_tag* type_tag); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: マークされる JavaScript オブジェクトまたは外部オブジェクト
  • [in] type_tag: オブジェクトにマークされるタグ。

APIが成功した場合はnapi_okを返します。

type_tag ポインタの値を JavaScript オブジェクトまたは外部オブジェクトに関連付けます。napi_check_object_type_tag() を使用して、オブジェクトにアタッチされたタグをアドオンが所有するタグと比較し、オブジェクトが正しい型であることを確認できます。

オブジェクトに型タグが既に関連付けられている場合、この API は napi_invalid_arg を返します。

napi_check_object_type_tag#

napi_status napi_check_object_type_tag(napi_env env,
                                       napi_value js_object,
                                       const napi_type_tag* type_tag,
                                       bool* result); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: 型タグを調べる JavaScript オブジェクトまたは外部オブジェクト
  • [in] type_tag: オブジェクトで見つかったタグと比較するタグ。
  • [out] result: 指定された型タグがオブジェクトの型タグと一致するかどうか。オブジェクトに型タグが見つからなかった場合も false が返されます。

APIが成功した場合はnapi_okを返します。

type_tag として指定されたポインタを js_object で見つかったポインタと比較します。js_object にタグが見つからない場合、またはタグが見つかっても type_tag と一致しない場合、resultfalse に設定されます。タグが見つかり、type_tag と一致する場合は、resulttrue に設定されます。

napi_add_finalizer#

napi_status napi_add_finalizer(napi_env env,
                               napi_value js_object,
                               void* finalize_data,
                               node_api_nogc_finalize finalize_cb,
                               void* finalize_hint,
                               napi_ref* result); 
  • [in] env: APIが呼び出される環境。
  • [in] js_object: ネイティブデータがアタッチされる JavaScript オブジェクト。
  • [in] finalize_data: finalize_cb に渡されるオプションのデータ。
  • [in] finalize_cb: JavaScript オブジェクトがガベージコレクションされたときにネイティブデータを解放するために使用されるネイティブコールバック。napi_finalize で詳細が説明されています。
  • [in] finalize_hint: ファイナライズコールバックに渡されるオプションのコンテキストヒント。
  • [out] result: JavaScript オブジェクトへのオプションの参照。

APIが成功した場合はnapi_okを返します。

js_object の JavaScript オブジェクトがガベージコレクションされたときに呼び出される napi_finalize コールバックを追加します。

この API は、1 つの JavaScript オブジェクトに対して複数回呼び出すことができます。

注意: オプションで返される参照 (取得した場合) は、ファイナライズコールバックの呼び出しに応答してのみ napi_delete_reference を介して削除する必要があります。それよりも前に削除すると、ファイナライズコールバックが呼び出されない可能性があります。したがって、参照を取得する場合は、参照を正しく破棄できるようにするためにファイナライズコールバックも必要です。

node_api_post_finalizer#

安定性: 1 - 実験的

napi_status node_api_post_finalizer(node_api_nogc_env env,
                                    napi_finalize finalize_cb,
                                    void* finalize_data,
                                    void* finalize_hint); 
  • [in] env: APIが呼び出される環境。
  • [in] finalize_cb: JavaScript オブジェクトがガベージコレクションされたときにネイティブデータを解放するために使用されるネイティブコールバック。napi_finalize で詳細が説明されています。
  • [in] finalize_data: finalize_cb に渡されるオプションのデータ。
  • [in] finalize_hint: ファイナライズコールバックに渡されるオプションのコンテキストヒント。

APIが成功した場合はnapi_okを返します。

イベントループで非同期的に呼び出されるように napi_finalize コールバックをスケジュールします。

通常、ファイナライザーは GC(ガベージコレクター)がオブジェクトを収集している間に呼び出されます。その時点で、GC 状態の変更を引き起こす可能性のある Node-API を呼び出すことは無効になり、Node.js がクラッシュします。

node_api_post_finalizer は、アドオンが GC ファイナライズ以外の時点に、このような Node-API の呼び出しを延期できるようにすることで、この制限を回避するのに役立ちます。

単純な非同期操作#

アドオンモジュールは、実装の一部として libuv から非同期ヘルパーを活用する必要があることがよくあります。これにより、作業の完了前にメソッドが返せるように、非同期的に実行される作業をスケジュールできます。これにより、Node.js アプリケーション全体の実行をブロックすることを回避できます。

Node-API は、最も一般的な非同期ユースケースをカバーする、これらのサポート関数用の ABI 安定インターフェースを提供します。

Node-API は、非同期ワーカーを管理するために使用される napi_async_work 構造を定義します。インスタンスは、napi_create_async_work および napi_delete_async_work で作成/削除されます。

execute コールバックと complete コールバックは、それぞれエグゼキューターが実行の準備ができたときと、タスクが完了したときに呼び出される関数です。

execute 関数は、JavaScript の実行または JavaScript オブジェクトとの対話につながる可能性のある Node-API の呼び出しを避ける必要があります。ほとんどの場合、Node-API の呼び出しを行う必要のあるコードは、代わりに complete コールバックで行う必要があります。JavaScript を実行する可能性が高いため、execute コールバックで napi_env パラメータを使用することは避けてください。

これらの関数は、次のインターフェースを実装します。

typedef void (*napi_async_execute_callback)(napi_env env,
                                            void* data);
typedef void (*napi_async_complete_callback)(napi_env env,
                                             napi_status status,
                                             void* data); 

これらのメソッドが呼び出されると、渡される data パラメータは、アドオンが提供する void* データとなり、napi_create_async_work 呼び出しに渡されます。

作成したら、napi_queue_async_work 関数を使用して、非同期ワーカーを実行待ちにすることができます。

napi_status napi_queue_async_work(node_api_nogc_env env,
                                  napi_async_work work); 

作業が実行を開始する前にキャンセルする必要がある場合は、napi_cancel_async_work を使用できます。

napi_cancel_async_work を呼び出した後、complete コールバックは napi_cancelled のステータス値で呼び出されます。キャンセルされた場合でも、complete コールバックの呼び出し前に作業を削除しないでください。

napi_create_async_work#

napi_status napi_create_async_work(napi_env env,
                                   napi_value async_resource,
                                   napi_value async_resource_name,
                                   napi_async_execute_callback execute,
                                   napi_async_complete_callback complete,
                                   void* data,
                                   napi_async_work* result); 
  • [in] env: APIが呼び出される環境。
  • [in] async_resource: async_hooksinit フックに渡される可能性のある、非同期作業に関連付けられたオプションのオブジェクト。
  • [in] async_resource_name: async_hooks API によって公開される診断情報に提供されるリソースの種類を識別する識別子。
  • [in] execute: ロジックを非同期的に実行するために呼び出す必要のあるネイティブ関数。指定された関数はワーカープールのスレッドから呼び出され、メインイベントループスレッドと並行して実行できます。
  • [in] complete: 非同期ロジックが完了またはキャンセルされたときに呼び出されるネイティブ関数。指定された関数は、メインイベントループスレッドから呼び出されます。napi_async_complete_callback で詳細が説明されています。
  • [in] data: ユーザーが提供するデータコンテキスト。これは execute 関数と complete 関数に返されます。
  • [out] result: 新しく作成された非同期作業へのハンドルである napi_async_work*

APIが成功した場合はnapi_okを返します。

この API は、ロジックを非同期的に実行するために使用される作業オブジェクトを割り当てます。作業が不要になったら、napi_delete_async_work を使用して解放する必要があります。

async_resource_name は、null で終わる UTF-8 エンコードされた文字列である必要があります。

async_resource_name 識別子はユーザーによって提供され、実行されている非同期作業の種類を表す必要があります。モジュール名を含めるなど、名前空間を識別子に適用することもお勧めします。詳細については、async_hooks ドキュメントを参照してください。

napi_delete_async_work#

napi_status napi_delete_async_work(napi_env env,
                                   napi_async_work work); 
  • [in] env: APIが呼び出される環境。
  • [in] work: napi_create_async_work の呼び出しによって返されたハンドル。

APIが成功した場合はnapi_okを返します。

この API は、以前に割り当てられた作業オブジェクトを解放します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_queue_async_work#

napi_status napi_queue_async_work(node_api_nogc_env env,
                                  napi_async_work work); 
  • [in] env: APIが呼び出される環境。
  • [in] work: napi_create_async_work の呼び出しによって返されたハンドル。

APIが成功した場合はnapi_okを返します。

この API は、以前に割り当てられた作業を実行のためにスケジュールすることを要求します。正常に返されたら、この API を同じ napi_async_work アイテムで再度呼び出してはなりません。そうしないと、結果は未定義になります。

napi_cancel_async_work#

napi_status napi_cancel_async_work(node_api_nogc_env env,
                                   napi_async_work work); 
  • [in] env: APIが呼び出される環境。
  • [in] work: napi_create_async_work の呼び出しによって返されたハンドル。

APIが成功した場合はnapi_okを返します。

この API は、まだ開始されていない場合、キューに入った作業をキャンセルします。既に実行を開始している場合は、キャンセルできず、napi_generic_failure が返されます。成功した場合、complete コールバックは napi_cancelled のステータス値で呼び出されます。正常にキャンセルされた場合でも、complete コールバックの呼び出し前に作業を削除しないでください。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

カスタム非同期操作#

上記の単純な非同期作業 API は、すべてのシナリオに適しているとは限りません。他の非同期メカニズムを使用する場合、非同期操作がランタイムによって適切に追跡されるように、次の API が必要です。

napi_async_init#

napi_status napi_async_init(napi_env env,
                            napi_value async_resource,
                            napi_value async_resource_name,
                            napi_async_context* result) 
  • [in] env: APIが呼び出される環境。
  • [in] async_resource: async_hooksinit フックに渡される可能性があり、async_hooks.executionAsyncResource() でアクセスできる非同期作業に関連付けられたオブジェクト。
  • [in] async_resource_name: async_hooks API によって公開される診断情報に提供されるリソースの種類を識別する識別子。
  • [out] result: 初期化された非同期コンテキスト。

APIが成功した場合はnapi_okを返します。

async_hooks 関連の API が正しく動作するように、async_resource オブジェクトは napi_async_destroy まで保持する必要があります。以前のバージョンとの ABI 互換性を維持するために、napi_async_context はメモリリークの原因となることを避けるために、async_resource オブジェクトへの強い参照を維持していません。ただし、async_resourcenapi_async_destroy によって破棄される前に JavaScript エンジンによってガベージコレクションされた場合、napi_open_callback_scopenapi_make_callback のような napi_async_context 関連の API を呼び出すと、AsyncLocalStorage API を使用しているときに非同期コンテキストが失われるなどの問題が発生する可能性があります。

以前のバージョンとの ABI 互換性を維持するために、async_resourceNULL を渡してもエラーにはなりません。ただし、これは、async_hooksinit フックおよび async_hooks.executionAsyncResource() で望ましくない動作が発生するため、お勧めしません。これは、非同期コールバック間のリンクを提供するために、基盤となる async_hooks 実装によってリソースが必要になったためです。

napi_async_destroy#

napi_status napi_async_destroy(napi_env env,
                               napi_async_context async_context); 
  • [in] env: APIが呼び出される環境。
  • [in] async_context: 破棄される非同期コンテキスト。

APIが成功した場合はnapi_okを返します。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

napi_make_callback#

NAPI_EXTERN napi_status napi_make_callback(napi_env env,
                                           napi_async_context async_context,
                                           napi_value recv,
                                           napi_value func,
                                           size_t argc,
                                           const napi_value* argv,
                                           napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] async_context: コールバックを呼び出している非同期操作のコンテキスト。これは通常、napi_async_init から以前に取得した値である必要があります。以前のバージョンとの ABI 互換性を維持するために、async_contextNULL を渡してもエラーにはなりません。ただし、これは非同期フックの誤った動作を引き起こします。潜在的な問題には、AsyncLocalStorage API を使用しているときに非同期コンテキストが失われることがあります。
  • [in] recv: 呼び出される関数に渡されるthis値。
  • [in] func: 呼び出すJavaScript関数を表すnapi_value
  • [in] argc: argv配列内の要素数。
  • [in] argv: 関数への引数を表す napi_value としての JavaScript 値の配列。argc がゼロの場合、このパラメータは NULL を渡すことで省略できます。
  • [out] result: 返されたJavaScriptオブジェクトを表すnapi_value

APIが成功した場合はnapi_okを返します。

このメソッドを使うと、ネイティブアドオンからJavaScript関数オブジェクトを呼び出すことができます。このAPIは、napi_call_functionに似ています。ただし、非同期操作から戻った後(スタックに他のスクリプトがない場合)に、ネイティブコードから JavaScript コールバックするために使用されます。これは、node::MakeCallbackの非常にシンプルなラッパーです。

napi_async_complete_callback内でnapi_make_callbackを使用する必要はないことに注意してください。その状況では、コールバックの非同期コンテキストはすでに設定されているため、napi_call_functionを直接呼び出すだけで十分であり、適切です。 napi_create_async_workを使用しないカスタムの非同期動作を実装する場合、napi_make_callback関数が必要になる場合があります。

コールバック中にJavaScriptによってマイクロタスクキューにスケジュールされたprocess.nextTickやPromiseは、C/C++に戻る前に実行されます。

napi_open_callback_scope#

NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env,
                                                 napi_value resource_object,
                                                 napi_async_context context,
                                                 napi_callback_scope* result) 
  • [in] env: APIが呼び出される環境。
  • [in] resource_object: 非同期処理に関連付けられたオブジェクト。async_hooksinitフックに渡されます。このパラメータは非推奨となり、実行時には無視されます。代わりにnapi_async_initasync_resourceパラメータを使用してください。
  • [in] context: コールバックを呼び出している非同期操作のコンテキスト。これは、以前にnapi_async_initから取得した値である必要があります。
  • [out] result: 新しく作成されたスコープ。

特定のNode-API呼び出しを行う際に、コールバックに関連付けられたスコープと同等のものが必要な場合があります(例:Promiseを解決する場合)。スタックに他のスクリプトがない場合は、napi_open_callback_scope関数とnapi_close_callback_scope関数を使用して、必要なスコープを開閉できます。

napi_close_callback_scope#

NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
                                                  napi_callback_scope scope) 
  • [in] env: APIが呼び出される環境。
  • [in] scope: 閉じるスコープ。

このAPIは、保留中のJavaScript例外がある場合でも呼び出すことができます。

バージョン管理#

napi_get_node_version#

typedef struct {
  uint32_t major;
  uint32_t minor;
  uint32_t patch;
  const char* release;
} napi_node_version;

napi_status napi_get_node_version(node_api_nogc_env env,
                                  const napi_node_version** version); 
  • [in] env: APIが呼び出される環境。
  • [out] version: 実行中のNode.js自体のバージョン情報へのポインタ。

APIが成功した場合はnapi_okを返します。

この関数は、現在実行中のNode.jsのメジャー、マイナー、パッチバージョンをversion構造体に格納し、releaseフィールドにprocess.release.nameの値を格納します。

返されるバッファは静的に割り当てられており、解放する必要はありません。

napi_get_version#

napi_status napi_get_version(node_api_nogc_env env,
                             uint32_t* result); 
  • [in] env: APIが呼び出される環境。
  • [out] result: サポートされているNode-APIの最高バージョン。

APIが成功した場合はnapi_okを返します。

このAPIは、Node.jsランタイムでサポートされているNode-APIの最高バージョンを返します。 Node-APIは、Node.jsの新しいリリースでAPI関数が追加されるように計画されています。アドオンが、それをサポートするNode.jsのバージョンで実行するときは新しい関数を使用し、サポートしないNode.jsのバージョンで実行するときはフォールバック動作を提供できるようにするために、

  • napi_get_version()を呼び出して、APIが利用可能かどうかを確認します。
  • 利用可能な場合は、uv_dlsym()を使用して関数へのポインタを動的にロードします。
  • 動的にロードされたポインタを使用して関数を呼び出します。
  • 関数が利用できない場合は、関数を使用しない代替の実装を提供します。

メモリ管理#

napi_adjust_external_memory#

NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_nogc_env env,
                                                    int64_t change_in_bytes,
                                                    int64_t* result); 
  • [in] env: APIが呼び出される環境。
  • [in] change_in_bytes: JavaScriptオブジェクトによって保持される外部で割り当てられたメモリの変更量。
  • [out] result: 調整された値

APIが成功した場合はnapi_okを返します。

この関数は、JavaScriptオブジェクトによって保持される外部で割り当てられたメモリの量(つまり、ネイティブアドオンによって割り当てられた独自のメモリを指すJavaScriptオブジェクト)をV8に示します。外部で割り当てられたメモリを登録すると、通常よりも頻繁にグローバルガベージコレクションがトリガーされます。

Promise#

Node-APIは、ECMA仕様のセクション25.4で説明されているように、Promiseオブジェクトを作成するための機能を提供します。 Promiseは、オブジェクトのペアとして実装されます。 napi_create_promise()によってPromiseが作成されると、「遅延」オブジェクトが作成され、Promiseとともに返されます。遅延オブジェクトは、作成されたPromiseにバインドされ、napi_resolve_deferred()またはnapi_reject_deferred()を使用してPromiseを解決または拒否する唯一の手段です。 napi_create_promise()によって作成された遅延オブジェクトは、napi_resolve_deferred()またはnapi_reject_deferred()によって解放されます。 Promiseオブジェクトは、JavaScriptに返され、通常の方法で使用できます。

たとえば、Promiseを作成して非同期ワーカーに渡すには、次のようにします。

napi_deferred deferred;
napi_value promise;
napi_status status;

// Create the promise.
status = napi_create_promise(env, &deferred, &promise);
if (status != napi_ok) return NULL;

// Pass the deferred to a function that performs an asynchronous action.
do_something_asynchronous(deferred);

// Return the promise to JS
return promise; 

上記の関数do_something_asynchronous()は、非同期アクションを実行し、その後、遅延を解決または拒否することにより、Promiseを完了し、遅延を解放します。

napi_deferred deferred;
napi_value undefined;
napi_status status;

// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;

// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (asynchronous_action_succeeded) {
  status = napi_resolve_deferred(env, deferred, undefined);
} else {
  status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;

// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL; 

napi_create_promise#

napi_status napi_create_promise(napi_env env,
                                napi_deferred* deferred,
                                napi_value* promise); 
  • [in] env: APIが呼び出される環境。
  • [out] deferred: 後で、関連付けられたPromiseを解決または拒否するためにnapi_resolve_deferred()またはnapi_reject_deferred()に渡すことができる、新しく作成された遅延オブジェクト。
  • [out] promise: 遅延オブジェクトに関連付けられたJavaScript Promise。

APIが成功した場合はnapi_okを返します。

このAPIは、遅延オブジェクトとJavaScript Promiseを作成します。

napi_resolve_deferred#

napi_status napi_resolve_deferred(napi_env env,
                                  napi_deferred deferred,
                                  napi_value resolution); 
  • [in] env: APIが呼び出される環境。
  • [in] deferred: 解決する関連付けられたPromiseの遅延オブジェクト。
  • [in] resolution: Promiseを解決する値。

このAPIは、関連付けられている遅延オブジェクトを介してJavaScript Promiseを解決します。したがって、対応する遅延オブジェクトが利用可能なJavaScript Promiseの解決にのみ使用できます。これは事実上、Promiseがnapi_create_promise()を使用して作成されている必要があり、その呼び出しから返された遅延オブジェクトがこのAPIに渡されるために保持されている必要があることを意味します。

遅延オブジェクトは、正常に完了すると解放されます。

napi_reject_deferred#

napi_status napi_reject_deferred(napi_env env,
                                 napi_deferred deferred,
                                 napi_value rejection); 
  • [in] env: APIが呼び出される環境。
  • [in] deferred: 解決する関連付けられたPromiseの遅延オブジェクト。
  • [in] rejection: Promiseを拒否する値。

このAPIは、関連付けられている遅延オブジェクトを介してJavaScript Promiseを拒否します。したがって、対応する遅延オブジェクトが利用可能なJavaScript Promiseの拒否にのみ使用できます。これは事実上、Promiseがnapi_create_promise()を使用して作成されている必要があり、その呼び出しから返された遅延オブジェクトがこのAPIに渡されるために保持されている必要があることを意味します。

遅延オブジェクトは、正常に完了すると解放されます。

napi_is_promise#

napi_status napi_is_promise(napi_env env,
                            napi_value value,
                            bool* is_promise); 
  • [in] env: APIが呼び出される環境。
  • [in] value: 調べる値
  • [out] is_promise: promiseがネイティブPromiseオブジェクト(つまり、基盤となるエンジンによって作成されたPromiseオブジェクト)であるかどうかを示すフラグ。

スクリプト実行#

Node-APIは、基盤となるJavaScriptエンジンを使用してJavaScriptを含む文字列を実行するためのAPIを提供します。

napi_run_script#

NAPI_EXTERN napi_status napi_run_script(napi_env env,
                                        napi_value script,
                                        napi_value* result); 
  • [in] env: APIが呼び出される環境。
  • [in] script: 実行するスクリプトを含むJavaScript文字列。
  • [out] result: スクリプトの実行によって得られた値。

この関数は、次の注意事項に従ってJavaScriptコードの文字列を実行し、その結果を返します。

  • evalとは異なり、この関数では、スクリプトが現在の字句スコープにアクセスすることはできず、したがって、モジュールスコープにアクセスすることもできません。つまり、requireなどの疑似グローバルは使用できません。
  • スクリプトはグローバルスコープにアクセスできます。スクリプト内の関数とvar宣言は、globalオブジェクトに追加されます。 letconstを使用して行われた変数宣言はグローバルに表示されますが、globalオブジェクトに追加されることはありません。
  • スクリプト内のthisの値はglobalです。

libuvイベントループ#

Node-APIは、特定のnapi_envに関連付けられた現在のイベントループを取得するための関数を提供します。

napi_get_uv_event_loop#

NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_nogc_env env,
                                               struct uv_loop_s** loop); 
  • [in] env: APIが呼び出される環境。
  • [out] loop: 現在のlibuvループインスタンス。

非同期スレッドセーフ関数呼び出し#

JavaScript関数は通常、ネイティブアドオンのメインスレッドからのみ呼び出すことができます。アドオンが追加のスレッドを作成する場合、napi_envnapi_value、またはnapi_refを必要とするNode-API関数は、それらのスレッドから呼び出すことはできません。

アドオンに追加のスレッドがあり、それらのスレッドによって完了した処理に基づいてJavaScript関数を呼び出す必要がある場合、それらのスレッドはアドオンのメインスレッドと通信して、メインスレッドが代わりにJavaScript関数を呼び出すことができるようにする必要があります。スレッドセーフ関数APIは、これを行う簡単な方法を提供します。

これらのAPIは、型napi_threadsafe_functionと、この型のオブジェクトを作成、破棄、および呼び出すAPIを提供します。 napi_create_threadsafe_function()は、複数のスレッドから呼び出すことができるJavaScript関数を保持するnapi_valueへの永続的な参照を作成します。呼び出しは非同期に行われます。これは、JavaScriptコールバックが呼び出される値がキューに配置され、キュー内の各値に対して、最終的にJavaScript関数が呼び出されることを意味します。

napi_threadsafe_function の作成時に、napi_finalize コールバックを提供できます。このコールバックは、スレッドセーフ関数が破棄されようとするときにメインスレッドで呼び出されます。コンテキストと構築時に与えられたファイナライズデータを受け取り、例えば uv_thread_join() を呼び出すことによって、スレッドの終了後のクリーンアップの機会を提供します。メインループスレッドを除き、ファイナライズコールバックが完了した後、スレッドセーフ関数を使用するスレッドは存在してはなりません。

napi_create_threadsafe_function() の呼び出し時に与えられた context は、napi_get_threadsafe_function_context() を呼び出すことで、どのスレッドからでも取得できます。

スレッドセーフ関数の呼び出し#

napi_call_threadsafe_function() は、JavaScript への呼び出しを開始するために使用できます。napi_call_threadsafe_function() は、API がブロッキング動作をするかどうかを制御するパラメータを受け入れます。napi_tsfn_nonblocking に設定すると、API は非ブロッキング動作をし、キューがいっぱいでデータがキューに正常に追加できなかった場合、napi_queue_full を返します。napi_tsfn_blocking に設定すると、API はキューに空きができるまでブロックします。スレッドセーフ関数が最大キューサイズ 0 で作成された場合、napi_call_threadsafe_function() は決してブロックしません。

napi_call_threadsafe_function() は、キューがいっぱいの場合、JavaScript スレッドをデッドロックさせる可能性があるため、JavaScript スレッドから napi_tsfn_blocking を指定して呼び出すべきではありません。

JavaScript への実際の呼び出しは、call_js_cb パラメータを介して与えられたコールバックによって制御されます。call_js_cb は、napi_call_threadsafe_function() の正常な呼び出しによってキューに配置された値ごとに、メインスレッド上で一度呼び出されます。そのようなコールバックが与えられない場合、デフォルトのコールバックが使用され、結果の JavaScript 呼び出しには引数がありません。call_js_cb コールバックは、パラメータ内の napi_value として呼び出す JavaScript 関数、napi_threadsafe_function の作成時に使用された void* コンテキストポインタ、およびセカンダリスレッドのいずれかによって作成された次のデータポインタを受け取ります。コールバックは、napi_call_function() などの API を使用して JavaScript を呼び出すことができます。

コールバックは、envcall_js_cb の両方が NULL に設定されて呼び出されることもあり、これは JavaScript への呼び出しがもはや不可能であることを示していますが、解放が必要なアイテムがキューに残っている可能性があります。これは通常、スレッドセーフ関数がまだアクティブな状態で Node.js プロセスが終了するときに発生します。

Node-API はコールバックに適したコンテキストで call_js_cb を実行するため、napi_make_callback() を介して JavaScript を呼び出す必要はありません。

イベントループの各ティックで、ゼロ個以上のキューに入れられたアイテムが呼び出される可能性があります。アプリケーションは、コールバックの呼び出しが進捗し、時間が進むにつれてイベントが呼び出されること以外に、特定の動作に依存すべきではありません。

スレッドセーフ関数の参照カウント#

スレッドは、その存在中に napi_threadsafe_function オブジェクトに追加したり、そこから削除したりできます。したがって、作成時にスレッドの初期数を指定するのに加えて、napi_acquire_threadsafe_function を呼び出して、新しいスレッドがスレッドセーフ関数の使用を開始することを示すことができます。同様に、napi_release_threadsafe_function を呼び出して、既存のスレッドがスレッドセーフ関数の使用を停止することを示すことができます。

napi_threadsafe_function オブジェクトは、オブジェクトを使用するすべてのスレッドが napi_release_threadsafe_function() を呼び出したとき、または napi_call_threadsafe_function の呼び出しへの応答で napi_closing の戻りステータスを受け取ったときに破棄されます。キューは、napi_threadsafe_function が破棄される前に空にされます。napi_release_threadsafe_function() は、特定の napi_threadsafe_function に関連して行われる最後の API 呼び出しである必要があります。なぜなら、呼び出しが完了した後、napi_threadsafe_function がまだ割り当てられているという保証がないからです。同じ理由で、napi_call_threadsafe_function の呼び出しへの応答で napi_closing の戻り値を受け取った後、スレッドセーフ関数を使用しないでください。napi_threadsafe_function に関連付けられたデータは、napi_create_threadsafe_function() に渡された napi_finalize コールバックで解放できます。napi_create_threadsafe_function のパラメータ initial_thread_count は、作成時に napi_acquire_threadsafe_function を複数回呼び出すのではなく、スレッドセーフ関数の初期取得数をマークします。

napi_threadsafe_function を使用するスレッドの数がゼロに達すると、napi_acquire_threadsafe_function() を呼び出すことで、それ以上のスレッドが使用を開始することはできません。実際、napi_release_threadsafe_function() を除く、関連するすべての後続の API 呼び出しは、napi_closing のエラー値を返します。

スレッドセーフ関数は、napi_release_threadsafe_function()napi_tsfn_abort の値を指定することで「中止」できます。これにより、参照カウントがゼロに達する前でも、napi_release_threadsafe_function() を除く、スレッドセーフ関数に関連付けられたすべての後続の API が napi_closing を返すようになります。特に、napi_call_threadsafe_function()napi_closing を返し、スレッドセーフ関数への非同期呼び出しを行うことがもはや不可能であることをスレッドに通知します。これは、スレッドを終了するための基準として使用できます。napi_call_threadsafe_function() から napi_closing の戻り値を受け取った場合、スレッドはスレッドセーフ関数が割り当てられていることが保証されなくなったため、それ以上使用してはなりません。

プロセスを実行し続けるかどうかの決定#

libuv ハンドルと同様に、スレッドセーフ関数は「参照」および「参照解除」できます。「参照された」スレッドセーフ関数は、スレッドセーフ関数が破棄されるまで、作成されたスレッドのイベントループが生き続けるようにします。対照的に、「参照解除された」スレッドセーフ関数は、イベントループが終了するのを妨げません。API napi_ref_threadsafe_function および napi_unref_threadsafe_function は、この目的のために存在します。

napi_unref_threadsafe_function は、スレッドセーフ関数を破棄可能としてマークするものでもなければ、napi_ref_threadsafe_function は破棄されるのを防ぐものでもありません。

napi_create_threadsafe_function#

NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
                                napi_value func,
                                napi_value async_resource,
                                napi_value async_resource_name,
                                size_t max_queue_size,
                                size_t initial_thread_count,
                                void* thread_finalize_data,
                                napi_finalize thread_finalize_cb,
                                void* context,
                                napi_threadsafe_function_call_js call_js_cb,
                                napi_threadsafe_function* result); 
  • [in] env: APIが呼び出される環境。
  • [in] func: 別のスレッドから呼び出すオプションの JavaScript 関数。call_js_cbNULL が渡された場合は、必ず指定する必要があります。
  • [in] async_resource: async_hooksinit フックに渡される可能性のある、非同期作業に関連付けられたオプションのオブジェクト。
  • [in] async_resource_name: async_hooks API によって公開される診断情報のために提供されているリソースの種類を識別するための JavaScript 文字列。
  • [in] max_queue_size: キューの最大サイズ。制限がない場合は 0
  • [in] initial_thread_count: 取得の初期数、つまり、この関数を使用するメインスレッドを含むスレッドの初期数。
  • [in] thread_finalize_data: thread_finalize_cb に渡すオプションのデータ。
  • [in] thread_finalize_cb: napi_threadsafe_function が破棄されるときに呼び出すオプションの関数。
  • [in] context: 結果の napi_threadsafe_function にアタッチするオプションのデータ。
  • [in] call_js_cb: 別のスレッドでの呼び出しに応答して JavaScript 関数を呼び出すオプションのコールバック。このコールバックはメインスレッドで呼び出されます。指定されていない場合、JavaScript 関数はパラメータなしで、その this 値を undefined として呼び出されます。napi_threadsafe_function_call_js は、より詳細な情報を提供します。
  • [out] result: 非同期スレッドセーフ JavaScript 関数。

変更履歴

  • 実験的 (NAPI_EXPERIMENTAL が定義されている場合)

    call_js_cb でスローされたキャッチされない例外は、無視される代わりに 'uncaughtException' イベントで処理されます。

napi_get_threadsafe_function_context#

NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
                                     void** result); 
  • [in] func: コンテキストを取得するスレッドセーフ関数。
  • [out] result: コンテキストを格納する場所。

この API は、func を使用するどのスレッドからでも呼び出すことができます。

napi_call_threadsafe_function#

NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
                              void* data,
                              napi_threadsafe_function_call_mode is_blocking); 
  • [in] func: 呼び出す非同期スレッドセーフ JavaScript 関数。
  • [in] data: スレッドセーフ JavaScript 関数の作成中に提供されたコールバック call_js_cb を介して JavaScript に送信するデータ。
  • [in] is_blocking: キューがいっぱいの場合に呼び出しをブロックする必要があることを示す napi_tsfn_blocking、またはキューがいっぱいの場合に napi_queue_full のステータスですぐに戻る必要があることを示す napi_tsfn_nonblocking のいずれかの値をとることができるフラグ。

キューがいっぱいの場合、JavaScript スレッドをデッドロックさせる可能性があるため、この API は JavaScript スレッドから napi_tsfn_blocking を指定して呼び出すべきではありません。

napi_release_threadsafe_function() がどのスレッドからでも abortnapi_tsfn_abort に設定して呼び出された場合、この API は napi_closing を返します。API が napi_ok を返した場合にのみ、値がキューに追加されます。

この API は、func を使用するどのスレッドからでも呼び出すことができます。

napi_acquire_threadsafe_function#

NAPI_EXTERN napi_status
napi_acquire_threadsafe_function(napi_threadsafe_function func); 
  • [in] func: 使用を開始する非同期スレッドセーフ JavaScript 関数。

スレッドは、func を他のスレッドセーフ関数 API に渡す前に、この API を呼び出して、func を使用することを示す必要があります。これにより、他のすべてのスレッドが使用を停止したときに func が破棄されるのを防ぎます。

この API は、func の使用を開始するどのスレッドからでも呼び出すことができます。

napi_release_threadsafe_function#

NAPI_EXTERN napi_status
napi_release_threadsafe_function(napi_threadsafe_function func,
                                 napi_threadsafe_function_release_mode mode); 
  • [in] func: 参照カウントをデクリメントする非同期スレッドセーフ JavaScript 関数。
  • [in] mode: 現在のスレッドがスレッドセーフ関数へのそれ以上の呼び出しを行わないことを示す napi_tsfn_release、または現在のスレッドに加えて、他のスレッドもスレッドセーフ関数へのそれ以上の呼び出しを行うべきではないことを示す napi_tsfn_abort のいずれかの値をとることができるフラグ。napi_tsfn_abort に設定すると、napi_call_threadsafe_function() の後続の呼び出しは napi_closing を返し、それ以上の値はキューに配置されません。

スレッドは、func の使用を停止するときにこの API を呼び出す必要があります。この API を呼び出した後、func をスレッドセーフ API に渡すと、func が破棄された可能性があるため、未定義の結果になります。

この API は、func の使用を停止するどのスレッドからでも呼び出すことができます。

napi_ref_threadsafe_function#

NAPI_EXTERN napi_status
napi_ref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func); 
  • [in] env: APIが呼び出される環境。
  • [in] func: 参照するスレッドセーフ関数。

この API は、func が破棄されるまで、メインスレッドで実行されているイベントループが終了しないようにするために使用されます。uv_ref と同様に、べき等でもあります。

napi_unref_threadsafe_function は、スレッドセーフ関数を破棄可能としてマークするものでもなければ、napi_ref_threadsafe_function は破棄されるのを防ぐものでもありません。napi_acquire_threadsafe_functionnapi_release_threadsafe_function がその目的のために利用可能です。

この API はメインスレッドからのみ呼び出すことができます。

napi_unref_threadsafe_function#

NAPI_EXTERN napi_status
napi_unref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func); 
  • [in] env: APIが呼び出される環境。
  • [in] func: アンリファレンスするスレッドセーフ関数。

この API は、func が破棄される前に、メインスレッドで実行されているイベントループが終了する可能性があることを示すために使用されます。 uv_unref と同様に、冪等性もあります。

この API はメインスレッドからのみ呼び出すことができます。

その他のユーティリティ#

node_api_get_module_file_name#

NAPI_EXTERN napi_status
node_api_get_module_file_name(node_api_nogc_env env, const char** result);
 
  • [in] env: APIが呼び出される環境。
  • [out] result: アドオンがロードされた場所の絶対パスを含む URL。ローカルファイルシステム上のファイルの場合、file:// で始まります。文字列は null 終端されており、env によって所有されているため、変更または解放してはなりません。

result は、アドオンのロード中にアドオンのファイル名を確立できなかった場合、空の文字列になる可能性があります。