Node-API#

穩定性:2 - 穩定

Node-API(以前稱為 N-API)是建立原生附加元件的 API。它獨立於底層 JavaScript 執行時期(例如 V8),並作為 Node.js 本身的一部分進行維護。此 API 將在 Node.js 的各個版本中保持應用程式二進制介面(ABI)穩定。其目的是使附加元件不受底層 JavaScript 引擎變更的影響,並允許為一個主要版本編譯的模組在後續主要版本的 Node.js 上執行,而不需要重新編譯。ABI 穩定性指南提供了更深入的說明。

附加元件的建立/封裝方式與標題為C++ 附加元件的部分中概述的方法/工具相同。唯一的差別是原生程式碼所使用的 API 組合。原生程式碼使用 Node-API 中提供的函式,而不是使用 V8 或Node.js 的原生抽象 API。

Node-API 公開的 API 通常用於建立和操作 JavaScript 值。概念和操作通常會對應到 ECMA-262 語言規格中指定的構想。API 具有下列屬性

  • 所有 Node-API 呼叫都會傳回類型為 napi_status 的狀態碼。此狀態會指出 API 呼叫是否成功。
  • API 的傳回值會透過輸出參數傳遞。
  • 所有 JavaScript 值都會抽象在名為 napi_value 的不透明類型之後。
  • 如果發生錯誤狀態碼,可以使用 napi_get_last_error_info 取得其他資訊。可以在錯誤處理部分錯誤處理中找到更多資訊。

Node-API 是一個 C API,可確保不同 Node.js 版本和不同編譯器層級之間的 ABI 穩定性。C++ API 可能較易於使用。為了支援使用 C++,此專案維護一個名為 node-addon-api 的 C++ wrapper 模組。此 wrapper 提供一個可內嵌的 C++ API。使用 node-addon-api 建置的二進位檔將依賴 Node.js 匯出的 Node-API C-based 函式的符號。node-addon-api 是一種撰寫呼叫 Node-API 程式碼的更有效率的方式。舉例來說,以下的 node-addon-api 程式碼。第一段顯示 node-addon-api 程式碼,第二段顯示實際在附加元件中使用的內容。

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 穩定性優點。

在使用 node-addon-api 取代 C API 時,從 node-addon-api 的 API 文件 開始。

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> 
  • libuv API,也包含在 Node.js 中,且可透過下列方式取得

    #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 的專案,或是受到 node-gyp 限制影響的開發人員來說,CMake.js 是個不錯的選擇。build_with_cmake 是基於 CMake 的原生附加元件專案範例。

上傳預編譯二進位檔#

這裡列出的三個工具允許原生附加元件開發人員和維護人員建立二進位檔並上傳到公有或私有伺服器。這些工具通常與 CI/CD 建置系統整合,例如 Travis CIAppVeyor,以建置和上傳各種平台和架構的二進位檔。這些二進位檔可供不需要安裝 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 發行版本。對於使用 CMake.js 的 GitHub 專案來說,prebuild 是個不錯的選擇。

prebuildify#

prebuildify 是基於 node-gyp 的工具。prebuildify 的優點是,當將建置的二進位檔案上傳到 npm 時,這些檔案會與原生外掛程式綑綁在一起。二進位檔案會從 npm 下載,並在安裝原生外掛程式時立即提供給模組使用者。

用法#

若要使用 Node-API 函式,請包含位於節點開發樹中 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 和穩定 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 與其支援的最高版本之間的所有版本,並預設提供版本 8 API,除非附加元件選擇使用較高的 Node-API 版本。此方法提供了最佳化現有 Node-API 函數的彈性,同時維持 ABI 穩定性。現有的附加元件可以使用較早版本的 Node-API 繼續執行,而無需重新編譯。如果附加元件需要較新 Node-API 版本的功能,則需要變更現有程式碼並重新編譯才能使用這些新函數。

在支援 Node-API 版本 9 和更新版本的 Node.js 版本中,定義 NAPI_VERSION=X 並使用現有的附加元件初始化巨集,將在執行時使用要求的 Node-API 版本烘焙到附加元件中。如果未設定 NAPI_VERSION,則預設為 8。

此表格在較舊的串流中可能不是最新的,最新的資訊在以下最新 API 文件中:Node-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:。當使用支援 Node-API version: 中所示 Node-API 版本或更高版本的 Node.js 版本時,API 可直接使用。當使用未支援所列出的 Node-API version: 的 Node.js 版本,或未列出 Node-API version: 時,只有在 #define NAPI_EXPERIMENTAL 出現在包含 node_api.hjs_native_api.h 之前時,API 才會可用。如果 API 看起來在晚於 added in: 中所示版本的 Node.js 上不可用,那麼這很可能是明顯缺失的原因。

與從原生程式碼存取 ECMAScript 功能嚴格相關的 Node-API 可以分別在 js_native_api.hjs_native_api_types.h 中找到。在這些標頭中定義的 API 會包含在 node_api.hnode_api_types.h 中。標頭會以這種方式建構,以便在 Node.js 外部實作 Node-API。對於那些實作而言,Node.js 特定的 API 可能不適用。

附加元件中特定於 Node.js 的部分可以與將實際功能公開給 JavaScript 環境的程式碼分開,以便後者可以用於 Node-API 的多個實作。在以下範例中,addon.caddon.h 僅參照 js_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#

第 8.7 節ECMAScript 語言規範 將「代理」的概念定義為 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:在收集期間傳遞給終止回呼的選用提示。

如果 API 成功,則傳回 napi_ok

此 API 會將 data 與目前執行的 Node.js 環境關聯。稍後可以使用 napi_get_instance_data() 擷取 data。任何與目前執行的 Node.js 環境關聯的現有資料(透過先前呼叫 napi_set_instance_data() 設定)都將被覆寫。如果先前呼叫提供了 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 環境關聯的資料。如果未設定資料,呼叫會成功,且 data 會設為 NULL

基本 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_hooknapi_set_instance_data 的回呼函式傳遞。

node_api_nogc_env#

穩定性:1 - 實驗性

napi_env 變異會傳遞給同步終結函式 (node_api_nogc_finalize)。有一組 Node-API 會將類型為 node_api_nogc_env 的參數作為其第一個引數。這些 API 不會存取 JavaScript 引擎的狀態,因此可以安全地從同步終結函式呼叫。允許將類型為 napi_env 的參數傳遞給這些 API,但是禁止將類型為 node_api_nogc_env 的參數傳遞給會存取 JavaScript 引擎狀態的 API。嘗試在沒有轉換的情況下這麼做會產生編譯器警告或錯誤,當外掛程式使用會在傳遞不正確指標類型給函式時發出警告和/或錯誤的旗標編譯時。從同步終結函式呼叫此類 API 最終會導致應用程式終止。

