Node.js v21.7.2 文件
- Node.js v21.7.2
-
► 目錄
- Node-API
- ABI 穩定性的影響
- 建置
- 用法
- Node-API 版本矩陣
- 環境生命週期 API
- 基本的 Node-API 資料類型
- 錯誤處理
- 物件生命週期管理
- 模組註冊
- 使用 JavaScript 值
- 列舉類型
- 物件建立函式
napi_create_array
napi_create_array_with_length
napi_create_arraybuffer
napi_create_buffer
napi_create_buffer_copy
napi_create_date
napi_create_external
napi_create_external_arraybuffer
napi_create_external_buffer
napi_create_object
napi_create_symbol
node_api_symbol_for
napi_create_typedarray
napi_create_dataview
- 將 C 型別轉換為 Node-API 的函式
napi_create_int32
napi_create_uint32
napi_create_int64
napi_create_double
napi_create_bigint_int64
napi_create_bigint_uint64
napi_create_bigint_words
napi_create_string_latin1
node_api_create_external_string_latin1
napi_create_string_utf16
node_api_create_external_string_utf16
napi_create_string_utf8
node_api_create_property_key_utf16
- 將 Node-API 轉換為 C 型別的函式
napi_get_array_length
napi_get_arraybuffer_info
napi_get_buffer_info
napi_get_prototype
napi_get_typedarray_info
napi_get_dataview_info
napi_get_date_value
napi_get_value_bool
napi_get_value_double
napi_get_value_bigint_int64
napi_get_value_bigint_uint64
napi_get_value_bigint_words
napi_get_value_external
napi_get_value_int32
napi_get_value_int64
napi_get_value_string_latin1
napi_get_value_string_utf8
napi_get_value_string_utf16
napi_get_value_uint32
- 取得全域實例的函式
- 使用 JavaScript 值和抽象操作
- 使用 JavaScript 屬性
- 結構
- 函式
napi_get_property_names
napi_get_all_property_names
napi_set_property
napi_get_property
napi_has_property
napi_delete_property
napi_has_own_property
napi_set_named_property
napi_get_named_property
napi_has_named_property
napi_set_element
napi_get_element
napi_has_element
napi_delete_element
napi_define_properties
napi_object_freeze
napi_object_seal
- 使用 JavaScript 函式
- 物件包裝
- 簡單非同步作業
- 自訂非同步作業
- 版本管理
- 記憶體管理
- 承諾
- 指令碼執行
- libuv 事件迴圈
- 非同步執行緒安全函式呼叫
- 其他工具程式
- Node-API
-
► 索引
- 斷言測試
- 非同步內容追蹤
- 非同步掛鉤
- 緩衝區
- C++ 附加元件
- 使用 Node-API 的 C/C++ 附加元件
- C++ 嵌入式 API
- 子程序
- 叢集
- 命令列選項
- 主控台
- Corepack
- 加密
- 偵錯程式
- 已棄用的 API
- 診斷頻道
- DNS
- 網域
- 錯誤
- 事件
- 檔案系統
- 全域變數
- HTTP
- HTTP/2
- HTTPS
- 檢查器
- 國際化
- 模組:CommonJS 模組
- 模組:ECMAScript 模組
- 模組:
node:module
API - 模組:套件
- 網路
- 作業系統
- 路徑
- 效能掛鉤
- 權限
- 程序
- Punycode
- 查詢字串
- Readline
- REPL
- 報告
- 單一可執行應用程式
- 串流
- 字串解碼器
- 測試執行器
- 計時器
- TLS/SSL
- 追蹤事件
- TTY
- UDP/資料報
- URL
- 工具程式
- V8
- VM
- WASI
- Web Crypto API
- Web Streams API
- 工作執行緒
- Zlib
- ► 其他版本
- ► 選項
Node-API#
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 的專案,或是受到 node-gyp 限制影響的開發人員來說,CMake.js 是個不錯的選擇。build_with_cmake
是基於 CMake 的原生附加元件專案範例。
上傳預編譯二進位檔#
這裡列出的三個工具允許原生附加元件開發人員和維護人員建立二進位檔並上傳到公有或私有伺服器。這些工具通常與 CI/CD 建置系統整合,例如 Travis CI 和 AppVeyor,以建置和上傳各種平台和架構的二進位檔。這些二進位檔可供不需要安裝 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.h
或 js_native_api.h
之前時,API 才會可用。如果 API 看起來在晚於 added in:
中所示版本的 Node.js 上不可用,那麼這很可能是明顯缺失的原因。
與從原生程式碼存取 ECMAScript 功能嚴格相關的 Node-API 可以分別在 js_native_api.h
和 js_native_api_types.h
中找到。在這些標頭中定義的 API 會包含在 node_api.h
和 node_api_types.h
中。標頭會以這種方式建構,以便在 Node.js 外部實作 Node-API。對於那些實作而言,Node.js 特定的 API 可能不適用。
附加元件中特定於 Node.js 的部分可以與將實際功能公開給 JavaScript 環境的程式碼分開,以便後者可以用於 Node-API 的多個實作。在以下範例中,addon.c
和 addon.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_hook
和 napi_set_instance_data
的回呼函式傳遞。
node_api_nogc_env
#
此 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
#
外掛程式提供函式的函式指標類型,讓使用者在外部擁有資料準備好清理時收到通知,因為與它關聯的物件已遭垃圾回收。使用者必須提供符合下列簽章的函式,在物件收集時呼叫。目前,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_latin1
和 node_api_create_external_string_utf16
,env
參數可以為 null,因為外部字串可以在環境關閉的後段收集。
變更記錄
-
實驗性(定義了
NAPI_EXPERIMENTAL
)只能呼叫接受
node_api_nogc_env
作為其第一個參數的 Node-API 呼叫,否則應用程式將會終止,並顯示適當的錯誤訊息。此功能可透過定義NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT
來關閉。
napi_finalize
#
外掛程式提供的函式指標類型,允許使用者在垃圾回收週期完成後,根據垃圾回收事件排程一組呼叫至 Node-API。這些函式指標可以用於 node_api_post_finalizer
。
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint);
變更記錄
-
實驗性(定義了
NAPI_EXPERIMENTAL
)此類型的函式不再可以用作終結函式,除非與
node_api_post_finalizer
搭配使用。必須改用node_api_nogc_finalize
。此功能可透過定義NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT
來關閉。
napi_async_execute_callback
#
用於支援非同步作業的函式指標。回呼函式必須符合下列簽章
typedef void (*napi_async_execute_callback)(napi_env env, void* data);
此函式的實作必須避免執行會執行 JavaScript 或與 JavaScript 物件互動的 Node-API 呼叫。Node-API 呼叫應該改在 napi_async_complete_callback
中。請勿使用 napi_env
參數,因為這可能會導致執行 JavaScript。
napi_async_complete_callback
#
用於支援非同步作業的函式指標。回呼函式必須符合下列簽章
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data);
除非有 物件生命週期管理 中討論的原因,否則不需要在函式主體內建立處理和/或回呼範圍。
napi_threadsafe_function_call_js
#
用於非同步執行緒安全函式呼叫的函式指標。回呼函式將在主執行緒上呼叫。其目的是使用透過其中一個次要執行緒的佇列傳入的資料項目,來建構呼叫 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);
[in] data
:傳遞給napi_add_env_cleanup_hook
的資料。
napi_async_cleanup_hook
#
與 napi_add_async_cleanup_hook
搭配使用的函式指標。當環境要終止時,會呼叫此指標。
回呼函式必須符合下列簽章
typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
void* data);
[in] handle
:在非同步清理完成後,必須傳遞給napi_remove_async_cleanup_hook
的處理程序。[in] data
:傳遞給napi_add_async_cleanup_hook
的資料。
函式的本體應該在非同步清理動作的最後,啟動非同步清理動作,最後必須在呼叫 napi_remove_async_cleanup_hook
時傳遞 handle
。
錯誤處理#
Node-API 使用回傳值和 JavaScript 例外來處理錯誤。以下各節說明每種情況的方法。
回傳值#
所有 Node-API 函式共用相同的錯誤處理模式。所有 API 函式的回傳類型都是 napi_status
。
如果要求成功且未擲回任何未捕捉的 JavaScript 例外,回傳值會是 napi_ok
。如果發生錯誤且擲回例外,會回傳錯誤的 napi_status
值。如果擲回例外,但未發生錯誤,會回傳 napi_pending_exception
。
如果回傳值不是 napi_ok
或 napi_pending_exception
,必須呼叫 napi_is_exception_pending
來檢查是否有例外待處理。請參閱例外部分,以取得更多詳細資料。
所有可能的 napi_status
值都定義在 napi_api_types.h
中。
napi_status
回傳值提供發生錯誤的 VM 非相依表示。在某些情況下,取得更詳細的資訊會很有用,包括表示錯誤的字串以及 VM (引擎) 特定的資訊。
為了擷取此資訊,提供 napi_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_status
為 napi_ok
,則表示沒有例外狀況待處理,且不需要其他動作。如果傳回的 napi_status
不是 napi_ok
或 napi_pending_exception
,則必須呼叫 napi_is_exception_pending
以判斷是否有例外狀況待處理,才能嘗試復原並繼續,而不是立即傳回。
在許多情況下,當呼叫 Node-API 函式且已有例外狀況待處理時,函式會立即傳回 napi_status
為 napi_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_error
、napi_throw_type_error
、napi_throw_range_error
、node_api_throw_syntax_error
和 napi_is_error
。
如果原生程式碼需要建立 Error
物件,也可以使用下列公用函式:napi_create_error
、napi_create_type_error
、napi_create_range_error
和 node_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] msg
:napi_value
,參考要作為Error
訊息的 JavaScriptstring
。[out] result
:napi_value
,代表已建立的錯誤。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回 JavaScript Error
,並帶有提供的文字。
napi_create_type_error
#
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] code
:選用的napi_value
,其中包含與錯誤關聯的錯誤代碼字串。[in] msg
:napi_value
,參考要作為Error
訊息的 JavaScriptstring
。[out] result
:napi_value
,代表已建立的錯誤。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回 JavaScript TypeError
,並帶有提供的文字。
napi_create_range_error
#
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] code
:選用的napi_value
,其中包含與錯誤關聯的錯誤代碼字串。[in] msg
:napi_value
,參考要作為Error
訊息的 JavaScriptstring
。[out] result
:napi_value
,代表已建立的錯誤。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回 JavaScript RangeError
,並帶有提供的文字。
node_api_create_syntax_error
#
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] code
:選用的napi_value
,其中包含與錯誤關聯的錯誤代碼字串。[in] msg
:napi_value
,參考要作為Error
訊息的 JavaScriptstring
。[out] result
:napi_value
,代表已建立的錯誤。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回 JavaScript SyntaxError
,並帶有提供的文字。
napi_get_and_clear_last_exception
#
napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[out] result
:例外情況(如果有一個例外情況待處理),否則為NULL
。
如果 API 成功,則傳回 napi_ok
。
即使有待處理的 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_scope
和 napi_close_handle_scope
。
Node-API 僅支援範圍的單一巢狀階層。任何時候只有一個作用中範圍,而所有新處理常式會在該範圍作用中時與該範圍關聯。範圍必須以開啟順序的相反順序關閉。此外,在原生方法中建立的所有範圍都必須在從該方法傳回前關閉。
以先前的範例來說,新增呼叫 napi_open_handle_scope
和 napi_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_scope
和 napi_close_escapable_handle_scope
。
提升句柄的請求是透過 napi_escape_handle
進行,且只能呼叫一次。
napi_open_handle_scope
#
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
napi_handle_scope* result);
[in] env
:呼叫 API 時使用的環境。[out] result
:表示新範圍的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會開啟一個新範圍。
napi_close_handle_scope
#
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
napi_handle_scope scope);
[in] env
:呼叫 API 時使用的環境。[in] scope
:表示要關閉的範圍的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會關閉傳入的範圍。範圍必須依據建立的相反順序關閉。
即使有待處理的 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
:表示要逃逸的 JavaScriptObject
的napi_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_ref
和 napi_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] result
:napi_ref
參考的napi_value
。
如果 API 成功,則傳回 napi_ok
。
如果仍然有效,此 API 會傳回代表與 napi_ref
關聯的 JavaScript 值的 napi_value
。否則,result 會是 NULL
。
在目前的 Node.js 環境結束時進行清理#
雖然 Node.js 程序通常會在結束時釋放所有資源,但 Node.js 的嵌入者或未來的 Worker 支援可能需要附加元件註冊清理掛鉤,以便在目前的 Node.js 環境結束時執行。
Node-API 提供註冊和取消註冊此類回呼的函式。當執行這些回呼時,附加元件所持有的所有資源都應釋放。
napi_add_env_cleanup_hook
#
NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_nogc_env env,
napi_cleanup_hook fun,
void* arg);
註冊 fun
為一個函式,在當前 Node.js 環境結束時,使用 arg
參數執行。
可以安全地使用不同的 arg
值多次指定函式。在這種情況下,它也會被呼叫多次。不允許多次提供相同的 fun
和 arg
值,這將導致程序中止。
這些掛鉤將按相反順序呼叫,即最近新增的掛鉤將最先呼叫。
可以使用 napi_remove_env_cleanup_hook
來移除此掛鉤。通常,當新增此掛鉤的資源遭到破壞時,就會發生這種情況。
對於非同步清理,napi_add_async_cleanup_hook
可供使用。
napi_remove_env_cleanup_hook
#
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_nogc_env env,
void (*fun)(void* arg),
void* arg);
取消註冊 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_handle
和 arg
參數執行。
與 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);
[in] remove_handle
:使用napi_add_async_cleanup_hook
建立的非同步清理掛鉤的控制項。
取消註冊與 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_hook
和 napi_add_async_cleanup_hook
註冊清理掛勾,以正確順序手動釋放已配置的資源。
模組註冊#
Node-API 模組的註冊方式類似於其他模組,不同之處在於它不使用 NODE_MODULE
巨集,而是使用下列巨集
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
另一個不同之處在於 Init
方法的簽章。對於 Node-API 模組,簽章如下
napi_value Init(napi_env env, napi_value exports);
Init
的傳回值會視為模組的 exports
物件。Init
方法會透過 exports
參數傳遞一個空物件作為便利措施。如果 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;
}
env
和 exports
參數會提供給 NAPI_MODULE_INIT
巨集的主體。
所有 Node-API 外掛程式都具有內容感知,表示它們可能會被載入多次。在宣告此類模組時,有幾個設計考量。有關 內容感知外掛程式 的文件提供更多詳細資訊。
變數 env
和 exports
會在巨集呼叫後出現在函式主體內。
如需有關設定物件屬性的更多詳細資訊,請參閱 使用 JavaScript 屬性 一節。
如需有關一般外掛程式模組建置的更多詳細資訊,請參閱現有的 API。
使用 JavaScript 值#
Node-API 公開一組 API 來建立所有類型的 JavaScript 值。其中一些類型記載於 第 6 節 的 ECMAScript 語言規範 中。
基本上,這些 API 用於執行下列其中一項操作
- 建立新的 JavaScript 物件
- 從原始 C 類型轉換為 Node-API 值
- 從 Node-API 值轉換為原始 C 類型
- 取得全域執行個體,包括
undefined
和null
Node-API 值由類型 napi_value
表示。任何需要 JavaScript 值的 Node-API 呼叫都會採用 napi_value
。在某些情況下,API 會預先檢查 napi_value
的類型。但是,為了提升效能,呼叫者最好確保有問題的 napi_value
是 API 預期的 JavaScript 類型。
列舉類型#
napi_key_collection_mode
#
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode;
描述 Keys/Properties
篩選器列舉
napi_key_collection_mode
限制收集的屬性範圍。
napi_key_own_only
將收集的屬性限制為僅給定的物件。napi_key_include_prototypes
也會包含物件原型鏈的所有鍵。
napi_key_filter
#
typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter;
屬性篩選器位元。它們可以透過或運算來建立複合篩選器。
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
也可以表示具有外部資料的 Function
和 Object
。
類型為 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
:表示 JavaScriptArray
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 傳回對應於 JavaScript Array
類型的 Node-API 值。JavaScript 陣列在 ECMAScript 語言規範的 第 22.1 節 中有說明。
napi_create_array_with_length
#
napi_status napi_create_array_with_length(napi_env env,
size_t length,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] length
:Array
的初始長度。[out] result
:表示 JavaScriptArray
的napi_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] data
:ArrayBuffer
的底層位元組緩衝區指標。data
可以選擇忽略,方法是傳入NULL
。[out] result
:表示 JavaScriptArrayBuffer
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回對應於 JavaScript ArrayBuffer
的 Node-API 值。ArrayBuffer
用於表示固定長度的二進位資料緩衝區。它們通常用作 TypedArray
物件的後援緩衝區。配置的 ArrayBuffer
會有一個底層位元組緩衝區,其大小由傳入的 length
參數決定。底層緩衝區會選擇性地傳回給呼叫者,以防呼叫者想要直接操作緩衝區。此緩衝區只能從原生程式碼直接寫入。若要從 JavaScript 寫入此緩衝區,需要建立一個型別化陣列或 DataView
物件。
JavaScript ArrayBuffer
物件說明於 ECMAScript 語言規範的 第 24.1 節。
napi_create_buffer
#
napi_status napi_create_buffer(napi_env env,
size_t size,
void** data,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] size
:底層緩衝區的位元組大小。[out] data
:基礎緩衝區的原始指標。可選擇傳遞NULL
來忽略data
。[out] result
:表示node::Buffer
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 分配 node::Buffer
物件。雖然這仍是完全支援的資料結構,但在大多數情況下,使用 TypedArray
就已足夠。
napi_create_buffer_copy
#
napi_status napi_create_buffer_copy(napi_env env,
size_t length,
const void* data,
void** result_data,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] size
:輸入緩衝區的位元組大小(應與新緩衝區的大小相同)。[in] data
:要複製的基礎緩衝區的原始指標。[out] result_data
:指向新的Buffer
的基礎資料緩衝區的指標。可選擇傳遞NULL
來忽略result_data
。[out] result
:表示node::Buffer
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 分配 node::Buffer
物件,並使用從傳入緩衝區複製的資料來初始化它。雖然這仍是完全支援的資料結構,但在大多數情況下,使用 TypedArray
就已足夠。
napi_create_date
#
napi_status napi_create_date(napi_env env,
double time,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] time
:自 1970 年 1 月 1 日 UTC 以來的毫秒為單位的 ECMAScript 時間值。[out] result
:表示 JavaScriptDate
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 不會觀察閏秒;它們會被忽略,因為 ECMAScript 與 POSIX 時間規範保持一致。
此 API 分配 JavaScript Date
物件。
JavaScript Date
物件在 ECMAScript 語言規範的 第 20.3 節 中有說明。
napi_create_external
#
napi_status napi_create_external(napi_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] data
:外部資料的原始指標。[in] finalize_cb
:收集外部值時呼叫的選用回呼。napi_finalize
提供更多詳細資訊。[in] finalize_hint
:在收集期間傳遞給終止回呼的選用提示。[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_data
:ArrayBuffer
的底層位元組緩衝區指標。[in] byte_length
:底層緩衝區的位元組長度。[in] finalize_cb
:收集ArrayBuffer
時呼叫的選用回呼。napi_finalize
提供更多詳細資訊。[in] finalize_hint
:在收集期間傳遞給終止回呼的選用提示。[out] result
:表示 JavaScriptArrayBuffer
的napi_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::Buffer
的napi_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,Buffers
是 Uint8Array
。
napi_create_object
#
napi_status napi_create_object(napi_env env, napi_value* result)
[in] env
:呼叫 API 時使用的環境。[out] result
:表示 JavaScriptObject
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會配置一個預設的 JavaScript Object
。它等同於在 JavaScript 中執行 new Object()
。
JavaScript Object
類型在 ECMAScript 語言規範的 第 6.1.7 節 中描述。
napi_create_symbol
#
napi_status napi_create_symbol(napi_env env,
napi_value description,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] description
:選用的napi_value
,它參照要設定為符號描述的 JavaScriptstring
。[out] result
:表示 JavaScriptsymbol
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 從 UTF8 編碼的 C 字串建立一個 JavaScript symbol
值。
JavaScript symbol
類型在 ECMAScript 語言規範的 第 19.4 節 中描述。
node_api_symbol_for
#
napi_status node_api_symbol_for(napi_env env,
const char* utf8description,
size_t length,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] utf8description
:用於表示符號描述的 UTF-8 C 字串。[in] length
:描述字串的長度(以位元組為單位),如果以 null 終止,則為NAPI_AUTO_LENGTH
。[out] result
:表示 JavaScriptsymbol
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會在全域註冊表中搜尋具有指定描述的現有符號。如果符號已存在,將會傳回,否則會在註冊表中建立新的符號。
JavaScript symbol
類型在 ECMAScript 語言規範的 第 19.4 節 中描述。
napi_create_typedarray
#
napi_status napi_create_typedarray(napi_env env,
napi_typedarray_type type,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] type
:TypedArray
內元素的純量資料類型。[in] length
:TypedArray
內的元素數量。[in] arraybuffer
:TypedArray
底層的ArrayBuffer
。[in] byte_offset
:從中開始投影TypedArray
的ArrayBuffer
內的位元組偏移量。[out] result
:表示 JavaScriptTypedArray
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會在現有的 ArrayBuffer
上建立 JavaScript TypedArray
物件。TypedArray
物件會提供底層資料緩衝區的陣列狀檢視,其中每個元素都具有相同的底層二進位純量資料類型。
(length * size_of_element) + byte_offset
必須小於或等於傳入陣列的位元組大小。如果不是,則會引發 RangeError
例外狀況。
JavaScript TypedArray
物件說明於 ECMAScript 語言規範的 第 22.2 節。
napi_create_dataview
#
napi_status napi_create_dataview(napi_env env,
size_t byte_length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] length
:DataView
內的元素數量。[in] arraybuffer
:DataView
底層的ArrayBuffer
。[in] byte_offset
:ArrayBuffer
中的位元組偏移量,用於開始投射DataView
。[out] result
:表示 JavaScriptDataView
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 在現有的 ArrayBuffer
上建立 JavaScript DataView
物件。DataView
物件提供底層資料緩衝區的陣列狀檢視,但允許 ArrayBuffer
中不同大小和類型的項目。
byte_length + byte_offset
必須小於或等於傳入陣列的位元組大小。否則,會引發 RangeError
例外狀況。
JavaScript DataView
物件說明在 ECMAScript 語言規範的 第 24.3 節 中。
將 C 類型轉換為 Node-API 的函式#
napi_create_int32
#
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要在 JavaScript 中表示的整數值。[out] result
:表示 JavaScriptnumber
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 用於將 C int32_t
類型轉換為 JavaScript number
類型。
JavaScript number
類型說明在 ECMAScript 語言規範的 第 6.1.6 節 中。
napi_create_uint32
#
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要在 JavaScript 中表示的無號整數值。[out] result
:表示 JavaScriptnumber
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 用於將 C uint32_t
類型轉換為 JavaScript number
類型。
JavaScript number
類型說明在 ECMAScript 語言規範的 第 6.1.6 節 中。
napi_create_int64
#
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要在 JavaScript 中表示的整數值。[out] result
:表示 JavaScriptnumber
的napi_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
:表示 JavaScriptnumber
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 用於將 C double
類型轉換為 JavaScript number
類型。
JavaScript number
類型說明在 ECMAScript 語言規範的 第 6.1.6 節 中。
napi_create_bigint_int64
#
napi_status napi_create_bigint_int64(napi_env env,
int64_t value,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] value
:要在 JavaScript 中表示的整數值。[out] result
:表示 JavaScriptBigInt
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 將 C int64_t
類型轉換為 JavaScript BigInt
類型。
napi_create_bigint_uint64
#
napi_status napi_create_bigint_uint64(napi_env env,
uint64_t value,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] value
:要在 JavaScript 中表示的無號整數值。[out] result
:表示 JavaScriptBigInt
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 將 C uint64_t
類型轉換為 JavaScript BigInt
類型。
napi_create_bigint_words
#
napi_status napi_create_bigint_words(napi_env env,
int sign_bit,
size_t word_count,
const uint64_t* words,
napi_value* result);
[in] env
:呼叫 API 時使用的環境。[in] sign_bit
:決定產生的BigInt
是正數還是負數。[in] word_count
:words
陣列的長度。[in] words
:uint64_t
小端序 64 位元字元的陣列。[out] result
:表示 JavaScriptBigInt
的napi_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
:代表 JavaScriptstring
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會從 ISO-8859-1 編碼的 C 字串建立 JavaScript string
值。會複製原生字串。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
node_api_create_external_string_latin1
#
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_hint
。napi_finalize
提供更多詳細資訊。此參數是選用的。傳遞 null 值表示外掛程式不需要在對應的 JavaScript 字串被收集時收到通知。
[in] finalize_hint
:在收集期間傳遞給終止回呼的選用提示。[out] result
:代表 JavaScriptstring
的napi_value
。[out] copied
:字串是否已複製。如果已複製,則會呼叫完成函式來銷毀str
。
如果 API 成功,則傳回 napi_ok
。
此 API 會從 ISO-8859-1 編碼的 C 字串建立 JavaScript string
值。原生字串可能未複製,因此必須存在於 JavaScript 值的整個生命週期中。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
napi_create_string_utf16
#
napi_status napi_create_string_utf16(napi_env env,
const char16_t* str,
size_t length,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] str
:代表 UTF16-LE 編碼字串的字元緩衝區。[in] length
:字串的長度(以兩個位元組的程式碼單位表示),或如果以 null 結尾,則為NAPI_AUTO_LENGTH
。[out] result
:代表 JavaScriptstring
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會從 UTF16-LE 編碼的 C 字串建立 JavaScript string
值。原生字串已複製。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
node_api_create_external_string_utf16
#
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_hint
。napi_finalize
提供更多詳細資訊。此參數是選用的。傳遞 null 值表示外掛程式不需要在對應的 JavaScript 字串被收集時收到通知。
[in] finalize_hint
:在收集期間傳遞給終止回呼的選用提示。[out] result
:代表 JavaScriptstring
的napi_value
。[out] copied
:字串是否已複製。如果已複製,則會呼叫完成函式來銷毀str
。
如果 API 成功,則傳回 napi_ok
。
此 API 會從 UTF16-LE 編碼的 C 字串建立 JavaScript string
值。原生字串可能未複製,因此必須存在於 JavaScript 值的整個生命週期中。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
napi_create_string_utf8
#
napi_status napi_create_string_utf8(napi_env env,
const char* str,
size_t length,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] str
:代表 UTF8 編碼字串的字元緩衝區。[in] length
:字串的長度(單位:位元組),如果以 null 終止,則為NAPI_AUTO_LENGTH
。[out] result
:代表 JavaScriptstring
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 會從 UTF8 編碼的 C 字串建立 JavaScript string
值。原生字串已複製。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
node_api_create_property_key_utf16
#
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
,代表最佳化的 JavaScriptstring
,用於作為物件的屬性金鑰。
如果 API 成功,則傳回 napi_ok
。
此 API 從 UTF16-LE 編碼的 C 字串建立最佳化的 JavaScript string
值,以用作物件的屬性金鑰。會複製原生字串。
包括 V8 在內的許多 JavaScript 引擎使用內部化字串作為設定和取得屬性值的鍵。它們通常使用雜湊表來建立和查詢此類字串。雖然它會增加每個金鑰建立的成本,但它會在建立後透過比較字串指標(而非整個字串)來提升效能。
如果新的 JavaScript 字串打算用作屬性金鑰,那麼對某些 JavaScript 引擎而言,使用 node_api_create_property_key_utf16
函式會更有效率。否則,請使用 napi_create_string_utf16
或 node_api_create_external_string_utf16
函式,因為使用此方法建立/儲存字串可能會產生額外的負擔。
JavaScript string
類型在 ECMAScript 語言規範的 第 6.1.4 節 中有說明。
從 Node-API 轉換為 C 類型的函式#
napi_get_array_length
#
napi_status napi_get_array_length(napi_env env,
napi_value value,
uint32_t* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:代表要查詢其長度的 JavaScriptArray
的napi_value
。[out] result
:代表陣列長度的uint32
。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回陣列的長度。
Array
長度在 ECMAScript 語言規範的 第 22.1.4.1 節 中說明。
napi_get_arraybuffer_info
#
napi_status napi_get_arraybuffer_info(napi_env env,
napi_value arraybuffer,
void** data,
size_t* byte_length)
[in] env
:呼叫 API 時使用的環境。[in] arraybuffer
: 表示正在查詢的ArrayBuffer
的napi_value
。[out] data
:ArrayBuffer
的底層資料緩衝區。如果 byte_length 為0
,這可能是NULL
或任何其他指標值。[out] byte_length
: 底層資料緩衝區的長度(以位元組為單位)。
如果 API 成功,則傳回 napi_ok
。
此 API 用於擷取 ArrayBuffer
的底層資料緩衝區及其長度。
警告:使用此 API 時請小心。底層資料緩衝區的生命週期由 ArrayBuffer
管理,即使在它被傳回之後也是如此。使用此 API 的一種可能安全的方式是搭配 napi_create_reference
使用,它可用於保證控制 ArrayBuffer
的生命週期。只要沒有呼叫可能會觸發 GC 的其他 API,在同一個回呼中使用傳回的資料緩衝區也是安全的。
napi_get_buffer_info
#
napi_status napi_get_buffer_info(napi_env env,
napi_value value,
void** data,
size_t* length)
[in] env
:呼叫 API 時使用的環境。[in] value
: 表示正在查詢的node::Buffer
或Uint8Array
的napi_value
。[out] data
:node::Buffer
或Uint8Array
的底層資料緩衝區。如果 length 為0
,這可能是NULL
或任何其他指標值。[out] length
: 底層資料緩衝區的長度(以位元組為單位)。
如果 API 成功,則傳回 napi_ok
。
此方法傳回與 napi_get_typedarray_info
相同的 data
和 byte_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
: 表示要傳回其原型的 JavaScriptObject
的napi_value
。這會傳回等同於Object.getPrototypeOf
的值(與函式的prototype
屬性不同)。[out] result
:表示給定物件原型的napi_value
。
如果 API 成功,則傳回 napi_ok
。
napi_get_typedarray_info
#
napi_status napi_get_typedarray_info(napi_env env,
napi_value typedarray,
napi_typedarray_type* type,
size_t* length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset)
[in] env
:呼叫 API 時使用的環境。[in] typedarray
:表示要查詢其屬性的TypedArray
的napi_value
。[out] type
:TypedArray
內元素的純量資料類型。[out] length
:TypedArray
中的元素數量。[out] data
:TypedArray
底層的資料緩衝區,已由byte_offset
值調整,以便指向TypedArray
中的第一個元素。如果陣列長度為0
,則這可能是NULL
或任何其他指標值。[out] arraybuffer
:TypedArray
底層的ArrayBuffer
。[out] byte_offset
:陣列第一個元素位於底層原生陣列中的位元組偏移量。資料參數的值已調整,以便資料指向陣列中的第一個元素。因此,原生陣列的第一個位元組將位於data - 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
:表示要查詢其屬性的DataView
的napi_value
。[out] byte_length
:DataView
中的位元組數。[out] data
:DataView
底層的資料緩衝區。如果 byte_length 為0
,這可能是NULL
或任何其他指標值。[out] arraybuffer
:DataView
底層的ArrayBuffer
。[out] byte_offset
:從中開始投射DataView
的資料緩衝區內的位元組偏移量。
如果 API 成功,則傳回 napi_ok
。
如果不需要某項屬性,任何輸出參數都可以是 NULL
。
此 API 會傳回 DataView
的各種屬性。
napi_get_date_value
#
napi_status napi_get_date_value(napi_env env,
napi_value value,
double* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:代表 JavaScriptDate
的napi_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
:代表 JavaScriptBoolean
的napi_value
。[out] result
:給定 JavaScriptBoolean
的 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
:代表 JavaScriptnumber
的napi_value
。[out] result
:給定 JavaScriptnumber
的 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
:代表 JavaScriptBigInt
的napi_value
。[out] result
:給定 JavaScriptBigInt
的 Cint64_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
:代表 JavaScriptBigInt
的napi_value
。[out] result
:給定 JavaScriptBigInt
的 Cuint64_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
:代表 JavaScriptBigInt
的napi_value
。[out] sign_bit
:代表 JavaScriptBigInt
為正數或負數的整數。[in/out] word_count
:必須初始化為words
陣列的長度。傳回時,會設為儲存此BigInt
所需的實際字數。[out] words
:指向預先配置的 64 位元字陣列的指標。
如果 API 成功,則傳回 napi_ok
。
此 API 將單一 BigInt
值轉換為符號位元、64 位元小端陣列,以及陣列中的元素數。sign_bit
和 words
都可以設為 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
:代表 JavaScriptnumber
的napi_value
。[out] result
:給定 JavaScriptnumber
的 Cint32
基本型等效值。
如果 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
:代表 JavaScriptnumber
的napi_value
。[out] result
:給定 JavaScriptnumber
的 Cint64
基本型等效值。
如果 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
:代表 JavaScriptnumber
的napi_value
。[out] result
:給定napi_value
的 C 原始等效項,為uint32_t
。
如果 API 成功,則傳回 napi_ok
。如果傳入的 napi_value
不是數字,則傳回 napi_number_expected
。
此 API 會傳回給定 napi_value
的 C 原始等效項,為 uint32_t
。
取得全域實例的函式#
napi_get_boolean
#
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要擷取的布林值。[out] result
:表示要擷取的 JavaScriptBoolean
單例的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
:表示 JavaScriptglobal
物件的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
:表示 JavaScriptnull
物件的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 支援執行下列其中一項操作
- 將 JavaScript 值強制轉換為特定 JavaScript 類型(例如
number
或string
)。 - 檢查 JavaScript 值的類型。
- 檢查兩個 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
:表示強制轉換的 JavaScriptBoolean
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 實作 ECMAScript 語言規格 第 7.1.2 節 中定義的抽象運算 ToBoolean()
。
napi_coerce_to_number
#
napi_status napi_coerce_to_number(napi_env env,
napi_value value,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要強制轉換的 JavaScript 值。[out] result
:表示強制轉換的 JavaScriptnumber
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 實作 ECMAScript 語言規格 第 7.1.3 節 中定義的抽象運算 ToNumber()
。如果傳入的值是物件,此函式可能會執行 JS 程式碼。
napi_coerce_to_object
#
napi_status napi_coerce_to_object(napi_env env,
napi_value value,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要強制轉換的 JavaScript 值。[out] result
:表示強制轉換的 JavaScriptObject
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 實作 ECMAScript 語言規格 第 7.1.13 節 中定義的抽象運算 ToObject()
。
napi_coerce_to_string
#
napi_status napi_coerce_to_string(napi_env env,
napi_value value,
napi_value* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要強制轉換的 JavaScript 值。[out] result
:表示強制轉換的 JavaScriptstring
的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 實作 ECMAScript 語言規格 第 7.1.13 節 中定義的抽象運算 ToString()
。如果傳入的值是物件,此函式可能會執行 JS 程式碼。
napi_typeof
#
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要查詢其類型的 JavaScript 值。[out] result
:JavaScript 值的類型。
如果 API 成功,則傳回 napi_ok
。
- 如果
value
的類型不是已知的 ECMAScript 類型,且value
不是外部值,則為napi_invalid_arg
。
此 API 表示類似於在物件上呼叫 typeof
算子的行為,如 ECMAScript 語言規範第 12.5.5 節 所定義。不過,有些差異
- 它支援偵測外部值。
- 它將
null
偵測為一個獨立的類型,而 ECMAScripttypeof
會偵測為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::Buffer
或Uint8Array
物件。
如果 API 成功,則傳回 napi_ok
。
此 API 檢查傳入的 Object
是否為緩衝區或 Uint8Array。如果呼叫者需要檢查值是否為 Uint8Array,則應優先使用 napi_is_typedarray
。
napi_is_date
#
napi_status napi_is_date(napi_env env, napi_value value, bool* result)
[in] env
:呼叫 API 時使用的環境。[in] value
:要檢查的 JavaScript 值。[out] result
:給定的napi_value
是否代表 JavaScriptDate
物件。
如果 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
:要分離的 JavaScriptArrayBuffer
。
如果 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
:要檢查的 JavaScriptArrayBuffer
。[out] result
:arraybuffer
是否已分離。
如果 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_class
。napi_define_properties
會忽略它。napi_default_method
:就像 JS 類別中的方法,屬性是可設定且可寫入的,但不可列舉。napi_default_jsproperty
:就像透過 JavaScript 中的指定設定的屬性,屬性是可寫入、可列舉且可設定的。
napi_property_descriptor
#
typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;
napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;
napi_property_attributes attributes;
void* data;
} napi_property_descriptor;
utf8name
:描述屬性金鑰的選用字串,編碼為 UTF8。屬性必須提供utf8name
或name
之一。name
:指向要作為屬性金鑰使用的 JavaScript 字串或符號的選用napi_value
。屬性必須提供utf8name
或name
之一。value
:如果屬性為資料屬性,則為透過屬性的取得存取所擷取的值。如果傳入此值,請將getter
、setter
、method
和data
設定為NULL
(因為這些成員將不會使用)。getter
:在執行屬性的取得存取時要呼叫的函式。如果傳入此值,請將value
和method
設定為NULL
(因為這些成員將不會使用)。當從 JavaScript 程式碼存取屬性(或使用 Node-API 呼叫對屬性執行取得)時,執行時期會隱含呼叫指定的函式。napi_callback
提供更多詳細資料。setter
:在執行屬性的設定存取時要呼叫的函式。如果傳入此值,請將value
和method
設定為NULL
(因為這些成員將不會使用)。當從 JavaScript 程式碼設定屬性(或使用 Node-API 呼叫對屬性執行設定)時,執行時期會隱含呼叫指定的函式。napi_callback
提供更多詳細資料。method
:設定此值可將屬性描述物件的value
屬性設為由method
表示的 JavaScript 函式。如果傳入此值,請將value
、getter
和setter
設定為NULL
(因為這些成員將不會使用)。napi_callback
提供更多詳細資料。attributes
:與特定屬性關聯的屬性。請參閱napi_property_attributes
。data
:如果呼叫此函式,則傳遞至method
、getter
和setter
的回呼資料。
函式#
napi_get_property_names
#
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要從中擷取屬性的物件。[out] result
:代表物件屬性名稱的 JavaScript 值陣列的napi_value
。可以使用napi_get_array_length
和napi_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_length
和napi_get_element
來反覆處理result
。
如果 API 成功,則傳回 napi_ok
。
此 API 會傳回包含此物件可用屬性名稱的陣列。
napi_set_property
#
napi_status napi_set_property(napi_env env,
napi_value object,
napi_value key,
napi_value value);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要設定屬性的物件。[in] key
:要設定的屬性名稱。[in] value
:屬性值。
如果 API 成功,則傳回 napi_ok
。
此 API 會設定傳入的 Object
上的屬性。
napi_get_property
#
napi_status napi_get_property(napi_env env,
napi_value object,
napi_value key,
napi_value* result);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要從中擷取屬性的物件。[in] key
:要擷取的屬性名稱。[out] result
:屬性的值。
如果 API 成功,則傳回 napi_ok
。
此 API 從傳入的 Object
中取得要求的屬性。
napi_has_property
#
napi_status napi_has_property(napi_env env,
napi_value object,
napi_value key,
bool* result);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要查詢的物件。[in] key
:要檢查是否存在屬性的名稱。[out] result
:物件上是否存在屬性。
如果 API 成功,則傳回 napi_ok
。
此 API 檢查傳入的 Object
是否有指定的屬性。
napi_delete_property
#
napi_status napi_delete_property(napi_env env,
napi_value object,
napi_value key,
bool* result);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要查詢的物件。[in] key
:要刪除的屬性名稱。[out] result
:屬性刪除是否成功。result
可以選擇忽略,方法是傳遞NULL
。
如果 API 成功,則傳回 napi_ok
。
此 API 嘗試從 object
中刪除 key
自有屬性。
napi_has_own_property
#
napi_status napi_has_own_property(napi_env env,
napi_value object,
napi_value key,
bool* result);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要查詢的物件。[in] key
:要檢查是否存在自有屬性的名稱。[out] result
:物件上是否存在自有屬性。
如果 API 成功,則傳回 napi_ok
。
此 API 檢查傳入的 Object
是否有指定的自有屬性。key
必須是 string
或 symbol
,否則會擲回錯誤。Node-API 不會在資料類型之間進行任何轉換。
napi_set_named_property
#
napi_status napi_set_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value value);
[in] env
:Node-API 呼叫在其中呼叫的環境。[in] object
:要設定屬性的物件。[in] utf8Name
:要設定的屬性的名稱。[in] value
:屬性值。
如果 API 成功,則傳回 napi_ok
。
此方法等於呼叫 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_count
:properties
陣列中的元素數量。[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] argc
:argv
陣列中元素的數量。[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] length
:utf8name
的長度(以位元組為單位),或如果以 null 終止,則為NAPI_AUTO_LENGTH
。[in] cb
:呼叫此函式物件時應呼叫的原生函式。napi_callback
提供更多詳細資訊。[in] data
:使用者提供的資料內容。這會在稍後呼叫函式時傳回函式。[out] result
:表示新建立函式的 JavaScript 函式物件的napi_value
。
如果 API 成功,則傳回 napi_ok
。
此 API 允許外掛程式作者在原生程式碼中建立函式物件。這是允許從 JavaScript 呼叫 外掛程式的原生程式碼 的主要機制。
此呼叫後,新建立的函式不會自動在腳本中可見。相反地,必須明確設定屬性在任何對 JavaScript 可見的物件上,才能讓函式從腳本中存取。
若要將函式公開為附加元件模組輸出的一部分,請在輸出物件上設定新建立的函式。範例模組可能如下所示
napi_value SayHello(napi_env env, napi_callback_info info) {
printf("Hello\n");
return NULL;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return NULL;
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
給定上述程式碼,附加元件可從 JavaScript 使用如下所示
const myaddon = require('./addon');
myaddon.sayHello();
傳遞給 require()
的字串是 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] argv
:napi_value
的 C 陣列,引數將複製到其中。如果引數多於提供的計數,只會複製要求的引數數量。如果提供的引數少於宣稱的數量,argv
的其餘部分會填入代表undefined
的napi_value
值。argv
可以選擇透過傳遞NULL
來忽略。[out] thisArg
:接收呼叫的 JavaScriptthis
引數。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] argc
:argv
陣列中元素的數量。[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 呼叫。
napi_define_class
API 定義一個 JavaScript 類別,其中包含建構函式、靜態屬性和方法,以及與 C++ 類別對應的實例屬性和方法。- 當 JavaScript 程式碼呼叫建構函式時,建構函式回呼會使用
napi_wrap
將新的 C++ 實例包裝在 JavaScript 物件中,然後傳回包裝器物件。 - 當 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] length
:utf8name
的長度(以位元組為單位),或如果以 null 終止,則為NAPI_AUTO_LENGTH
。[in] constructor
:處理建構類別實例的 callback 函式。在封裝 C++ 類別時,此方法必須是具有napi_callback
簽章的靜態成員。無法使用 C++ 類別建構函式。napi_callback
提供更多詳細資料。[in] data
:傳遞給建構函式 callback 的選用資料,作為 callback 資訊的data
屬性。[in] property_count
:properties
陣列引數中的項目數目。[in] properties
:描述類別中靜態和執行個體資料屬性、存取器和方法的屬性描述符陣列,請參閱napi_property_descriptor
。[out] result
:代表類別建構函式的napi_value
。
如果 API 成功,則傳回 napi_ok
。
定義 JavaScript 類別,包括
- 具有類別名稱的 JavaScript 建構函式。在封裝對應的 C++ 類別時,可透過
constructor
傳遞的回呼函式來實例化新的 C++ 類別執行個體,然後可將其置入使用napi_wrap
建構的 JavaScript 物件執行個體中。 - 建構函式上的屬性,其實作可呼叫 C++ 類別對應的靜態資料屬性、存取器和方法(由具有
napi_static
屬性的屬性描述符定義)。 - 建構函式
prototype
物件上的屬性。在封裝 C++ 類別時,可從屬性描述符中給定的靜態函式呼叫 C++ 類別的非靜態資料屬性、存取器和方法,而無需使用napi_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
#
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_work
和 napi_delete_async_work
來建立/刪除。
execute
和 complete
回呼是執行器準備執行和完成其任務時會呼叫的函式。
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] result
:napi_async_work*
,這是新建立的非同步工作的控制代碼。
如果 API 成功,則傳回 napi_ok
。
此 API 會配置一個工作物件,用於以非同步方式執行邏輯。一旦不再需要工作,應使用 napi_delete_async_work
將其釋放。
async_resource_name
應為以 Null 終止的 UTF-8 編碼字串。
async_resource_name
識別碼由使用者提供,應代表正在執行的非同步工作類型。建議對識別碼套用命名空間,例如包含模組名稱。請參閱 async_hooks
文件 以取得更多資訊。
napi_delete_async_work
#
napi_status napi_delete_async_work(napi_env env,
napi_async_work work);
[in] env
:呼叫 API 時使用的環境。[in] work
:napi_create_async_work
呼叫傳回的控制代碼。
如果 API 成功,則傳回 napi_ok
。
此 API 會釋放先前配置的工作物件。
即使有待處理的 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] work
:napi_create_async_work
呼叫傳回的控制代碼。
如果 API 成功,則傳回 napi_ok
。
此 API 要求將先前配置的工作排程執行。一旦成功傳回,此 API 不得再使用相同的 napi_async_work
項目呼叫,否則結果將未定義。
napi_cancel_async_work
#
napi_status napi_cancel_async_work(node_api_nogc_env env,
napi_async_work work);
[in] env
:呼叫 API 時使用的環境。[in] work
:napi_create_async_work
呼叫傳回的控制代碼。
如果 API 成功,則傳回 napi_ok
。
如果尚未開始,此 API 會取消排隊的工作。如果已開始執行,則無法取消,且會傳回 napi_generic_failure
。如果成功,則 complete
回呼會以 napi_cancelled
的狀態值呼叫。即使已成功取消,也不應在 complete
回呼呼叫之前刪除工作。
即使有待處理的 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_resource
在 napi_async_context
被 napi_async_destroy
銷毀前就被 JavaScript 引擎當成垃圾回收,呼叫 napi_async_context
相關 API(例如 napi_open_callback_scope
和 napi_make_callback
)可能會造成問題,例如在使用 AsyncLocalStorage
API 時失去非同步內容。
為了與先前版本保持 ABI 相容性,傳遞 NULL
給 async_resource
不會造成錯誤。不過,這並不建議,因為這會導致 async_hooks
init
hooks 和 async_hooks.executionAsyncResource()
出現不理想的行為,因為底層 async_hooks
實作現在需要資源才能提供非同步回呼之間的連結。
napi_async_destroy
#
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context);
[in] env
:呼叫 API 時使用的環境。[in] async_context
:要銷毀的非同步內容。
如果 API 成功,則傳回 napi_ok
。
即使有待處理的 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 相容,傳遞NULL
給async_context
不會產生錯誤。不過,這會導致非同步掛鉤運作不正確。潛在問題包括在使用AsyncLocalStorage
API 時失去非同步內容。[in] recv
:傳遞給所呼叫函式的this
值。[in] func
:表示要呼叫的 JavaScript 函式的napi_value
。[in] argc
:argv
陣列中元素的數量。[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_scope
和 napi_close_callback_scope
函數開啟/關閉所需的範圍。
napi_close_callback_scope
#
NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
napi_callback_scope scope)
[in] env
:呼叫 API 時使用的環境。[in] scope
:要關閉的範圍。
即使有待處理的 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 程式碼字串,並傳回其結果,但有下列注意事項
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_env
、napi_value
或 napi_ref
的 Node-API 函數不得從這些執行緒呼叫。
當外掛程式有其他執行緒,且需要根據這些執行緒完成的處理呼叫 JavaScript 函數時,這些執行緒必須與外掛程式的執行緒進行通訊,以便主執行緒可以代表它們呼叫 JavaScript 函數。執行緒安全函數 API 提供一個簡單的方法來執行此操作。
這些 API 提供類型 napi_threadsafe_function
,以及建立、銷毀和呼叫此類型的物件的 API。napi_create_threadsafe_function()
會建立一個持續性參考,指向包含 JavaScript 函數的 napi_value
,此函數可以從多個執行緒呼叫。呼叫會非同步進行。這表示將會把呼叫 JavaScript 回呼的那些值放入佇列中,而且會針對佇列中的每個值,最終呼叫 JavaScript 函數。
在建立 napi_threadsafe_function
時,可以提供 napi_finalize
回呼。當執行緒安全函式即將被銷毀時,此回呼會在主執行緒中被呼叫。它會接收在建構期間提供的內容和最終化資料,並提供一個機會來清理執行緒,例如呼叫 uv_thread_join()
。除了主迴圈執行緒外,在最終化回呼完成後,不應有任何執行緒使用執行緒安全函式。
在呼叫 napi_create_threadsafe_function()
期間提供的 context
可以透過呼叫 napi_get_threadsafe_function_context()
從任何執行緒中擷取。
呼叫執行緒安全函式#
napi_call_threadsafe_function()
可用於啟動呼叫 JavaScript。napi_call_threadsafe_function()
接受一個參數,用於控制 API 是否以封鎖方式運作。如果設定為 napi_tsfn_nonblocking
,API 會以非封鎖方式運作,如果佇列已滿,則傳回 napi_queue_full
,防止資料成功加入佇列。如果設定為 napi_tsfn_blocking
,API 會封鎖,直到佇列中出現可用空間。如果執行緒安全函式建立時的最大佇列大小為 0,則 napi_call_threadsafe_function()
永遠不會封鎖。
不應從 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。
回呼也可以在 env
和 call_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_function
的 initial_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_function
和 napi_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
值為undefined
。napi_threadsafe_function_call_js
提供更多詳細資料。[out] result
:非同步執行緒安全 JavaScript 函式。
變更記錄
-
實驗性質(已定義
NAPI_EXPERIMENTAL
)call_js_cb
中引發的未捕捉例外狀況會以'uncaughtException'
事件處理,而不是略過。
napi_get_threadsafe_function_context
#
NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
void** result);
[in] func
:要擷取其內容的執行緒安全函式。[out] result
:儲存內容的位置。
此 API 可以從使用 func
的任何執行緒呼叫。
napi_call_threadsafe_function
#
NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking);
[in] func
:要呼叫的非同步執行緒安全 JavaScript 函式。[in] data
:在建立執行緒安全 JavaScript 函式的過程中,透過提供的回呼call_js_cb
傳送至 JavaScript 的資料。[in] is_blocking
:旗標,其值可以是napi_tsfn_blocking
(表示佇列已滿時呼叫應封鎖)或napi_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_function
和 napi_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
可能為空字串。