napi_value#

這是一個不透明指標,用於表示 JavaScript 值。

napi_threadsafe_function#

這是一個不透明指標,表示一個 JavaScript 函式,可透過 napi_call_threadsafe_function() 從多個執行緒非同步呼叫。

napi_threadsafe_function_release_mode#

傳遞給 napi_release_threadsafe_function() 的值,用於指示執行緒安全函式是否要立即關閉 (napi_tsfn_abort) 或僅釋放 (napi_tsfn_release),並因此可透過 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 銷毀。關閉範圍可以指示 GC,在處理範圍生命週期中建立的所有 napi_value 不再從目前的堆疊框架中參照。

如需更多詳情,請檢閱物件生命週期管理

napi_escapable_handle_scope#

可逸出的處理範圍是一種特殊類型的處理範圍,用於將在特定處理範圍內建立的值傳回給父範圍。

napi_ref#

這是用於參照napi_value的抽象化。這允許使用者管理 JavaScript 值的生命週期,包括明確定義其最小生命週期。

如需更多詳情,請檢閱物件生命週期管理

napi_type_tag#

一個儲存為兩個未簽署 64 位元整數的 128 位元值。它用作 UUID,JavaScript 物件或外部物件可以用它來「標記」,以確保它們屬於某種類型。這比napi_instanceof更強的檢查,因為如果物件的原型已被操作,後者可能會回報假陽性。類型標記最常與napi_wrap一起使用,因為它可確保從包裝物件中擷取的指標可以安全地轉換為與先前套用至 JavaScript 物件的類型標記相應的原生類型。

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。node_api_post_finalizer 可用於排程需要存取 JavaScript 引擎狀態才能執行的 Node-API 呼叫,在目前的垃圾回收週期完成後執行。

對於 node_api_create_external_string_latin1node_api_create_external_string_utf16env 參數可以為 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#

用於非同步執行緒安全函式呼叫的函式指標。回呼函式將在主執行緒上呼叫。其目的是使用透過其中一個次要執行緒的佇列傳入的資料項目,來建構呼叫 JavaScript 所需的參數(通常透過 napi_call_function),然後呼叫 JavaScript。

透過佇列從次要執行緒傳送過來的資料會提供在 data 參數中,而要呼叫的 JavaScript 函式會提供在 js_callback 參數中。

Node-API 會在呼叫此回呼之前設定環境,因此只要透過 napi_call_function 呼叫 JavaScript 函式就足夠,而不用透過 napi_make_callback

回呼函式必須符合下列簽章

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_oknapi_pending_exception,必須呼叫 napi_is_exception_pending 來檢查是否有例外待處理。請參閱例外部分,以取得更多詳細資料。

所有可能的 napi_status 值都定義在 napi_api_types.h 中。

napi_status 回傳值提供發生錯誤的 VM 非相依表示。在某些情況下,取得更詳細的資訊會很有用,包括表示錯誤的字串以及 VM (引擎) 特定的資訊。

為了擷取此資訊,提供 napi_get_last_error_info,它會回傳 napi_extended_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 約束,且隨時可能變更。它僅供記錄目的使用。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

例外狀況#

任何 Node-API 函式呼叫都可能導致待處理的 JavaScript 例外狀況。這是任何 API 函式的狀況,即使那些可能不會導致執行 JavaScript 的函式也是如此。

如果函式傳回的 napi_statusnapi_ok,則表示沒有例外狀況待處理,且不需要其他動作。如果傳回的 napi_status 不是 napi_oknapi_pending_exception,則必須呼叫 napi_is_exception_pending 以判斷是否有例外狀況待處理,才能嘗試復原並繼續,而不是立即傳回。

在許多情況下,當呼叫 Node-API 函式且已有例外狀況待處理時,函式會立即傳回 napi_statusnapi_pending_exception。但是,並非所有函式都是如此。Node-API 允許呼叫函式的子集,以便在傳回 JavaScript 之前進行一些最小的清理。在這種情況下,napi_status 會反映函式的狀態。它不會反映先前的待處理例外狀況。為避免混淆,請在每次函式呼叫後檢查錯誤狀態。

當有例外狀況待處理時,可以使用兩種方法之一。

第一種方法是執行任何適當的清理,然後傳回,以便執行傳回 JavaScript。作為傳回 JavaScript 的一部分,例外狀況會在呼叫原生方法的 JavaScript 程式碼中拋出。在有例外狀況待處理時,大多數 Node-API 呼叫的行為未指定,許多呼叫只會傳回 napi_pending_exception,因此請盡可能少做,然後傳回 JavaScript,以便處理例外狀況。

第二種方法是嘗試處理例外狀況。在某些情況下,原生程式碼可以捕捉例外狀況、採取適當的動作,然後繼續執行。這僅建議在已知可以安全處理例外狀況的特定情況下使用。在這些情況下,可以使用 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_errornapi_is_error

如果原生程式碼需要建立 Error 物件,也可以使用下列公用函式:napi_create_errornapi_create_type_errornapi_create_range_errornode_api_create_syntax_error,其中 result 是指向新建立的 JavaScript Error 物件的 napi_value

Node.js 專案正在將錯誤碼新增至內部產生的所有錯誤中。目標是讓應用程式使用這些錯誤碼進行所有錯誤檢查。相關的錯誤訊息仍會保留,但僅供記錄和顯示,預期訊息可以變更,而無需套用 SemVer。為了支援此模型與 Node-API,在內部功能和模組特定功能(這是良好做法)中,throw_create_ 函式會採用一個選用程式碼參數,此參數為要新增至錯誤物件的程式碼字串。如果選用參數為 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] msgnapi_value,參考要作為 Error 訊息的 JavaScript string
  • [out] resultnapi_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] msgnapi_value,參考要作為 Error 訊息的 JavaScript string
  • [out] resultnapi_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] msgnapi_value,參考要作為 Error 訊息的 JavaScript string
  • [out] resultnapi_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] msgnapi_value,參考要作為 Error 訊息的 JavaScript string
  • [out] resultnapi_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

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

napi_is_exception_pending#
napi_status napi_is_exception_pending(napi_env env, bool* result); 
  • [in] env:呼叫 API 時使用的環境。
  • [out] result:如果例外狀況待處理,則設定為 true 的布林值。

如果 API 成功,則傳回 napi_ok

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

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

函式呼叫不會傳回,處理程序將會終止。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

物件生命週期管理#

執行 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 僅支援範圍的單一巢狀階層。任何時候只有一個作用中範圍,而所有新處理常式會在該範圍作用中時與該範圍關聯。範圍必須以開啟順序的相反順序關閉。此外,在原生方法中建立的所有範圍都必須在從該方法傳回前關閉。

以先前的範例來說,新增呼叫 napi_open_handle_scopenapi_close_handle_scope 會確保在迴圈執行期間最多只有一個處理常式有效

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 支援「可逃逸範圍」以支援這種情況。可逃逸範圍允許一個句柄被「提升」,以便它「逃逸」目前的範圍,而句柄的生命週期從目前的範圍變更為外部範圍的生命週期。

可用於開啟/關閉可逃逸範圍的方法為 napi_open_escapable_handle_scopenapi_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 會關閉傳入的範圍。範圍必須依據建立的相反順序關閉。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

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 會開啟一個新範圍,其中一個物件可以提升到外部範圍。

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 會關閉傳入的範圍。範圍必須依據建立的相反順序關閉。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

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 Objectnapi_value
  • [out] result:表示外部範圍中已逃逸 Object 的句柄的 napi_value

如果 API 成功,則傳回 napi_ok

此 API 會將 JavaScript 物件的控制代碼提升,使其在外部範圍的生命週期內有效。每個範圍只能呼叫一次。如果呼叫多次,會傳回錯誤。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

參照值的生命週期長於原生方法#

在某些情況下,外掛程式需要建立並參照值,其生命週期長於單一原生方法呼叫。例如,建立建構函式並在稍後於建立執行個體的請求中使用該建構函式,必須可以在許多不同的執行個體建立請求中參照建構函式物件。這無法使用先前部分中所述的,以 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_refnapi_reference_unref 修改計數。如果在參考計數為 0 時收集物件,則後續所有呼叫以取得與參考相關聯的物件 napi_get_reference_value 會傳回 NULL 作為傳回的 napi_value。嘗試呼叫物件已收集的參考的 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 刪除傳入的參考。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

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] resultnapi_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); 

註冊 fun 為一個函式,在當前 Node.js 環境結束時,使用 arg 參數執行。

可以安全地使用不同的 arg 值多次指定函式。在這種情況下,它也會被呼叫多次。不允許多次提供相同的 funarg 值,這將導致程序中止。

這些掛鉤將按相反順序呼叫,即最近新增的掛鉤將最先呼叫。

可以使用 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); 

取消註冊 fun 為一個函式,在當前 Node.js 環境結束時,使用 arg 參數執行。參數和函式值都需要完全匹配。

函式必須最初使用 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:選用控制項,用於參照非同步清理掛鉤。

註冊 hook,它是一個 napi_async_cleanup_hook 類型的函式,作為一個函式,一旦目前的 Node.js 環境結束,便會使用 remove_handlearg 參數執行。

napi_add_env_cleanup_hook 不同,允許掛鉤為非同步。

否則,行為通常與 napi_add_env_cleanup_hook 相符。

如果 remove_handle 不為 NULL,將會在其中儲存一個不透明的值,無論掛鉤是否已呼叫,都必須稍後傳遞給 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 環境可能會在盡快禁止執行 JavaScript 的情況下被中斷,例如在 worker.terminate() 的要求下。當環境遭到中斷時,JavaScript 物件、執行緒安全函式和環境執行個體資料的已註冊 napi_finalize 回呼會立即且獨立地被呼叫。

napi_finalize 回呼的呼叫會在手動註冊的清理掛勾之後排程。為了確保在環境關閉期間外掛程式最終化的正確順序,以避免在 napi_finalize 回呼中使用已釋放資源,外掛程式應使用 napi_add_env_cleanup_hooknapi_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 參數傳遞一個空物件作為便利措施。如果 Init 傳回 NULL,則傳遞為 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;
} 

若要定義類別,以便可以建立新執行個體(通常與 物件包裝 搭配使用)

// 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;
} 

envexports 參數會提供給 NAPI_MODULE_INIT 巨集的主體。

所有 Node-API 外掛程式都具有內容感知,表示它們可能會被載入多次。在宣告此類模組時,有幾個設計考量。有關 內容感知外掛程式 的文件提供更多詳細資訊。

變數 envexports 會在巨集呼叫後出現在函式主體內。

如需有關設定物件屬性的更多詳細資訊,請參閱 使用 JavaScript 屬性 一節。

如需有關一般外掛程式模組建置的更多詳細資訊,請參閱現有的 API。

使用 JavaScript 值#

Node-API 公開一組 API 來建立所有類型的 JavaScript 值。其中一些類型記載於 第 6 節ECMAScript 語言規範 中。

基本上,這些 API 用於執行下列其中一項操作

  1. 建立新的 JavaScript 物件
  2. 從原始 C 類型轉換為 Node-API 值
  3. 從 Node-API 值轉換為原始 C 類型
  4. 取得全域執行個體,包括 undefinednull

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; 

屬性篩選器位元。它們可以透過或運算來建立複合篩選器。

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 的基本二進位標量資料類型。此列舉的元素對應於 第 22.2 節ECMAScript 語言規範

物件建立函式#

napi_create_array#
napi_status napi_create_array(napi_env env, napi_value* result) 
  • [in] env:Node-API 呼叫在其中呼叫的環境。
  • [out] result:表示 JavaScript Arraynapi_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] lengthArray 的初始長度。
  • [out] result:表示 JavaScript Arraynapi_value

如果 API 成功,則傳回 napi_ok

此 API 會傳回對應於 JavaScript Array 類型的 Node-API 值。Array 的長度屬性會設定為傳入的長度參數。不過,無法保證 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] dataArrayBuffer 的底層位元組緩衝區指標。data 可以選擇忽略,方法是傳入 NULL
  • [out] result:表示 JavaScript ArrayBuffernapi_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:基礎緩衝區的原始指標。可選擇傳遞 NULL 來忽略 data
  • [out] result:表示 node::Buffernapi_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 的基礎資料緩衝區的指標。可選擇傳遞 NULL 來忽略 result_data
  • [out] result:表示 node::Buffernapi_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 Datenapi_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:在收集期間傳遞給終止回呼的選用提示。
  • [out] result:表示外部值的 napi_value

如果 API 成功,則傳回 napi_ok

此 API 會配置附有外部資料的 JavaScript 值。這用於透過 JavaScript 程式碼傳遞外部資料,因此稍後可以使用 napi_get_value_external 透過原生程式碼擷取。

此 API 會新增 napi_finalize 回呼,當剛建立的 JavaScript 物件已被垃圾回收時,會呼叫此回呼。

建立的值不是物件,因此不支援其他屬性。它被視為不同的值類型:使用外部值呼叫 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_dataArrayBuffer 的底層位元組緩衝區指標。
  • [in] byte_length:底層緩衝區的位元組長度。
  • [in] finalize_cb:收集 ArrayBuffer 時呼叫的選用回呼。 napi_finalize 提供更多詳細資訊。
  • [in] finalize_hint:在收集期間傳遞給終止回呼的選用提示。
  • [out] result:表示 JavaScript ArrayBuffernapi_value

如果 API 成功,則傳回 napi_ok

除了 Node.js 以外的其他一些執行環境已不再支援外部緩衝區。在除了 Node.js 以外的其他執行環境中,此方法可能會傳回 napi_no_external_buffers_allowed 以表示不支援外部緩衝區。其中一個執行環境是 Electron,如這個問題中所述 electron/issues/35801

為了與所有執行時期維持最廣泛的相容性,您可以在包含 node-api 標頭之前,在您的附加元件中定義 NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED。這樣做會隱藏建立外部緩衝區的 2 個函式。如果您意外使用其中一個方法,這將確保發生編譯錯誤。

此 API 會傳回一個與 JavaScript ArrayBuffer 相應的 Node-API 值。ArrayBuffer 的底層位元組緩衝區是外部配置和管理的。呼叫者必須確保位元組緩衝區保持有效,直到呼叫完成回呼為止。

此 API 會新增 napi_finalize 回呼,當剛建立的 JavaScript 物件已被垃圾回收時,會呼叫此回呼。

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:在收集期間傳遞給終止回呼的選用提示。
  • [out] result:表示 node::Buffernapi_value

如果 API 成功,則傳回 napi_ok

除了 Node.js 以外的其他一些執行環境已不再支援外部緩衝區。在除了 Node.js 以外的其他執行環境中,此方法可能會傳回 napi_no_external_buffers_allowed 以表示不支援外部緩衝區。其中一個執行環境是 Electron,如這個問題中所述 electron/issues/35801

為了與所有執行時期維持最廣泛的相容性,您可以在包含 node-api 標頭之前,在您的附加元件中定義 NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED。這樣做會隱藏建立外部緩衝區的 2 個函式。如果您意外使用其中一個方法,這將確保發生編譯錯誤。

此 API 會配置一個 node::Buffer 物件,並使用傳入緩衝區作為後盾初始化它。雖然這仍然是一個完全受支援的資料結構,但在大多數情況下,使用 TypedArray 就足夠了。

此 API 會新增 napi_finalize 回呼,當剛建立的 JavaScript 物件已被垃圾回收時,會呼叫此回呼。

對於 Node.js >=4,BuffersUint8Array

napi_create_object#
napi_status napi_create_object(napi_env env, napi_value* result) 
  • [in] env:呼叫 API 時使用的環境。
  • [out] result:表示 JavaScript Objectnapi_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:選用的 napi_value,它參照要設定為符號描述的 JavaScript string
  • [out] result:表示 JavaScript symbolnapi_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 symbolnapi_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] typeTypedArray 內元素的純量資料類型。
  • [in] lengthTypedArray 內的元素數量。
  • [in] arraybufferTypedArray 底層的 ArrayBuffer
  • [in] byte_offset:從中開始投影 TypedArrayArrayBuffer 內的位元組偏移量。
  • [out] result:表示 JavaScript TypedArraynapi_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] lengthDataView 內的元素數量。
  • [in] arraybufferDataView 底層的 ArrayBuffer
  • [in] byte_offsetArrayBuffer 中的位元組偏移量,用於開始投射 DataView
  • [out] result:表示 JavaScript DataViewnapi_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 numbernapi_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 numbernapi_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 numbernapi_value

如果 API 成功,則傳回 napi_ok

此 API 用於將 C int64_t 類型轉換為 JavaScript number 類型。

JavaScript number 類型在 ECMAScript 語言規範的 第 6.1.6 節 中有說明。請注意,int64_t 的完整範圍無法在 JavaScript 中以完全精確度表示。小於 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 numbernapi_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 BigIntnapi_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 BigIntnapi_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_countwords 陣列的長度。
  • [in] wordsuint64_t 小端序 64 位元字元的陣列。
  • [out] result:表示 JavaScript BigIntnapi_value

如果 API 成功,則傳回 napi_ok

此 API 會將陣列的未簽署 64 位元字元轉換為單一 BigInt 值。

結果的 BigInt 會計算為: (–1)sign_bit (words[0] × (264)0 + words[1] × (264)1 + …)

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 stringnapi_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:這是 str 值,以 void* 指標表示。
    • [in] finalize_hint:這是傳遞給 API 的值 finalize_hintnapi_finalize 提供更多詳細資訊。此參數是選用的。傳遞 null 值表示外掛程式不需要在對應的 JavaScript 字串被收集時收到通知。
  • [in] finalize_hint:在收集期間傳遞給終止回呼的選用提示。
  • [out] result:代表 JavaScript stringnapi_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:字串的長度(以兩個位元組的程式碼單位表示),或如果以 null 結尾,則為 NAPI_AUTO_LENGTH
  • [out] result:代表 JavaScript stringnapi_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:字串的長度(以兩個位元組的程式碼單位表示),或如果以 null 結尾,則為 NAPI_AUTO_LENGTH
  • [in] finalize_callback:字串收集時要呼叫的函式。函式會呼叫下列參數
    • [in] env:外掛程式執行的環境。如果字串收集是作為工作執行緒或主要 Node.js 執行個體終止的一部分,則此值可能是 null。
    • [in] data:這是 str 值,以 void* 指標表示。
    • [in] finalize_hint:這是傳遞給 API 的值 finalize_hintnapi_finalize 提供更多詳細資訊。此參數是選用的。傳遞 null 值表示外掛程式不需要在對應的 JavaScript 字串被收集時收到通知。
  • [in] finalize_hint:在收集期間傳遞給終止回呼的選用提示。
  • [out] result:代表 JavaScript stringnapi_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 stringnapi_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:字串的長度(以兩個位元組的程式碼單位表示),或如果以 null 結尾,則為 NAPI_AUTO_LENGTH
  • [out] result:一個 napi_value,代表最佳化的 JavaScript string,用於作為物件的屬性金鑰。

如果 API 成功,則傳回 napi_ok

此 API 從 UTF16-LE 編碼的 C 字串建立最佳化的 JavaScript string 值,以用作物件的屬性金鑰。會複製原生字串。

包括 V8 在內的許多 JavaScript 引擎使用內部化字串作為設定和取得屬性值的鍵。它們通常使用雜湊表來建立和查詢此類字串。雖然它會增加每個金鑰建立的成本,但它會在建立後透過比較字串指標(而非整個字串)來提升效能。

如果新的 JavaScript 字串打算用作屬性金鑰,那麼對某些 JavaScript 引擎而言,使用 node_api_create_property_key_utf16 函式會更有效率。否則,請使用 napi_create_string_utf16node_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 Arraynapi_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: 表示正在查詢的 ArrayBuffernapi_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::BufferUint8Arraynapi_value
  • [out] data: node::BufferUint8Array 的底層資料緩衝區。如果 length 為 0,這可能是 NULL 或任何其他指標值。
  • [out] length: 底層資料緩衝區的長度(以位元組為單位)。

如果 API 成功,則傳回 napi_ok

此方法傳回與 napi_get_typedarray_info 相同的 databyte_length。而且 napi_get_typedarray_info 也接受 node::Buffer (Uint8Array) 作為值。

此 API 用於擷取 node::Buffer 的底層資料緩衝區及其長度。

警告:使用此 API 時請小心,因為如果底層資料緩衝區是由 VM 管理的,則無法保證其生命週期。

napi_get_prototype#
napi_status napi_get_prototype(napi_env env,
                               napi_value object,
                               napi_value* result) 
  • [in] env:呼叫 API 時使用的環境。
  • [in] object: 表示要傳回其原型的 JavaScript Objectnapi_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:表示要查詢其屬性的 TypedArraynapi_value
  • [out] typeTypedArray 內元素的純量資料類型。
  • [out] lengthTypedArray 中的元素數量。
  • [out] dataTypedArray 底層的資料緩衝區,已由 byte_offset 值調整,以便指向 TypedArray 中的第一個元素。如果陣列長度為 0,則這可能是 NULL 或任何其他指標值。
  • [out] arraybufferTypedArray 底層的 ArrayBuffer
  • [out] byte_offset:陣列第一個元素位於底層原生陣列中的位元組偏移量。資料參數的值已調整,以便資料指向陣列中的第一個元素。因此,原生陣列的第一個位元組將位於 data - byte_offset

如果 API 成功,則傳回 napi_ok

此 API 會傳回型化陣列的各種屬性。

如果不需要某項屬性,任何輸出參數都可以是 NULL

警告:使用此 API 時請小心,因為底層資料緩衝區是由 VM 管理的。

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:表示要查詢其屬性的 DataViewnapi_value
  • [out] byte_lengthDataView 中的位元組數。
  • [out] dataDataView 底層的資料緩衝區。如果 byte_length 為 0,這可能是 NULL 或任何其他指標值。
  • [out] arraybufferDataView 底層的 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 Datenapi_value
  • [out] result:時間值,以 1970 年 1 月 1 日 UTC 午夜以來的毫秒數表示的 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 Booleannapi_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 numbernapi_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 BigIntnapi_value
  • [out] result:給定 JavaScript BigInt 的 C int64_t 基本等效值。
  • [out] lossless:指出 BigInt 值是否無損失轉換。

如果 API 成功,則傳回 napi_ok。如果傳入的不是 BigInt,則傳回 napi_bigint_expected

此 API 傳回給定 JavaScript BigInt 的 C int64_t 基本等效值。如果需要,它會截斷值,並將 lossless 設為 false

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 BigIntnapi_value
  • [out] result:給定 JavaScript BigInt 的 C uint64_t 基本等效值。
  • [out] lossless:指出 BigInt 值是否無損失轉換。

如果 API 成功,則傳回 napi_ok。如果傳入的不是 BigInt,則傳回 napi_bigint_expected

此 API 傳回給定 JavaScript BigInt 的 C uint64_t 基本等效值。如果需要,它會截斷值,並將 lossless 設為 false

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 BigIntnapi_value
  • [out] sign_bit:代表 JavaScript BigInt 為正數或負數的整數。
  • [in/out] word_count:必須初始化為 words 陣列的長度。傳回時,會設為儲存此 BigInt 所需的實際字數。
  • [out] words:指向預先配置的 64 位元字陣列的指標。

如果 API 成功,則傳回 napi_ok

此 API 將單一 BigInt 值轉換為符號位元、64 位元小端陣列,以及陣列中的元素數。sign_bitwords 都可以設為 NULL,以僅取得 word_count

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 numbernapi_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)會將結果設為零。

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 numbernapi_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)會將結果設為零。

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。如果傳入的 napi_value 不是 string,會傳回 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。如果傳入的 napi_value 不是 string,會傳回 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。如果傳入的 napi_value 不是 string,會傳回 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 numbernapi_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 未定義值的 napi_value

如果 API 成功,則傳回 napi_ok

此 API 會傳回未定義的物件。

使用 JavaScript 值和抽象運算#

Node-API 公開一組 API,用於對 JavaScript 值執行一些抽象運算。其中一些運算記載於 第 7 節ECMAScript 語言規範 中。

這些 API 支援執行下列其中一項操作

  1. 將 JavaScript 值強制轉換為特定 JavaScript 類型(例如 numberstring)。
  2. 檢查 JavaScript 值的類型。
  3. 檢查兩個 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 Booleannapi_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 numbernapi_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 Objectnapi_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 stringnapi_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 表示類似於在物件上呼叫 typeof 算子的行為,如 ECMAScript 語言規範第 12.5.5 節 所定義。不過,有些差異

  1. 它支援偵測外部值。
  2. 它將 null 偵測為一個獨立的類型,而 ECMAScript typeof 會偵測為 object

如果 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 表示在物件上呼叫 instanceof 算子,如 ECMAScript 語言規範第 12.10.4 節 所定義。

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 表示在物件上呼叫 IsArray 作業,如 ECMAScript 語言規範第 7.2.2 節 所定義。

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_value 是否代表 node::BufferUint8Array 物件。

如果 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_value 是否代表 Error 物件。

如果 API 成功,則傳回 napi_ok

此 API 檢查傳入的 Object 是否為 Error

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_value 是否代表 TypedArray

如果 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_value 是否代表 DataView

如果 API 成功,則傳回 napi_ok

此 API 檢查傳入的 Object 是否為 DataView

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:兩個 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] resultarraybuffer 是否已分離。

如果 API 成功,則傳回 napi_ok

如果 ArrayBuffer 的內部資料為 null,則視為已分離。

此 API 代表在 ECMAScript 語言規格 第 24.1.1.2 節 中定義的 ArrayBuffer IsDetachedBuffer 操作的呼叫。

使用 JavaScript 屬性#

Node-API 揭露一組 API 來取得和設定 JavaScript 物件中的屬性。其中一些類型記載於 第 7 節ECMAScript 語言規範 中。

JavaScript 中的屬性表示為一個由金鑰和值組成的元組。基本上,Node-API 中的所有屬性金鑰都可以表示成下列其中一種形式

  • 命名:一個簡單的 UTF8 編碼字串
  • 整數索引:一個由 uint32_t 表示的索引值
  • JavaScript 值:這些在 Node-API 中由 napi_value 表示。這可以是一個表示 字串數字符號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.1 節 中列出的屬性ECMAScript 語言規範。它們可以是下列一個或多個位元旗標

  • napi_default:屬性上沒有設定明確的屬性。預設情況下,屬性是唯讀、不可列舉且不可設定。
  • napi_writable:屬性是可寫入的。
  • napi_enumerable:屬性是可列舉的。
  • napi_configurable:屬性是可設定的,如 第 6.1.7.1 節 中定義的ECMAScript 語言規範
  • napi_static:屬性將定義為類別上的靜態屬性,而不是預設的實例屬性。這只會用於 napi_define_classnapi_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。屬性必須提供 utf8namename 之一。
  • name:指向要作為屬性金鑰使用的 JavaScript 字串或符號的選用 napi_value。屬性必須提供 utf8namename 之一。
  • value:如果屬性為資料屬性,則為透過屬性的取得存取所擷取的值。如果傳入此值,請將 gettersettermethoddata 設定為 NULL(因為這些成員將不會使用)。
  • getter:在執行屬性的取得存取時要呼叫的函式。如果傳入此值,請將 valuemethod 設定為 NULL(因為這些成員將不會使用)。當從 JavaScript 程式碼存取屬性(或使用 Node-API 呼叫對屬性執行取得)時,執行時期會隱含呼叫指定的函式。napi_callback 提供更多詳細資料。
  • setter:在執行屬性的設定存取時要呼叫的函式。如果傳入此值,請將 valuemethod 設定為 NULL(因為這些成員將不會使用)。當從 JavaScript 程式碼設定屬性(或使用 Node-API 呼叫對屬性執行設定)時,執行時期會隱含呼叫指定的函式。napi_callback 提供更多詳細資料。
  • method:設定此值可將屬性描述物件的 value 屬性設為由 method 表示的 JavaScript 函式。如果傳入此值,請將 valuegettersetter 設定為 NULL(因為這些成員將不會使用)。napi_callback 提供更多詳細資料。
  • attributes:與特定屬性關聯的屬性。請參閱 napi_property_attributes
  • data:如果呼叫此函式,則傳遞至 methodgettersetter 的回呼資料。

函式#

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。可以使用 napi_get_array_lengthnapi_get_element API 來反覆處理 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_value。可以使用 napi_get_array_lengthnapi_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 是否有指定的自有屬性。key 必須是 stringsymbol,否則會擲回錯誤。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

此方法等於呼叫 napi_set_property,並使用從傳入的字串 utf8Name 建立的 napi_value

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

此方法等於呼叫 napi_get_property,並使用從傳入的字串 utf8Name 建立的 napi_value

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

此方法等於呼叫 napi_has_property,並使用從傳入的字串 utf8Name 建立的 napi_value

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_countproperties 陣列中的元素數量。
  • [in] properties:屬性描述符陣列。

如果 API 成功,則傳回 napi_ok

此方法允許在給定的物件上有效率地定義多個屬性。屬性使用屬性描述符定義(請參閱 napi_property_descriptor)。給定此類屬性描述符陣列後,此 API 會一次設定物件上的屬性,如 DefineOwnProperty() 所定義(說明於 ECMA-262 規範的 第 9.1.6 節)。

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 提供一組 API,允許 JavaScript 程式碼呼叫回原生程式碼。支援呼叫回原生程式碼的 Node-API 會使用 napi_callback 類型表示的呼叫回函式。當 JavaScript VM 呼叫回原生程式碼時,就會呼叫所提供的 napi_callback 函式。此區段中說明的 API 允許呼叫回函式執行下列動作

  • 取得呼叫回被呼叫的內容。
  • 取得傳遞給呼叫回的引數。
  • 從呼叫回傳回 napi_value

此外,Node-API 提供一組函式,允許從原生程式碼呼叫 JavaScript 函式。可以像呼叫一般 JavaScript 函式一樣呼叫函式,或作為建構函式呼叫。

透過 napi_property_descriptor 項目的 data 欄位傳遞給此 API 的任何非 NULL 資料都可以與 object 關聯,並在 object 被垃圾回收時釋放,方法是將 object 和資料傳遞給 napi_add_finalizer

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] argcargv 陣列中元素的數量。
  • [in] argv:表示傳入函式作為引數的 JavaScript 值的 napi_values 陣列。
  • [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 的函式名稱(選用)。這在 JavaScript 中可見為新函式物件的 name 屬性。
  • [in] lengthutf8name 的長度(以位元組為單位),或如果以 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() 的字串是 binding.gyp 中負責建立 .node 檔案的目標名稱。

任何非 NULL 資料,透過 data 參數傳遞給此 API,可以與產生的 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:傳遞給 callback 函式的 callback 資訊。
  • [in-out] argc:指定提供的 argv 陣列長度,並接收實際引數計數。argc 可以選擇透過傳遞 NULL 來忽略。
  • [out] argvnapi_value 的 C 陣列,引數將複製到其中。如果引數多於提供的計數,只會複製要求的引數數量。如果提供的引數少於宣稱的數量,argv 的其餘部分會填入代表 undefinednapi_value 值。argv 可以選擇透過傳遞 NULL 來忽略。
  • [out] thisArg:接收呼叫的 JavaScript this 引數。thisArg 可以選擇透過傳遞 NULL 來忽略。
  • [out] data:接收 callback 的資料指標。data 可以選擇透過傳遞 NULL 來忽略。

如果 API 成功,則傳回 napi_ok

此方法用於 callback 函式中,以擷取呼叫的詳細資訊,例如引數和 this 指標,從給定的 callback 資訊。

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:傳遞給 callback 函式的 callback 資訊。
  • [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] argcargv 陣列中元素的數量。
  • [in] argv:表示傳遞給建構函式的引數的 JavaScript 值陣列,為 napi_value。如果 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 定義一個 JavaScript 類別,其中包含建構函式、靜態屬性和方法,以及與 C++ 類別對應的實例屬性和方法。
  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...
} 

當不再需要時,必須釋放參考。

有些時候,napi_instanceof() 不足以確保 JavaScript 物件是特定原生類型的包裝器。特別是在包裝的 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() 是一個接受兩個參數的方法。第一個是資料庫控制代碼,第二個是查詢控制代碼。在內部,它會解開包裝第一個參數,並將產生的指標轉換為原生資料庫控制代碼。然後,它會解開包裝第二個參數,並將產生的指標轉換為查詢控制代碼。如果參數傳遞順序錯誤,轉換會成功,但是基礎資料庫操作很可能會失敗,甚至會導致無效的記憶體存取。

為了確保從第一個參數擷取的指標確實是指向資料庫控制代碼的指標,以及從第二個參數擷取的指標確實是指向查詢控制代碼的指標,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] lengthutf8name 的長度(以位元組為單位),或如果以 null 終止,則為 NAPI_AUTO_LENGTH
  • [in] constructor:處理建構類別實例的 callback 函式。在封裝 C++ 類別時,此方法必須是具有 napi_callback 簽章的靜態成員。無法使用 C++ 類別建構函式。 napi_callback 提供更多詳細資料。
  • [in] data:傳遞給建構函式 callback 的選用資料,作為 callback 資訊的 data 屬性。
  • [in] property_countproperties 陣列引數中的項目數目。
  • [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_static 屬性,只要使用 napi_unwrap 擷取置入 JavaScript 物件執行個體中的 C++ 類別執行個體即可。

在封裝 C++ 類別時,透過 constructor 傳遞的 C++ 建構函式回呼函式應該是類別上的靜態方法,用於呼叫實際的類別建構函式,然後將新的 C++ 執行個體封裝在 JavaScript 物件中,並傳回封裝物件。有關詳細資訊,請參閱 napi_wrap

通常會儲存從 napi_define_class 傳回的 JavaScript 建構函式,並在稍後使用它從原生程式碼建構類別的新執行個體,和/或檢查提供的數值是否為類別的執行個體。在這種情況下,可使用 napi_create_reference 建立對其的強式持續參考,以防止函式數值被垃圾回收,確保參考計數保持 >= 1。

任何非 NULL 資料,透過 data 參數或 napi_property_descriptor 陣列項目的 data 欄位傳遞到此 API,都可以與產生的 JavaScript 建構函式關聯(在 result 參數中傳回),並在類別由 napi_add_finalizer 將 JavaScript 函式和資料傳遞後,在垃圾回收類別時釋放。

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(),將新建構的實例包裝在已建立的 JavaScript 物件中,也就是建構函式呼叫回函式的 this 參數。(該 this 物件是由建構函式函式的 prototype 建立,因此已定義所有實例屬性和方法。)

通常在包裝類別實例時,應提供完成呼叫回函式,該呼叫回函式僅刪除接收為完成呼叫回函式 data 參數的原生實例。

選用的傳回參照最初是弱參照,表示其參照計數為 0。通常,在需要實例保持有效的非同步作業期間,會暫時增加此參照計數。

注意:選用的傳回參照(如果取得)應僅在回應完成回呼呼叫時透過 napi_delete_reference 刪除。如果在此之前將其刪除,則可能永遠不會呼叫完成回呼。因此,在取得參照時,也需要完成回呼才能正確處置參照。

完成器回呼可能會遞延,留下一個物件已由垃圾回收器回收(且弱參照無效)但完成器尚未呼叫的視窗。在對 napi_wrap() 傳回的弱參照使用 napi_get_reference_value() 時,您仍應處理空結果。

第二次對物件呼叫 napi_wrap() 會傳回錯誤。若要將另一個原生實例與物件關聯,請先使用 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 參數是封裝物件;可透過在封裝物件上呼叫 napi_unwrap() 來取得呼叫目標的封裝 C++ 實例。

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 不相符,則 result 會設為 false。如果找到標籤且與 type_tag 相符,則 result 會設為 true

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

新增 napi_finalize 回呼,當 js_object 中的 JavaScript 物件已被垃圾回收時,將呼叫此回呼。

此 API 可在單一 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 允許外掛程式將對此類 Node-API 的呼叫延後到 GC 終結化之外的時間點,有助於解決此限制。

簡單的非同步作業#

外掛程式模組經常需要利用 libuv 的非同步輔助程式作為其實作的一部分。這允許他們排程工作以非同步方式執行,以便他們的方法可以在工作完成之前提前傳回。這允許他們避免阻擋 Node.js 應用程式的整體執行。

Node-API 提供這些支援函式的 ABI 穩定介面,涵蓋最常見的非同步使用案例。

Node-API 定義了 napi_async_work 結構,用於管理非同步工作。實例會使用 napi_create_async_worknapi_delete_async_work 來建立/刪除。

executecomplete 回呼是執行器準備執行和完成其任務時會呼叫的函式。

execute 函式應避免進行任何可能導致執行 JavaScript 或與 JavaScript 物件互動的 Node-API 呼叫。通常,任何需要進行 Node-API 呼叫的程式碼都應該在 complete 回呼中進行。避免在執行回呼中使用 napi_env 參數,因為它可能會執行 JavaScript。

這些函式實作下列介面

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_hooks init 勾子
  • [in] async_resource_name:提供給 async_hooks API 揭露的診斷資訊中,資源類型的識別碼。
  • [in] execute:應呼叫的原生函式,以非同步方式執行邏輯。所提供的函式會從工作人員池執行緒呼叫,並且可以與主事件迴圈執行緒平行執行。
  • [in] complete:非同步邏輯完成或取消時將呼叫的原生函式。所提供的函式會從主事件迴圈執行緒呼叫。napi_async_complete_callback 提供更多詳細資料。
  • [in] data:使用者提供的資料內容。這會傳回至 execute 和 complete 函式。
  • [out] resultnapi_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] worknapi_create_async_work 呼叫傳回的控制代碼。

如果 API 成功,則傳回 napi_ok

此 API 會釋放先前配置的工作物件。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

napi_queue_async_work#

napi_status napi_queue_async_work(node_api_nogc_env env,
                                  napi_async_work work); 
  • [in] env:呼叫 API 時使用的環境。
  • [in] worknapi_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] worknapi_create_async_work 呼叫傳回的控制代碼。

如果 API 成功,則傳回 napi_ok

如果尚未開始,此 API 會取消排隊的工作。如果已開始執行,則無法取消,且會傳回 napi_generic_failure。如果成功,則 complete 回呼會以 napi_cancelled 的狀態值呼叫。即使已成功取消,也不應在 complete 回呼呼叫之前刪除工作。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

自訂非同步操作#

上述的簡單非同步工作 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_hooks init 勾子,且可由 async_hooks.executionAsyncResource() 存取。
  • [in] async_resource_name:提供給 async_hooks API 揭露的診斷資訊中,資源類型的識別碼。
  • [out] result:已初始化的非同步內容。

如果 API 成功,則傳回 napi_ok

async_resource 物件需要維持運作,直到 napi_async_destroy 才能讓 async_hooks 相關 API 正確運作。為了與先前版本保持 ABI 相容性,napi_async_context 並未維持對 async_resource 物件的強參照,以避免造成記憶體外洩。不過,如果 async_resourcenapi_async_contextnapi_async_destroy 銷毀前就被 JavaScript 引擎當成垃圾回收,呼叫 napi_async_context 相關 API(例如 napi_open_callback_scopenapi_make_callback)可能會造成問題,例如在使用 AsyncLocalStorage API 時失去非同步內容。

為了與先前版本保持 ABI 相容性,傳遞 NULLasync_resource 不會造成錯誤。不過,這並不建議,因為這會導致 async_hooks init hooksasync_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

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

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 相容,傳遞 NULLasync_context 不會產生錯誤。不過,這會導致非同步掛鉤運作不正確。潛在問題包括在使用 AsyncLocalStorage API 時失去非同步內容。
  • [in] recv:傳遞給所呼叫函式的 this 值。
  • [in] func:表示要呼叫的 JavaScript 函式的 napi_value
  • [in] argcargv 陣列中元素的數量。
  • [in] argv:JavaScript 值陣列,表示函式的引數,型態為 napi_value。如果 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_hooks init 掛鉤。這個參數已被棄用,且在執行時會被忽略。請改用 napi_async_init 中的 async_resource 參數。
  • [in] context:呼叫回呼的非同步作業的內容。這應該是先前從 napi_async_init 取得的值。
  • [out] result:新建立的範圍。

在某些情況下(例如,解析承諾),在執行某些 Node-API 呼叫時,必須擁有與回呼關聯的範圍的等效範圍。如果堆疊中沒有其他腳本,可以使用 napi_open_callback_scopenapi_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:要關閉的範圍。

即使有待處理的 JavaScript 例外狀況,也可以呼叫此 API。

版本管理#

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 的主要、次要和修補程式版本,以及使用 process.release.name 的值填入 version 結構的 release 欄位。

傳回的緩衝區是靜態配置的,不需要釋放。

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

此函數會向 V8 提供由 JavaScript 物件維持運作的外部配置記憶體數量 (例如,指向其自身由原生外掛程式配置的記憶體的 JavaScript 物件)。註冊外部配置記憶體會比平常更頻繁地觸發全域垃圾回收。

承諾#

Node-API 提供建立 Promise 物件的工具,如 ECMA 規範 第 25.4 節 所述。它實作承諾為一對物件。當透過 napi_create_promise() 建立承諾時,會建立一個「延遲」物件並與 Promise 一起傳回。延遲物件會繫結到建立的 Promise,且是透過 napi_resolve_deferred()napi_reject_deferred() 來解析或拒絕 Promise 的唯一方法。透過 napi_create_promise() 建立的延遲物件會透過 napi_resolve_deferred()napi_reject_deferred() 釋放。Promise 物件可以傳回 JavaScript,並以一般方式使用。

例如,建立承諾並將其傳遞給非同步工作執行

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() 會執行其非同步動作,然後解析或拒絕延遲,從而結束承諾並釋放延遲

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:新建立的延遲物件,稍後可以傳遞給 napi_resolve_deferred()napi_reject_deferred() 來解析或拒絕相關的承諾。
  • [out] promise:與延遲物件相關聯的 JavaScript 承諾。

如果 API 成功,則傳回 napi_ok

此 API 會建立延遲物件和 JavaScript 承諾。

napi_resolve_deferred#

napi_status napi_resolve_deferred(napi_env env,
                                  napi_deferred deferred,
                                  napi_value resolution); 
  • [in] env:呼叫 API 時使用的環境。
  • [in] deferred:要解析其相關承諾的延遲物件。
  • [in] resolution:用來解析承諾的值。

此 API 會透過與其關聯的延遲物件來解決 JavaScript 承諾。因此,它只能用來解決對應延遲物件可用的 JavaScript 承諾。這實際上表示承諾必須使用 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:要解析其相關承諾的延遲物件。
  • [in] rejection:用來拒絕承諾的值。

此 API 會透過與其關聯的延遲物件來拒絕 JavaScript 承諾。因此,它只能用來拒絕對應延遲物件可用的 JavaScript 承諾。這實際上表示承諾必須使用 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 是否為原生承諾物件 (也就是由底層引擎建立的承諾物件)。

腳本執行#

Node-API 提供一個 API,用於使用底層 JavaScript 引擎執行包含 JavaScript 的字串。

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_valuenapi_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() 永遠不會封鎖。

不應從 JavaScript 執行緒呼叫 napi_call_threadsafe_function() 並將其設定為 napi_tsfn_blocking,因為如果佇列已滿,可能會導致 JavaScript 執行緒陷入僵局。

實際呼叫 JavaScript 是由透過 call_js_cb 參數提供的回呼控制。call_js_cb 會在主執行緒中針對每個透過成功呼叫 napi_call_threadsafe_function() 放入佇列的值呼叫一次。如果未提供此類回呼,將使用預設回呼,而產生的 JavaScript 呼叫將沒有參數。call_js_cb 回呼會在參數中接收要呼叫的 JavaScript 函式作為 napi_value,以及在建立 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_release_threadsafe_function() 或在回應 napi_call_threadsafe_function 的呼叫時收到 napi_closing 的回傳狀態時,就會銷毀 napi_threadsafe_function 物件。在銷毀 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_functioninitial_thread_count 參數會標示執行緒安全函式的初始取得數目,而不是在建立時多次呼叫 napi_acquire_threadsafe_function

一旦使用 napi_threadsafe_function 的執行緒數量達到 0,則沒有其他執行緒可以透過呼叫 napi_acquire_threadsafe_function() 來開始使用它。事實上,除了 napi_release_threadsafe_function() 以外,與其相關的所有後續 API 呼叫都會傳回 napi_closing 的錯誤值。

執行緒安全函式可以透過將 napi_tsfn_abort 的值傳遞給 napi_release_threadsafe_function() 來「中止」。這將導致與執行緒安全函式相關的所有後續 API(除了 napi_release_threadsafe_function())在參考計數達到 0 之前便傳回 napi_closing。特別是,napi_call_threadsafe_function() 會傳回 napi_closing,從而通知執行緒不再可以對執行緒安全函式進行非同步呼叫。這可以用作終止執行緒的依據。收到 napi_call_threadsafe_function() 傳回的 napi_closing 之後,執行緒不得再使用執行緒安全函式,因為不再保證已配置它。

決定是否讓程序繼續執行#

與 libuv 句柄類似,執行緒安全函式可以「參考」和「取消參考」。「參考」的執行緒安全函式會導致建立它的執行緒上的事件迴圈保持運作,直到執行緒安全函式被銷毀。相反地,「取消參考」的執行緒安全函式不會阻止事件迴圈退出。napi_ref_threadsafe_functionnapi_unref_threadsafe_function API 即用於此目的。

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 函式,用於從另一個執行緒呼叫。如果將 NULL 傳遞給 call_js_cb,則必須提供它。
  • [in] async_resource:與非同步工作相關聯的選用物件,會傳遞給可能的 async_hooks init 勾子
  • [in] async_resource_name:一個 JavaScript 字串,提供識別碼,用於識別由 async_hooks API 揭露的診斷資訊所提供的資源類型。
  • [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 值為 undefinednapi_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_tsfn_nonblocking(表示佇列已滿時呼叫應立即傳回狀態 napi_queue_full)。

此 API 不應從 JavaScript 執行緒呼叫 napi_tsfn_blocking,因為如果佇列已滿,可能會導致 JavaScript 執行緒死結。

如果從任何執行緒呼叫 napi_release_threadsafe_function(),且將 abort 設為 napi_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 時,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 可能為空字串。