- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
Node.js v24.13.0 文档
- Node.js v24.13.0
-
目录
- Node-API
- 使用各种编程语言编写插件
- ABI 稳定性的影响
- 构建
- 使用方法
- Node-API 版本矩阵
- 环境生命周期 API
- 基本的 Node-API 数据类型
- 错误处理
- 对象生命周期管理
- 模块注册
- 使用 JavaScript 值
- 枚举类型
- 对象创建函数
napi_create_arraynapi_create_array_with_lengthnapi_create_arraybuffernapi_create_buffernapi_create_buffer_copynapi_create_datenapi_create_externalnapi_create_external_arraybuffernapi_create_external_buffernapi_create_objectnapi_create_object_with_propertiesnapi_create_symbolnode_api_symbol_fornapi_create_typedarraynode_api_create_buffer_from_arraybuffernapi_create_dataview
- 从 C 类型转换为 Node-API 的函数
napi_create_int32napi_create_uint32napi_create_int64napi_create_doublenapi_create_bigint_int64napi_create_bigint_uint64napi_create_bigint_wordsnapi_create_string_latin1node_api_create_external_string_latin1napi_create_string_utf16node_api_create_external_string_utf16napi_create_string_utf8
- 用于创建优化属性键的函数
- 从 Node-API 转换为 C 类型的函数
napi_get_array_lengthnapi_get_arraybuffer_infonapi_get_buffer_infonapi_get_prototypenapi_get_typedarray_infonapi_get_dataview_infonapi_get_date_valuenapi_get_value_boolnapi_get_value_doublenapi_get_value_bigint_int64napi_get_value_bigint_uint64napi_get_value_bigint_wordsnapi_get_value_externalnapi_get_value_int32napi_get_value_int64napi_get_value_string_latin1napi_get_value_string_utf8napi_get_value_string_utf16napi_get_value_uint32
- 获取全局实例的函数
- 使用 JavaScript 值和抽象操作
napi_coerce_to_boolnapi_coerce_to_numbernapi_coerce_to_objectnapi_coerce_to_stringnapi_typeofnapi_instanceofnapi_is_arraynapi_is_arraybuffernapi_is_buffernapi_is_datenapi_is_errornapi_is_typedarraynapi_is_dataviewnapi_strict_equalsnapi_detach_arraybuffernapi_is_detached_arraybuffernode_api_is_sharedarraybuffernode_api_create_sharedarraybuffer
- 使用 JavaScript 属性
- 结构
- 函数
napi_get_property_namesnapi_get_all_property_namesnapi_set_propertynapi_get_propertynapi_has_propertynapi_delete_propertynapi_has_own_propertynapi_set_named_propertynapi_get_named_propertynapi_has_named_propertynapi_set_elementnapi_get_elementnapi_has_elementnapi_delete_elementnapi_define_propertiesnapi_object_freezenapi_object_seal
- 使用 JavaScript 函数
- 对象封装
- 简单的异步操作
- 自定义异步操作
- 版本管理
- 内存管理
- Promise
- 脚本执行
- libuv 事件循环
- 异步线程安全函数调用
- 其他实用工具
- Node-API
-
导航
- assert 断言
- async_hooks 异步钩子
- async_hooks/context 异步上下文
- buffer 缓冲区
- C++插件
- C/C++插件(使用 Node-API)
- C++嵌入器
- child_process 子进程
- cluster 集群
- CLI 命令行
- console 控制台
- crypto 加密
- crypto/webcrypto 网络加密
- debugger 调试器
- deprecation 弃用
- dgram 数据报
- diagnostics_channel 诊断通道
- dns 域名服务器
- domain 域
- Error 错误
- events 事件触发器
- fs 文件系统
- global 全局变量
- http 超文本传输协议
- http2 超文本传输协议 2.0
- https 安全超文本传输协议
- inspector 检查器
- Intl 国际化
- module 模块
- module/cjs CommonJS 模块
- module/esm ECMAScript 模块
- module/package 包模块
- module/typescript TS 模块
- net 网络
- os 操作系统
- path 路径
- perf_hooks 性能钩子
- permission 权限
- process 进程
- punycode 域名代码
- querystring 查询字符串
- readline 逐行读取
- repl 交互式解释器
- report 诊断报告
- sea 单个可执行应用程序
- 其他版本
Node-API#>
Node-API(前称 N-API)是用于构建原生插件的 API。它独立于底层 JavaScript 运行时(例如 V8),并作为 Node.js 的一部分进行维护。该 API 在 Node.js 的各个版本之间将保持应用二进制接口(ABI)稳定。其目的是将插件与底层 JavaScript 引擎的变化隔离开来,并允许为一个主要版本编译的模块在 Node.js 的后续主要版本上运行,而无需重新编译。ABI 稳定性 指南提供了更深入的说明。
【Node-API (formerly N-API) is an API for building native Addons. It is independent from the underlying JavaScript runtime (for example, V8) and is maintained as part of Node.js itself. This API will be Application Binary Interface (ABI) stable across versions of Node.js. It is intended to insulate addons from changes in the underlying JavaScript engine and allow modules compiled for one major version to run on later major versions of Node.js without recompilation. The ABI Stability guide provides a more in-depth explanation.】
插件的构建/打包采用了在标题为 C++ 插件 的部分中概述的相同方法/工具。唯一的区别在于本地代码使用的 API 集。Node-API 中可用的函数取代了 V8 或 Node.js 的原生抽象 API。
【Addons are built/packaged with the same approach/tools outlined in the section titled C++ Addons. The only difference is the set of APIs that are used by the native code. Instead of using the V8 or Native Abstractions for Node.js APIs, the functions available in Node-API are used.】
Node-API 暴露的 API 通常用于创建和操作 JavaScript 值。其概念和操作通常对应于 ECMA-262 语言规范中指定的思想。这些 API 具有以下特性:
【APIs exposed by Node-API are generally used to create and manipulate JavaScript values. Concepts and operations generally map to ideas specified in the ECMA-262 Language Specification. The APIs have the following properties:】
- 所有 Node-API 调用都会返回类型为
napi_status的状态码。该状态码表示 API 调用是成功还是失败。 - API 的返回值通过输出参数传递。
- 所有 JavaScript 值都被抽象为一个名为
napi_value的不透明类型。 - 在出现错误状态码时,可以使用
napi_get_last_error_info获取更多信息。更多信息可以在错误处理部分 错误处理 中找到。
使用各种编程语言编写插件#>
【Writing addons in various programming languages】
Node-API 是一个 C 语言 API,它确保在不同的 Node.js 版本和不同的编译器级别之间的 ABI 稳定性。有了这种稳定性保证,就可以在 Node-API 上用其他编程语言编写插件。有关更多编程语言和引擎支持的详细信息,请参阅 语言和引擎绑定。
【Node-API is a C API that ensures ABI stability across Node.js versions and different compiler levels. With this stability guarantee, it is possible to write addons in other programming languages on top of Node-API. Refer to language and engine bindings for more programming languages and engines support details.】
node-addon-api 是官方的 C++ 绑定,它提供了一种更高效的方式来编写调用 Node-API 的 C++ 代码。这个封装是一个仅包含头文件的库,提供了可内联的 C++ API。使用 node-addon-api 构建的二进制文件将依赖 Node.js 导出的基于 C 的 Node-API 函数符号。下面的代码示例展示了 node-addon-api 的用法:
Object obj = Object::New(env);
obj["foo"] = String::New(env, "bar");
上述 node-addon-api C++ 代码相当于以下基于 C 的 Node-API 代码:
【The above node-addon-api C++ code is equivalent to the following C-based
Node-API code:】
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++ 编写的,它仍然能够享受由 C Node-API 提供的 ABI 稳定性带来的好处。
【The end result is that the addon only uses the exported C APIs. Even though the addon is written in C++, it still gets the benefits of the ABI stability provided by the C Node-API.】
在使用 node-addon-api 而不是 C API 时,首先使用 node-addon-api 的 API 文档。
【When using node-addon-api instead of the C APIs, start with the API docs
for node-addon-api.】
Node-API 资源 为刚开始使用 Node-API 和 node-addon-api 的开发者提供了出色的入门指导和建议。更多的媒体资源可以在 Node-API 媒体 页面找到。
【The Node-API Resource offers
an excellent orientation and tips for developers just getting started with
Node-API and node-addon-api. Additional media resources can be found on the
Node-API Media page.】
ABI 稳定性的影响#>
【Implications of ABI stability】
尽管 Node-API 提供 ABI 稳定性保证,但 Node.js 的其他部分并不保证,且从插件使用的任何外部库也可能没有保证。尤其是,以下任何 API 在主要版本之间都不提供 ABI 稳定性保证:
【Although Node-API provides an ABI stability guarantee, other parts of Node.js do not, and any external libraries used from the addon may not. In particular, none of the following APIs provide an ABI stability guarantee across major versions:】
-
通过任何以下途径可用的 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,并限制自己使用
【Thus, for an addon to remain ABI-compatible across Node.js major versions, it must use Node-API exclusively by restricting itself to using】
#include <node_api.h>
并且通过检查它使用的所有外部库,确保这些外部库提供类似于 Node-API 的 ABI 稳定性保证。
【and by checking, for all external libraries that it uses, that the external library makes ABI stability guarantees similar to Node-API.】
ABI 稳定性中的枚举值#>
【Enum values in ABI stability】
在 Node-API 中定义的所有枚举数据类型都应视为固定大小的 int32_t 值。位标志枚举类型应明确记录,并且它们可以像位值一样与位运算符(如按位或 |)一起使用。除非另有说明,否则枚举类型应视为可扩展的。
【All enum data types defined in Node-API should be considered as a fixed size
int32_t value. Bit flag enum types should be explicitly documented, and they
work with bit operators like bit-OR (|) as a bit value. Unless otherwise
documented, an enum type should be considered to be extensible.】
一个新的枚举值将被添加到枚举定义的末尾。枚举值不会被删除或重命名。
【A new enum value will be added at the end of the enum definition. An enum value will not be removed or renamed.】
对于从 Node-API 函数返回的枚举类型,或作为 Node-API 函数的输出参数提供的枚举类型,其值为整数值,插件应处理未知值。可以在不使用版本保护的情况下引入新值。例如,在 switch 语句中检查 napi_status 时,插件应包含默认分支,因为在较新的 Node.js 版本中可能会引入新的状态码。
【For an enum type returned from a Node-API function, or provided as an out
parameter of a Node-API function, the value is an integer value and an addon
should handle unknown values. New values are allowed to be introduced without
a version guard. For example, when checking napi_status in switch statements,
an addon should include a default branch, as new status codes may be introduced
in newer Node.js versions.】
对于在输入参数中使用的枚举类型,将未知整数值传递给 Node-API 函数的结果是未定义的,除非另有文档说明。新增的值会附带版本保护,以指示它被引入的 Node-API 版本。例如,napi_get_all_property_names 可以通过新增 napi_key_filter 枚举值来扩展。
【For an enum type used in an in-parameter, the result of passing an unknown
integer value to Node-API functions is undefined unless otherwise documented.
A new value is added with a version guard to indicate the Node-API version in
which it was introduced. For example, napi_get_all_property_names can be
extended with new enum value of napi_key_filter.】
对于同时用于输入参数和输出参数的枚举类型,允许在不使用版本保护的情况下引入新值。
【For an enum type used in both in-parameters and out-parameters, new values are allowed to be introduced without a version guard.】
构建#>
【Building】
与使用 JavaScript 编写的模块不同,使用 Node-API 开发和部署 Node.js 原生插件需要额外的一套工具。除了开发 Node.js 所需的基本工具外,原生插件开发者还需要一套能够将 C 和 C++ 代码编译为二进制文件的工具链。此外,根据原生插件的部署方式,原生插件的用户也可能需要安装 C/C++ 工具链。
【Unlike modules written in JavaScript, developing and deploying Node.js native addons using Node-API requires an additional set of tools. Besides the basic tools required to develop for Node.js, the native addon developer requires a toolchain that can compile C and C++ code into a binary. In addition, depending upon how the native addon is deployed, the user of the native addon will also need to have a C/C++ toolchain installed.】
对于 Linux 开发者来说,所需的 C/C++ 工具链包很容易获取。海湾阿拉伯国家合作委员会 在 Node.js 社区中被广泛用于在各种平台上构建和测试。对于许多开发者来说,LLVM 编译器基础设施也是一个不错的选择。
【For Linux developers, the necessary C/C++ toolchain packages are readily available. GCC is widely used in the Node.js community to build and test across a variety of platforms. For many developers, the LLVM compiler infrastructure is also a good choice.】
对于 Mac 开发者,Xcode 提供了所有所需的编译器工具。然而,并不需要安装完整的 Xcode IDE。以下命令会安装所需的工具链:
【For Mac developers, Xcode offers all the required compiler tools. However, it is not necessary to install the entire Xcode IDE. The following command installs the necessary toolchain:】
xcode-select --install
对于 Windows 开发者,Visual Studio 提供了所有必需的编译工具。然而,并不需要安装完整的 Visual Studio IDE。以下命令会安装所需的工具链:
【For Windows developers, Visual Studio offers all the required compiler tools. However, it is not necessary to install the entire Visual Studio IDE. The following command installs the necessary toolchain:】
npm install --global windows-build-tools
下面的各节描述了用于开发和部署 Node.js 原生插件的额外工具。
【The sections below describe the additional tools available for developing and deploying Node.js native addons.】
构建工具#>
【Build tools】
此处列出的两种工具都要求本地插件的 用户 安装 C/C++ 工具链,才能成功安装本地插件。
【Both the tools listed here require that users of the native addon have a C/C++ toolchain installed in order to successfully install the native addon.】
node-gyp#>
node-gyp 是一个基于 Google 的 欺骗 工具的 gyp-next 分支的构建系统,并随 npm 一起提供。GYP,因此 node-gyp,需要安装 Python。
历史上,node-gyp 一直是构建本地插件的首选工具。它被广泛采用并且有完整的文档。然而,一些开发者在使用 node-gyp 时遇到了一些限制。
【Historically, node-gyp has been the tool of choice for building native addons. It has widespread adoption and documentation. However, some developers have run into limitations in node-gyp.】
CMake.js#>
CMake.js 是一个适合已经使用 CMake 的项目或受 node-gyp 限制影响的开发者的好选择。build_with_cmake 是一个基于 CMake 的本地插件项目的示例。
【CMake.js is a good choice for projects that already use CMake or for
developers affected by limitations in node-gyp. build_with_cmake is an
example of a CMake-based native addon project.】
上传预编译的二进制文件#>
【Uploading precompiled binaries】
这里列出的三个工具允许本地插件开发者和维护者创建并上传二进制文件到公共或私有服务器。这些工具通常与 CI/CD 构建系统(如 Travis CI 和 AppVeyor)集成,用于为各种平台和架构构建和上传二进制文件。然后,这些二进制文件可供没有安装 C/C++ 工具链的用户下载使用。
【The three tools listed here permit native addon developers and maintainers to create and upload binaries to public or private servers. These tools are typically integrated with CI/CD build systems like Travis CI and AppVeyor to build and upload binaries for a variety of platforms and architectures. These binaries are then available for download by users who do not need to have a C/C++ toolchain installed.】
node-pre-gyp#>
node-pre-gyp 是一个基于 node-gyp 的工具,它增加了将二进制文件上传到开发者选择的服务器的能力。node-pre-gyp 在将二进制文件上传到 Amazon S3 方面有特别好的支持。
预构建#>
【prebuild】
预构建 是一个支持使用 node-gyp 或 CMake.js 进行构建的工具。与支持多种服务器的 node-pre-gyp 不同,prebuild 仅将二进制文件上传到 GitHub 发行版。对于使用 CMake.js 的 GitHub 项目,prebuild 是一个不错的选择。
预构建化#>
【prebuildify】
预构建化 是一个基于 node-gyp 的工具。prebuildify 的优势在于,当原生插件上传到 npm 时,构建好的二进制文件会与原生插件打包在一起。这些二进制文件可以从 npm 下载,并且在安装原生插件时,模块用户可以立即使用。
使用方法#>
【Usage】
为了使用 Node-API 函数,请包含位于节点开发树 src 目录中的文件 node_api.h:
【In order to use the Node-API functions, include the file node_api.h which
is located in the src directory in the node development tree:】
#include <node_api.h>
这将选择使用给定版本 Node.js 的默认 NAPI_VERSION。为了确保与特定版本的 Node-API 兼容,可以在包含头文件时显式指定版本:
【This will opt into the default NAPI_VERSION for the given release of Node.js.
In order to ensure compatibility with specific versions of Node-API, the version
can be specified explicitly when including the header:】
#define NAPI_VERSION 3
#include <node_api.h>
这将 Node-API 的接口限制在指定版本(及更早版本)中可用的功能范围内。
【This restricts the Node-API surface to just the functionality that was available in the specified (and earlier) versions.】
一些 Node-API 表面是实验性的,需要明确选择加入:
【Some of the Node-API surface is experimental and requires explicit opt-in:】
#define NAPI_EXPERIMENTAL
#include <node_api.h>
在这种情况下,整个 API 接口,包括任何实验性 API,都将对模块代码可用。
【In this case the entire API surface, including any experimental APIs, will be available to the module code.】
有时会引入影响已发布和稳定 API 的实验性功能。这些功能可以通过选择不使用来禁用:
【Occasionally, experimental features are introduced that affect already-released and stable APIs. These features can be disabled by an opt-out:】
#define NAPI_EXPERIMENTAL
#define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT
#include <node_api.h>
其中 <FEATURE_NAME> 是一个影响实验性和稳定性 API 的实验性功能的名称。
【where <FEATURE_NAME> is the name of an experimental feature that affects both
experimental and stable APIs.】
Node-API 版本矩阵#>
【Node-API version matrix】
直到版本 9,Node-API 版本是累加的,并且独立于 Node.js 进行版本控制。这意味着任何版本都是对前一个版本的扩展,它包含了前一个版本的所有 API,并增加了一些新的 API。每个 Node.js 版本只支持一个 Node-API 版本。例如,v18.15.0 只支持 Node-API 版本 8。ABI 稳定性得以实现是因为版本 8 是所有先前版本的严格超集。
【Up until version 9, Node-API versions were additive and versioned independently from Node.js. This meant that any version was an extension to the previous version in that it had all of the APIs from the previous version with some additions. Each Node.js version only supported a single Node-API version. For example v18.15.0 supports only Node-API version 8. ABI stability was achieved because 8 was a strict superset of all previous versions.】
从版本 9 开始,虽然 Node-API 版本仍然独立版本化,但使用 Node-API 版本 9 的插件在升级到 Node-API 版本 10 时可能需要更新代码。然而,ABI 稳定性得以维持,因为支持高于 8 版本 Node-API 的 Node.js 版本,将支持从 8 到它们支持的最高版本之间的所有版本,并且默认提供版本 8 的 API,除非插件选择使用更高版本的 Node-API。这种方法在保持 ABI 稳定性的同时,也提供了更好地优化现有 Node-API 功能的灵活性。现有插件可以继续使用早期版本的 Node-API 运行而无需重新编译。如果插件需要使用更新版本 Node-API 的新功能,那么无论如何都需要修改现有代码并重新编译以使用这些新功能。
【As of version 9, while Node-API versions continue to be versioned independently, an add-on that ran with Node-API version 9 may need code updates to run with Node-API version 10. ABI stability is maintained, however, because Node.js versions that support Node-API versions higher than 8 will support all versions between 8 and the highest version they support and will default to providing the version 8 APIs unless an add-on opts into a higher Node-API version. This approach provides the flexibility of better optimizing existing Node-API functions while maintaining ABI stability. Existing add-ons can continue to run without recompilation using an earlier version of Node-API. If an add-on needs functionality from a newer Node-API version, changes to existing code and recompilation will be needed to use those new functions anyway.】
在支持 Node-API 版本 9 及更高版本的 Node.js 中,定义 NAPI_VERSION=X 并使用现有的插件初始化宏,将会将运行时使用的请求 Node-API 版本编译到插件中。如果未设置 NAPI_VERSION,则默认值为 8。
【In versions of Node.js that support Node-API version 9 and later, defining
NAPI_VERSION=X and using the existing add-on initialization macros
will bake in the requested Node-API version that will be used at runtime
into the add-on. If NAPI_VERSION is not set it will default to 8.】
在较旧的版本中,此表可能不是最新的,最新的信息请参阅最新的 API 文档: Node-API 版本矩阵
【This table may not be up to date in older streams, the most up to date information is in the latest API documentation in: Node-API version matrix】
| Node-API 版本 | 支持 |
|---|---|
| 10 | v22.14.0+、23.6.0+ 及所有后续版本 |
| 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 和所有后续版本 |
| 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 以及所有后续版本 | |
| 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。在 Node.js 8.6.0 之前的版本中,API 是不同的。我们推荐使用 Node-API 版本 3 或更高版本。
每个为 Node-API 记录的 API 都会有一个名为 added in: 的标题,而稳定的 API 会额外有一个 Node-API version: 的标题。使用支持 Node-API version: 所示版本或更高版本的 Node.js 时,API 可以直接使用。如果使用的 Node.js 版本不支持所列的 Node-API version:,或者没有列出 Node-API version:,那么该 API 只有在 #define NAPI_EXPERIMENTAL 出现在包含 node_api.h 或 js_native_api.h 之前时才能使用。如果某个 API 在 Node.js 的某个版本中似乎不可用,而该版本比 added in: 中显示的时间晚,那么这很可能是造成表面上缺失的原因。
【Each API documented for Node-API will have a header named added in:, and APIs
which are stable will have the additional header Node-API version:.
APIs are directly usable when using a Node.js version which supports
the Node-API version shown in Node-API version: or higher.
When using a Node.js version that does not support the
Node-API version: listed or if there is no Node-API version: listed,
then the API will only be available if
#define NAPI_EXPERIMENTAL precedes the inclusion of node_api.h
or js_native_api.h. If an API appears not to be available on
a version of Node.js which is later than the one shown in added in: then
this is most likely the reason for the apparent absence.】
严格与从本地代码访问 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 可能不适用。
【The Node-APIs associated strictly with accessing ECMAScript features from native
code can be found separately in js_native_api.h and js_native_api_types.h.
The APIs defined in these headers are included in node_api.h and
node_api_types.h. The headers are structured in this way in order to allow
implementations of Node-API outside of Node.js. For those implementations the
Node.js specific APIs may not be applicable.】
插件中针对 Node.js 的特定部分可以与将实际功能暴露给 JavaScript 环境的代码分离,以便后者可以与 Node-API 的多个实现一起使用。在下面的示例中,addon.c 和 addon.h 仅引用 js_native_api.h。这确保了 addon.c 可以重复使用,以便针对 Node.js 的 Node-API 实现或 Node.js 之外的任何 Node-API 实现进行编译。
【The Node.js-specific parts of an addon can be separated from the code that
exposes the actual functionality to the JavaScript environment so that the
latter may be used with multiple implementations of Node-API. In the example
below, addon.c and addon.h refer only to js_native_api.h. This ensures
that addon.c can be reused to compile against either the Node.js
implementation of Node-API or any implementation of Node-API outside of Node.js.】
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#>
【Environment life cycle APIs】
ECMAScript 语言规范 的 代理部分 将“代理”的概念定义为一个独立的环境,在其中运行 JavaScript 代码。多个这样的代理可以由进程同时或按顺序启动和终止。
Node.js 环境对应于 ECMAScript 代理。在主进程中,环境在启动时被创建,并且可以在单独的线程上创建额外的环境以作为 工作线程。当 Node.js 被嵌入到其他应用中时,应用的主线程在应用进程的生命周期内可能会多次构建和销毁 Node.js 环境,因此应用创建的每个 Node.js 环境在其生命周期内也可能创建和销毁额外的环境作为工作线程。
【A Node.js environment corresponds to an ECMAScript Agent. In the main process, an environment is created at startup, and additional environments can be created on separate threads to serve as worker threads. When Node.js is embedded in another application, the main thread of the application may also construct and destroy a Node.js environment multiple times during the life cycle of the application process such that each Node.js environment created by the application may, in turn, during its life cycle create and destroy additional environments as worker threads.】
从本地插件的角度来看,这意味着它提供的绑定可能会被多次调用,来自多个上下文,甚至可能同时来自多个线程。
【From the perspective of a native addon this means that the bindings it provides may be called multiple times, from multiple contexts, and even concurrently from multiple threads.】
本地插件可能需要分配全局状态,以便在 Node.js 环境的生命周期中使用该状态,从而使每个插件实例的状态都是唯一的。
【Native addons may need to allocate global state which they use during their life cycle of an Node.js environment such that the state can be unique to each instance of the addon.】
为此,Node-API 提供了一种方式来关联数据,使其生命周期与 Node.js 环境的生命周期相关联。
【To this end, Node-API provides a way to associate data such that its life cycle is tied to the life cycle of a Node.js environment.】
napi_set_instance_data#>
napi_status napi_set_instance_data(node_api_basic_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint);
[in] env:调用 Node-API 时所处的环境。[in] data:要提供给此实例绑定的数据项。[in] finalize_cb:当环境被拆除时要调用的函数。该函数接收data,以便可能释放它。napi_finalize提供了更多详细信息。[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 将 data 与当前运行的 Node.js 环境关联。之后可以使用 napi_get_instance_data() 来检索 data。任何通过之前调用 napi_set_instance_data() 设置的、与当前运行的 Node.js 环境关联的现有数据将被覆盖。如果之前的调用提供了 finalize_cb,该回调将不会被调用。
【This API associates data with the currently running Node.js environment. data
can later be retrieved using napi_get_instance_data(). Any existing data
associated with the currently running Node.js environment which was set by means
of a previous call to napi_set_instance_data() will be overwritten. If a
finalize_cb was provided by the previous call, it will not be called.】
napi_get_instance_data#>
napi_status napi_get_instance_data(node_api_basic_env env,
void** data);
[in] env:调用 Node-API 时所处的环境。[out] 数据:之前通过调用napi_set_instance_data()与当前正在运行的 Node.js 环境关联的数据项。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该 API 检索先前通过 napi_set_instance_data() 与当前运行的 Node.js 环境关联的数据。如果未设置任何数据,调用将成功,并且 data 将被设置为 NULL。
【This API retrieves data that was previously associated with the currently
running Node.js environment via napi_set_instance_data(). If no data is set,
the call will succeed and data will be set to NULL.】
基本的 Node-API 数据类型#>
【Basic Node-API data types】
Node-API 将以下基本数据类型作为抽象暴露出来,供各种 API 使用。这些 API 应被视为不透明的,只能通过其他 Node-API 调用进行检查。
【Node-API exposes the following fundamental data types as abstractions that are consumed by the various APIs. These APIs should be treated as opaque, introspectable only with other Node-API calls.】
napi_status#>
表示 Node-API 调用成功或失败的整数状态码。目前支持以下状态码。
【Integral status code indicating the success or failure of a Node-API call. Currently, the following status codes are supported.】
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 来获取。
【If additional information is required upon an API returning a failed status,
it can be obtained by calling 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:保留用于虚拟机特定的错误详情。目前此功能尚未在任何虚拟机中实现。engine_error_code:特定于虚拟机的错误代码。目前尚未针对任何虚拟机实现此功能。error_code:与上一次错误相关的 Node-API 状态码。
有关更多信息,请参阅 错误处理 部分。
【See the Error handling section for additional information.】
napi_env#>
napi_env 用于表示一个上下文,底层的 Node-API 实现可以使用它来持久化特定于虚拟机的状态。当调用本地函数时,这个结构会被传入,并且在进行 Node-API 调用时必须传回。具体来说,在最初调用本地函数时传入的同一个 napi_env 必须传递给任何随后的嵌套 Node-API 调用。不允许为了通用重用而缓存 napi_env,也不允许在不同 Worker 线程上运行的同一插件实例之间传递 napi_env。当本地插件实例被卸载时,napi_env 会失效。通过提供给 napi_add_env_cleanup_hook 和 napi_set_instance_data 的回调可以收到该事件的通知。
node_api_basic_env#>
这种 napi_env 的变体会传递给同步终结器 (node_api_basic_finalize)。Node-API 中有一部分 API 接受 node_api_basic_env 类型的参数作为它们的第一个参数。这些 API 不会访问 JavaScript 引擎的状态,因此可以安全地从同步终结器中调用。将 napi_env 类型的参数传递给这些 API 是允许的,但是将 node_api_basic_env 类型的参数传递给访问 JavaScript 引擎状态的 API 是不允许的。如果在没有强制类型转换的情况下尝试这样做,当使用会在传入错误指针类型时发出警告和/或错误的标志编译插件时,将会产生编译器警告或错误。从同步终结器中调用此类 API 最终会导致应用终止。
【This variant of napi_env is passed to synchronous finalizers
(node_api_basic_finalize). There is a subset of Node-APIs which accept
a parameter of type node_api_basic_env as their first argument. These APIs do
not access the state of the JavaScript engine and are thus safe to call from
synchronous finalizers. Passing a parameter of type napi_env to these APIs is
allowed, however, passing a parameter of type node_api_basic_env to APIs that
access the JavaScript engine state is not allowed. Attempting to do so without
a cast will produce a compiler warning or an error when add-ons are compiled
with flags which cause them to emit warnings and/or errors when incorrect
pointer types are passed into a function. Calling such APIs from a synchronous
finalizer will ultimately result in the termination of the application.】
napi_value#>
这是一个用于表示 JavaScript 值的不透明指针。
【This is an opaque pointer that is used to represent a JavaScript value.】
napi_threadsafe_function#>
这是一个不透明指针,表示一个 JavaScript 函数,可以通过 napi_call_threadsafe_function() 从多个线程异步调用。
【This is an opaque pointer that represents a JavaScript function which can be
called asynchronously from multiple threads via
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() 进行后续使用。
【A value to be given to napi_release_threadsafe_function() to indicate whether
the thread-safe function is to be closed immediately (napi_tsfn_abort) or
merely released (napi_tsfn_release) and thus available for subsequent use via
napi_acquire_threadsafe_function() and 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() 的一个值,用于指示当与线程安全函数关联的队列已满时调用是否应阻塞。
【A value to be given to napi_call_threadsafe_function() to indicate whether
the call should block whenever the queue associated with the thread-safe
function is full.】
typedef enum {
napi_tsfn_nonblocking,
napi_tsfn_blocking
} napi_threadsafe_function_call_mode;
Node-API 内存管理类型#>
【Node-API memory management types】
napi_handle_scope#>
这是一个用于控制和修改在特定作用域内创建的对象生命周期的抽象。通常,Node-API 值是在句柄作用域的上下文中创建的。当从 JavaScript 调用本地方法时,将存在一个默认的句柄作用域。如果用户没有显式地创建新的句柄作用域,Node-API 值将会在默认句柄作用域中创建。对于在本地方法执行之外的任何代码调用(例如,在 libuv 回调调用期间),模块在调用任何可能导致创建 JavaScript 值的函数之前,都必须创建一个作用域。
【This is an abstraction used to control and modify the lifetime of objects created within a particular scope. In general, Node-API values are created within the context of a handle scope. When a native method is called from JavaScript, a default handle scope will exist. If the user does not explicitly create a new handle scope, Node-API values will be created in the default handle scope. For any invocations of code outside the execution of a native method (for instance, during a libuv callback invocation), the module is required to create a scope before invoking any functions that can result in the creation of JavaScript values.】
句柄作用域是使用 napi_open_handle_scope 创建的,并通过 napi_close_handle_scope 销毁。关闭作用域可以向垃圾回收器(GC)表明,在句柄作用域生命周期内创建的所有 napi_value 不再被当前调用栈引用。
【Handle scopes are created using napi_open_handle_scope and are destroyed
using napi_close_handle_scope. Closing the scope can indicate to the GC
that all napi_values created during the lifetime of the handle scope are no
longer referenced from the current stack frame.】
如需更多详情,请查阅 对象生命周期管理。
【For more details, review the Object lifetime management.】
napi_escapable_handle_scope#>
可逃逸句柄作用域是一种特殊类型的句柄作用域,用于将特定句柄作用域内创建的值返回到父作用域。
【Escapable handle scopes are a special type of handle scope to return values created within a particular handle scope to a parent scope.】
napi_ref#>
这是用于引用 napi_value 的抽象。这允许用户管理 JavaScript 值的生命周期,包括显式定义它们的最短生命周期。
【This is the abstraction to use to reference a napi_value. This allows for
users to manage the lifetimes of JavaScript values, including defining their
minimum lifetimes explicitly.】
如需更多详情,请查阅 对象生命周期管理。
【For more details, review the Object lifetime management.】
napi_type_tag#>
一个以两个无符号64位整数存储的128位值。它用作UUID,可以对JavaScript对象或外部进行“标记”,以确保它们属于某种特定类型。这比napi_instanceof的检查更严格,因为如果对象的原型已被修改,后者可能会报告假阳性。类型标记在与napi_wrap结合使用时最为有用,因为它确保从封装对象中检索的指针可以安全地转换为与之前应用于该JavaScript对象的类型标记对应的本地类型。
【A 128-bit value stored as two unsigned 64-bit integers. It serves as a UUID
with which JavaScript objects or externals can be "tagged" in order to
ensure that they are of a certain type. This is a stronger check than
napi_instanceof, because the latter can report a false positive if the
object's prototype has been manipulated. Type-tagging is most useful in
conjunction with napi_wrap because it ensures that the pointer retrieved
from a wrapped object can be safely cast to the native type corresponding to the
type tag that had been previously applied to the JavaScript object.】
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。
【An opaque value returned by napi_add_async_cleanup_hook. It must be passed
to napi_remove_async_cleanup_hook when the chain of asynchronous cleanup
events completes.】
Node-API 回调类型#>
【Node-API callback types】
napi_callback_info#>
传递给回调函数的不透明数据类型。它可用于获取关于调用回调时上下文的更多信息。
【Opaque datatype that is passed to a callback function. It can be used for getting additional information about the context in which the callback was invoked.】
napi_callback#>
用于用户提供的本地函数的函数指针类型,这些函数将通过 Node-API 暴露给 JavaScript。回调函数应满足以下签名:
【Function pointer type for user-provided native functions which are to be exposed to JavaScript via Node-API. Callback functions should satisfy the following signature:】
typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
除非出于 对象生命周期管理 中讨论的原因,在 napi_callback 内创建 handle 和/或回调作用域通常是不必要的。
【Unless for reasons discussed in Object Lifetime Management, creating a
handle and/or callback scope inside a napi_callback is not necessary.】
node_api_basic_finalize#>
用于附加功能的函数指针类型,当外部拥有的数据准备好被清理时,用户可以收到通知,因为与其相关联的对象已经被垃圾回收。用户必须提供一个满足以下签名的函数,当对象被回收时该函数会被调用。目前,可以使用 node_api_basic_finalize 来了解具有外部数据的对象何时被收集。
【Function pointer type for add-on provided functions that allow the user to be
notified when externally-owned data is ready to be cleaned up because the
object it was associated with has been garbage-collected. The user must provide
a function satisfying the following signature which would get called upon the
object's collection. Currently, node_api_basic_finalize can be used for
finding out when objects that have external data are collected.】
typedef void (*node_api_basic_finalize)(node_api_basic_env env,
void* finalize_data,
void* finalize_hint);
除非出于 对象生命周期管理 中讨论的原因,否则在函数体内创建 handle 和/或回调作用域并非必要。
【Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.】
由于这些函数可能在 JavaScript 引擎处于无法执行 JavaScript 代码的状态时被调用,因此只能调用将 node_api_basic_env 作为第一个参数的 Node-API。node_api_post_finalizer 可用于安排需要访问 JavaScript 引擎状态的 Node-API 调用,以便在当前垃圾回收周期完成后运行。
【Since these functions may be called while the JavaScript engine is in a state
where it cannot execute JavaScript code, only Node-APIs which accept a
node_api_basic_env as their first parameter may be called.
node_api_post_finalizer can be used to schedule Node-API calls that
require access to the JavaScript engine's state to run after the current
garbage collection cycle has completed.】
在 node_api_create_external_string_latin1 和 node_api_create_external_string_utf16 的情况下,env 参数可能为 null,因为外部字符串可能会在环境关闭的后期被收集。
【In the case of node_api_create_external_string_latin1 and
node_api_create_external_string_utf16 the env parameter may be null,
because external strings can be collected during the latter part of environment
shutdown.】
变更历史:
【Change History:】
-
实验性(
NAPI_EXPERIMENTAL):只有接受
node_api_basic_env作为第一个参数的 Node-API 调用可以被执行,否则应用将以适当的错误信息终止。通过定义NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT可以关闭此功能。
napi_finalize#>
用于附加组件提供的函数的函数指针类型,该函数允许用户在垃圾回收事件发生后、垃圾回收周期完成后,安排一组对 Node-API 的调用。这些函数指针可以与 node_api_post_finalizer 一起使用。
【Function pointer type for add-on provided function that allow the user to
schedule a group of calls to Node-APIs in response to a garbage collection
event, after the garbage collection cycle has completed. These function
pointers can be used with node_api_post_finalizer.】
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint);
变更历史:
【Change History:】
-
实验性(定义了
NAPI_EXPERIMENTAL):这种类型的函数不再可用作终结器,除非使用
node_api_post_finalizer。必须使用node_api_basic_finalize代替。通过定义NODE_API_EXPERIMENTAL_BASIC_ENV_OPT_OUT可以关闭此功能。
napi_async_execute_callback#>
函数指针用于支持异步操作的函数。回调函数必须满足以下签名:
【Function pointer used with functions that support asynchronous operations. Callback functions must satisfy the following signature:】
typedef void (*napi_async_execute_callback)(napi_env env, void* data);
该函数的实现必须避免调用执行 JavaScript 或与 JavaScript 对象交互的 Node-API。Node-API 调用应放在 napi_async_complete_callback 中。不要使用 napi_env 参数,因为这可能会导致执行 JavaScript。
【Implementations of this function must avoid making Node-API calls that execute
JavaScript or interact with JavaScript objects. Node-API calls should be in the
napi_async_complete_callback instead. Do not use the napi_env parameter as
it will likely result in execution of JavaScript.】
napi_async_complete_callback#>
函数指针用于支持异步操作的函数。回调函数必须满足以下签名:
【Function pointer used with functions that support asynchronous operations. Callback functions must satisfy the following signature:】
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data);
除非出于 对象生命周期管理 中讨论的原因,否则在函数体内创建 handle 和/或回调作用域并非必要。
【Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.】
napi_threadsafe_function_call_js#>
函数指针用于异步线程安全的函数调用。回调函数将在主线程上被调用。其目的是使用通过队列从某个辅助线程传来的数据项来构建调用 JavaScript 所需的参数,通常通过 napi_call_function,然后执行对 JavaScript 的调用。
【Function pointer used with asynchronous thread-safe function calls. The callback
will be called on the main thread. Its purpose is to use a data item arriving
via the queue from one of the secondary threads to construct the parameters
necessary for a call into JavaScript, usually via napi_call_function, and then
make the call into JavaScript.】
从次线程通过队列传来的数据在 data 参数中给出,要调用的 JavaScript 函数在 js_callback 参数中给出。
【The data arriving from the secondary thread via the queue is given in the data
parameter and the JavaScript function to call is given in the js_callback
parameter.】
Node-API 会在调用此回调之前设置好环境,因此通过 napi_call_function 调用 JavaScript 函数就足够了,而无需通过 napi_make_callback。
【Node-API sets up the environment prior to calling this callback, so it is
sufficient to call the JavaScript function via napi_call_function rather than
via napi_make_callback.】
回调函数必须满足以下签名:
【Callback functions must satisfy the following signature:】
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:由二级线程创建的数据。回调函数的责任是将这些本地数据转换为可以在调用js_callback时作为参数传递的 JavaScript 值(使用 Node-API 函数)。这个指针完全由线程和该回调函数管理。因此,该回调函数应释放这些数据。
除非出于 对象生命周期管理 中讨论的原因,否则在函数体内创建 handle 和/或回调作用域并非必要。
【Unless for reasons discussed in Object Lifetime Management, creating a handle and/or callback scope inside the function body is not necessary.】
napi_cleanup_hook#>
与 napi_add_env_cleanup_hook 一起使用的函数指针。它将在环境被拆除时被调用。
【Function pointer used with napi_add_env_cleanup_hook. It will be called
when the environment is being torn down.】
回调函数必须满足以下签名:
【Callback functions must satisfy the following signature:】
typedef void (*napi_cleanup_hook)(void* data);
[in] data:传递给napi_add_env_cleanup_hook的数据。
napi_async_cleanup_hook#>
与 napi_add_async_cleanup_hook 一起使用的函数指针。它将在环境被拆除时被调用。
【Function pointer used with napi_add_async_cleanup_hook. It will be called
when the environment is being torn down.】
回调函数必须满足以下签名:
【Callback functions must satisfy the following signature:】
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。
【The body of the function should initiate the asynchronous cleanup actions at the
end of which handle must be passed in a call to
napi_remove_async_cleanup_hook.】
错误处理#>
【Error handling】
Node-API 在错误处理方面既使用返回值,也使用 JavaScript 异常。以下各节将解释每种情况的处理方法。
【Node-API uses both return values and JavaScript exceptions for error handling. The following sections explain the approach for each case.】
返回值#>
【Return values】
所有的 Node-API 函数都遵循相同的错误处理模式。所有 API 函数的返回类型都是 napi_status。
【All of the Node-API functions share the same error handling pattern. The
return type of all API functions is napi_status.】
如果请求成功且未抛出未捕获的 JavaScript 异常,返回值将是 napi_ok。如果发生错误并且抛出了异常,将返回表示该错误的 napi_status 值。如果抛出了异常但没有发生错误,将返回 napi_pending_exception。
【The return value will be napi_ok if the request was successful and
no uncaught JavaScript exception was thrown. If an error occurred AND
an exception was thrown, the napi_status value for the error
will be returned. If an exception was thrown, and no error occurred,
napi_pending_exception will be returned.】
在返回值不是 napi_ok 或 napi_pending_exception 的情况下,必须调用 napi_is_exception_pending 来检查是否有待处理的异常。有关详细信息,请参阅异常部分。
【In cases where a return value other than napi_ok or
napi_pending_exception is returned, napi_is_exception_pending
must be called to check if an exception is pending.
See the section on exceptions for more details.】
napi_status 的所有可能值的完整集合定义在 napi_api_types.h 中。
【The full set of possible napi_status values is defined
in napi_api_types.h.】
napi_status 返回值提供了一个与虚拟机无关的错误表示。在某些情况下,获取更详细的信息是有用的,包括表示错误的字符串以及与虚拟机(引擎)相关的特定信息。
【The napi_status return value provides a VM-independent representation of
the error which occurred. In some cases it is useful to be able to get
more detailed information, including a string representing the error as well as
VM (engine)-specific information.】
为了检索此信息,提供了 napi_get_last_error_info,它会返回一个 napi_extended_error_info 结构体。napi_extended_error_info 结构体的格式如下:
【In order to retrieve this information napi_get_last_error_info
is provided which returns a napi_extended_error_info structure.
The format of the napi_extended_error_info structure is as follows:】
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:虚拟机特定的错误代码。error_code:上一个错误的 Node-API 状态码。
napi_get_last_error_info 返回上一次 Node-API 调用的信息。
不要依赖任何扩展信息的内容或格式,因为它不受语义化版本控制(SemVer)约束,可能随时发生变化。它仅用于记录目的。
【Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for logging purposes.】
napi_get_last_error_info#>
napi_status
napi_get_last_error_info(node_api_basic_env env,
const napi_extended_error_info** result);
[in] env:调用该 API 时所处的环境。[out] result:包含有关错误的更多信息的napi_extended_error_info结构。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会检索一个包含最近发生错误信息的 napi_extended_error_info 结构。
【This API retrieves a napi_extended_error_info structure with information
about the last error that occurred.】
napi_extended_error_info 返回的内容仅在对同一个 env 调用 Node-API 函数之前有效。这包括 napi_is_exception_pending 的调用,因此通常需要复制信息以便稍后使用。返回的 error_message 指针指向一个静态定义的字符串,因此,如果你在调用另一个 Node-API 函数之前已经将其从 error_message 字段中复制出来(该字段会被覆盖),使用该指针是安全的。
【The content of the napi_extended_error_info returned is only valid up until
a Node-API function is called on the same env. This includes a call to
napi_is_exception_pending so it may often be necessary to make a copy
of the information so that it can be used later. The pointer returned
in error_message points to a statically-defined string so it is safe to use
that pointer if you have copied it out of the error_message field (which will
be overwritten) before another Node-API function was called.】
不要依赖任何扩展信息的内容或格式,因为它不受语义化版本控制(SemVer)约束,可能随时发生变化。它仅用于记录目的。
【Do not rely on the content or format of any of the extended information as it is not subject to SemVer and may change at any time. It is intended only for logging purposes.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
异常#>
【Exceptions】
任何 Node-API 函数调用都可能导致挂起的 JavaScript 异常。对于任何 API 函数都是如此,即使是那些可能不会触发 JavaScript 执行的函数。
【Any Node-API function call may result in a pending JavaScript exception. This is the case for any of the API functions, even those that may not cause the execution of JavaScript.】
如果函数返回的 napi_status 为 napi_ok,则表示没有挂起的异常,也不需要采取其他操作。如果返回的 napi_status 不是 napi_ok 或 napi_pending_exception,为了尝试恢复并继续执行,而不是立即返回,必须调用 napi_is_exception_pending 来确定是否有异常挂起。
【If the napi_status returned by a function is napi_ok then no
exception is pending and no additional action is required. If the
napi_status returned is anything other than napi_ok or
napi_pending_exception, in order to try to recover and continue
instead of simply returning immediately, napi_is_exception_pending
must be called in order to determine if an exception is pending or not.】
在很多情况下,当调用 Node-API 函数且已存在未处理的异常时,该函数会立即返回 napi_status 为 napi_pending_exception。然而,并非所有函数都是这样。Node-API 允许调用其中一部分函数,以便在返回 JavaScript 之前进行一些最小的清理。在这种情况下,napi_status 会反映函数的执行状态,而不会反映之前未处理的异常。为了避免混淆,应在每次函数调用后检查错误状态。
【In many cases when a Node-API function is called and an exception is
already pending, the function will return immediately with a
napi_status of napi_pending_exception. However, this is not the case
for all functions. Node-API allows a subset of the functions to be
called to allow for some minimal cleanup before returning to JavaScript.
In that case, napi_status will reflect the status for the function. It
will not reflect previous pending exceptions. To avoid confusion, check
the error status after every function call.】
当异常悬而未决时,可以采用两种方法之一。
【When an exception is pending one of two approaches can be employed.】
第一种方法是进行任何适当的清理,然后返回,以便执行可以回到 JavaScript。作为回到 JavaScript 过渡的一部分,异常将在原生方法被调用的 JavaScript 代码处抛出。在异常挂起期间,大多数 Node-API 调用的行为是未定义的,很多调用会简单地返回 napi_pending_exception,因此应尽量少做操作,然后返回到 JavaScript 以处理异常。
【The first approach is to do any appropriate cleanup and then return so that
execution will return to JavaScript. As part of the transition back to
JavaScript, the exception will be thrown at the point in the JavaScript
code where the native method was invoked. The behavior of most Node-API calls
is unspecified while an exception is pending, and many will simply return
napi_pending_exception, so do as little as possible and then return to
JavaScript where the exception can be handled.】
第二种方法是尝试处理异常。会有一些情况,本地代码可以捕获异常,采取适当的措施,然后继续执行。这仅建议在特定情况下使用,即已知异常可以安全处理。在这些情况下,可以使用 napi_get_and_clear_last_exception 来获取并清除异常。成功时,result 将包含最近抛出的 JavaScript Object 的句柄。如果在获取异常后确定无法处理该异常,可以使用 napi_throw 重新抛出异常,其中 error 是要抛出的 JavaScript 值。
【The second approach is to try to handle the exception. There will be cases
where the native code can catch the exception, take the appropriate action,
and then continue. This is only recommended in specific cases
where it is known that the exception can be safely handled. In these
cases napi_get_and_clear_last_exception can be used to get and
clear the exception. On success, result will contain the handle to
the last JavaScript Object thrown. If it is determined, after
retrieving the exception, the exception cannot be handled after all
it can be re-thrown it with napi_throw where error is the
JavaScript value to be thrown.】
以下工具函数也可用,以防原生代码需要抛出异常或确定 napi_value 是否是 JavaScript Error 对象的实例:napi_throw_error、napi_throw_type_error、napi_throw_range_error、node_api_throw_syntax_error 和 napi_is_error。
【The following utility functions are also available in case native code
needs to throw an exception or determine if a napi_value is an instance
of a JavaScript Error object: napi_throw_error,
napi_throw_type_error, napi_throw_range_error, node_api_throw_syntax_error and 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。
【The following utility functions are also available in case native
code needs to create an Error object: napi_create_error,
napi_create_type_error, napi_create_range_error and node_api_create_syntax_error,
where result is the napi_value that refers to the newly created
JavaScript Error object.】
Node.js 项目正在为所有内部生成的错误添加错误代码。目标是让应用在进行所有错误检查时使用这些错误代码。相关的错误信息将保留,但仅用于记录和显示,预期这些信息可能会变化而不遵循语义化版本控制(SemVer)。为了支持 Node-API 的这一模型,无论是在内部功能还是模块特定功能中(这是良好实践),throw_ 和 create_ 函数都接受一个可选的 code 参数,该参数是要添加到错误对象的错误代码字符串。如果可选参数为 NULL,则错误不会关联任何代码。如果提供了代码,错误关联的名称也会更新为:
【The Node.js project is adding error codes to all of the errors
generated internally. The goal is for applications to use these
error codes for all error checking. The associated error messages
will remain, but will only be meant to be used for logging and
display with the expectation that the message can change without
SemVer applying. In order to support this model with Node-API, both
in internal functionality and for module specific functionality
(as its good practice), the throw_ and create_ functions
take an optional code parameter which is the string for the code
to be added to the error object. If the optional parameter is NULL
then no code will be associated with the error. If a code is provided,
the name associated with the error is also updated to be:】
originalName [code]
其中 originalName 是与错误相关的原始名称,code 是提供的代码。例如,如果代码是 'ERR_ERROR_1' 并且正在创建一个 TypeError,则名称将是:
【where originalName is the original name associated with the error
and code is the code that was provided. For example, if the code
is 'ERR_ERROR_1' and a TypeError is being created the name will be:】
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。
【Returns napi_ok if the API succeeded.】
此 API 抛出提供的 JavaScript 值。
【This API throws the JavaScript value provided.】
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。
【Returns napi_ok if the API succeeded.】
该 API 会抛出一个带有提供文本的 JavaScript Error。
【This API throws a JavaScript Error with the text provided.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 会抛出带有提供文本的 JavaScript TypeError。
【This API throws a JavaScript TypeError with the text provided.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 会抛出带有提供文本的 JavaScript RangeError。
【This API throws a JavaScript RangeError with the text provided.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 会抛出带有提供文本的 JavaScript SyntaxError。
【This API throws a JavaScript SyntaxError with the text provided.】
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。
【Returns napi_ok if the API succeeded.】
此 API 查询 napi_value 以检查它是否表示一个错误对象。
【This API queries a napi_value to check if it represents an error object.】
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:引用 JavaScriptstring的napi_value,将作为Error的消息使用。[out] result:表示已创建错误的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该 API 会返回一个包含提供文本的 JavaScript Error。
【This API returns a JavaScript Error with the text provided.】
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:引用 JavaScriptstring的napi_value,将作为Error的消息使用。[out] result:表示已创建错误的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
这个 API 会返回一个带有提供文本的 JavaScript TypeError。
【This API returns a JavaScript TypeError with the text provided.】
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:引用 JavaScriptstring的napi_value,将作为Error的消息使用。[out] result:表示已创建错误的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
这个 API 会返回一个 JavaScript RangeError,并包含提供的文本。
【This API returns a JavaScript RangeError with the text provided.】
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:引用 JavaScriptstring的napi_value,将作为Error的消息使用。[out] result:表示已创建错误的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
这个 API 会返回一个 JavaScript SyntaxError,并包含提供的文本。
【This API returns a JavaScript SyntaxError with the text provided.】
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。
【Returns napi_ok if the API succeeded.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
napi_is_exception_pending#>
napi_status napi_is_exception_pending(napi_env env, bool* result);
[in] env:调用该 API 时所处的环境。[out] result:布尔值,如果有异常待处理,则设置为 true。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
napi_fatal_exception#>
napi_status napi_fatal_exception(napi_env env, napi_value err);
[in] env:调用该 API 时所处的环境。[in] err:传递给'uncaughtException'的错误。
在 JavaScript 中触发 'uncaughtException'。如果异步回调抛出异常且无法恢复,这很有用。
【Trigger an 'uncaughtException' in JavaScript. Useful if an async
callback throws an exception with no way to recover.】
致命错误#>
【Fatal errors】
在本地插件发生无法恢复的错误时,可以抛出致命错误以立即终止进程。
【In the event of an unrecoverable error in a native addon, a fatal error can be thrown to immediately terminate the process.】
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。
函数调用不返回,进程将终止。
【The function call does not return, the process will be terminated.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
对象生命周期管理#>
【Object lifetime management】
在进行 Node-API 调用时,可能会返回指向底层虚拟机堆中对象的句柄,称为 napi_values。这些句柄必须保持对象“活动”,直到原生代码不再需要它们,否则在原生代码使用完之前,这些对象可能会被回收。
【As Node-API calls are made, handles to objects in the heap for the underlying
VM may be returned as napi_values. These handles must hold the
objects 'live' until they are no longer required by the native code,
otherwise the objects could be collected before the native code was
finished using them.】
当返回对象句柄时,它们会与“作用域”关联。默认作用域的生命周期与本地方法调用的生命周期绑定。其结果是,默认情况下,句柄保持有效,并且与这些句柄关联的对象将在本地方法调用的生命周期内保持存活。
【As object handles are returned they are associated with a 'scope'. The lifespan for the default scope is tied to the lifespan of the native method call. The result is that, by default, handles remain valid and the objects associated with these handles will be held live for the lifespan of the native method call.】
然而,在许多情况下,句柄必须保持有效,其生命周期可能比本地方法的生命周期更短或更长。以下各节将介绍可用于将句柄生命周期从默认值更改的 Node-API 函数。
【In many cases, however, it is necessary that the handles remain valid for either a shorter or longer lifespan than that of the native method. The sections which follow describe the Node-API functions that can be used to change the handle lifespan from the default.】
使句柄寿命短于本地方法#>
【Making handle lifespan shorter than that of the native method】
通常有必要使句柄的生命周期比本地方法的生命周期短。例如,考虑一个本地方法,它有一个循环,迭代大型数组中的元素:
【It is often necessary to make the lifespan of handles shorter than the lifespan of a native method. For example, consider a native method that has a loop which iterates through the elements in a large array:】
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
}
这将导致创建大量的句柄,消耗大量资源。此外,尽管原生代码只能使用最新的句柄,所有相关对象也都会被保留,因为它们都共享相同的作用域。
【This would result in a large number of handles being created, consuming substantial resources. In addition, even though the native code could only use the most recent handle, all of the associated objects would also be kept alive since they all share the same scope.】
为处理这种情况,Node-API 提供了建立一个新的“作用域”的能力,新创建的句柄将与该作用域关联。一旦这些句柄不再需要,该作用域可以被“关闭”,与该作用域关联的任何句柄都会失效。用于打开/关闭作用域的方法是 napi_open_handle_scope 和 napi_close_handle_scope。
【To handle this case, Node-API provides the ability to establish a new 'scope' to
which newly created handles will be associated. Once those handles
are no longer required, the scope can be 'closed' and any handles associated
with the scope are invalidated. The methods available to open/close scopes are
napi_open_handle_scope and napi_close_handle_scope.】
Node-API 仅支持单层嵌套的作用域层次结构。任何时候只有一个活动作用域,所有新的句柄在该作用域活动时都会与其关联。作用域必须按照打开的相反顺序关闭。此外,在本地方法中创建的所有作用域必须在从该方法返回之前关闭。
【Node-API only supports a single nested hierarchy of scopes. There is only one active scope at any time, and all new handles will be associated with that scope while it is active. Scopes must be closed in the reverse order from which they are opened. In addition, all scopes created within a native method must be closed before returning from that method.】
以之前的例子为例,添加对 napi_open_handle_scope 和 napi_close_handle_scope 的调用将确保在整个循环执行过程中最多只有一个句柄是有效的:
【Taking the earlier example, adding calls to napi_open_handle_scope and
napi_close_handle_scope would ensure that at most a single handle
is valid throughout the execution of the loop:】
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 支持“可逃逸作用域”来处理这种情况。可逃逸作用域允许一个句柄被“提升”,从而“逃逸”当前作用域,其生命周期从当前作用域变为外层作用域。
【When nesting scopes, there are cases where a handle from an inner scope needs to live beyond the lifespan of that scope. Node-API supports an 'escapable scope' in order to support this case. An escapable scope allows one handle to be 'promoted' so that it 'escapes' the current scope and the lifespan of the handle changes from the current scope to that of the outer scope.】
可用于打开/关闭可转义作用域的方法是 napi_open_escapable_handle_scope 和 napi_close_escapable_handle_scope。
【The methods available to open/close escapable scopes are
napi_open_escapable_handle_scope and
napi_close_escapable_handle_scope.】
提升账号的请求是通过 napi_escape_handle 提出的,该请求只能调用一次。
【The request to promote a handle is made through napi_escape_handle which
can only be called once.】
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。
【Returns napi_ok if the API succeeded.】
此 API 开辟了一个新的范围。
【This API opens a new scope.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会关闭传入的作用域。作用域必须按照创建的相反顺序关闭。
【This API closes the scope passed in. Scopes must be closed in the reverse order from which they were created.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 打开一个新的作用域,从中可以将一个对象提升到外部作用域。
【This API opens a new scope from which one object can be promoted to the outer scope.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会关闭传入的作用域。作用域必须按照创建的相反顺序关闭。
【This API closes the scope passed in. Scopes must be closed in the reverse order from which they were created.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
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。
【Returns napi_ok if the API succeeded.】
该 API 会将句柄提升到 JavaScript 对象,使其在外部作用域的整个生命周期内有效。每个作用域只能调用一次。如果调用超过一次,将返回错误。
【This API promotes the handle to the JavaScript object so that it is valid for the lifetime of the outer scope. It can only be called once per scope. If it is called more than once an error will be returned.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
对生命周期比原生方法长的值的引用#>
【References to values with a lifespan longer than that of the native method】
在某些情况下,插件需要能够创建并引用生命周期超过单个本地方法调用的值。例如,要创建一个构造函数并在后续请求中使用该构造函数来创建实例,就必须能够在多个不同的实例创建请求中引用该构造函数对象。用前面章节中描述的 napi_value 返回的普通句柄是无法实现这一点的。普通句柄的生命周期由作用域管理,并且所有作用域必须在本地方法结束之前关闭。
【In some cases, an addon will need to be able to create and reference values
with a lifespan longer than that of a single native method invocation. For
example, to create a constructor and later use that constructor
in a request to create instances, it must be possible to reference
the constructor object across many different instance creation requests. This
would not be possible with a normal handle returned as a napi_value as
described in the earlier section. The lifespan of a normal handle is
managed by scopes and all scopes must be closed before the end of a native
method.】
Node-API 提供了用于创建值的持久引用的方法。目前,Node-API 只允许为有限类型的值创建引用,包括对象、外部、函数和符号。
【Node-API provides methods for creating persistent references to values. Currently Node-API only allows references to be created for a limited set of value types, including object, external, function, and symbol.】
每个引用都有一个关联的计数,其值为0或更高,这决定了引用是否会保持对应的值存活。计数为0的引用不会阻止值被回收。对象(对象、函数、外部对象)和符号类型的值将成为“弱”引用,并且在它们未被回收时仍然可以访问。任何大于0的计数都将阻止值被回收。
【Each reference has an associated count with a value of 0 or higher, which determines whether the reference will keep the corresponding value alive. References with a count of 0 do not prevent values from being collected. Values of object (object, function, external) and symbol types are becoming 'weak' references and can still be accessed while they are not collected. Any count greater than 0 will prevent the values from being collected.】
符号值有不同的类型。真正的弱引用行为只支持使用 napi_create_symbol 函数或 JavaScript Symbol() 构造函数创建的本地符号。使用 node_api_symbol_for 函数或 JavaScript Symbol.for() 函数创建的全局注册符号始终保持强引用,因为垃圾回收器不会回收它们。对于像 Symbol.iterator 这样的众所周知的符号也是如此,它们同样不会被垃圾回收器回收。
【Symbol values have different flavors. The true weak reference behavior is
only supported by local symbols created with the napi_create_symbol function
or the JavaScript Symbol() constructor calls. Globally registered symbols
created with the node_api_symbol_for function or JavaScript Symbol.for()
function calls remain always strong references because the garbage collector
does not collect them. The same is true for well-known symbols such as
Symbol.iterator. They are also never collected by the garbage collector.】
引用可以在创建时设置初始引用计数。然后可以通过 napi_reference_ref 和 napi_reference_unref 修改计数。如果在引用的计数为 0 时对象被回收,随后对与该引用相关联的对象调用 napi_get_reference_value 将返回 NULL 作为返回的 napi_value。尝试对已被回收的对象的引用调用 napi_reference_ref 会导致错误。
【References can be created with an initial reference count. The count can
then be modified through napi_reference_ref and
napi_reference_unref. If an object is collected while the count
for a reference is 0, all subsequent calls to
get the object associated with the reference napi_get_reference_value
will return NULL for the returned napi_value. An attempt to call
napi_reference_ref for a reference whose object has been collected
results in an error.】
一旦不再需要,必须删除引用。当引用被删除时,它将不再阻止相应的对象被回收。如果未删除持久引用,将导致“内存泄漏”,持久引用的本地内存和堆上的相应对象都会被永久保留。
【References must be deleted once they are no longer required by the addon. When a reference is deleted, it will no longer prevent the corresponding object from being collected. Failure to delete a persistent reference results in a 'memory leak' with both the native memory for the persistent reference and the corresponding object on the heap being retained forever.】
可以创建多个持久引用指向同一个对象,每个引用会根据其自身的计数决定是否保持对象的存活。对同一个对象的多个持久引用可能导致本地内存意外被保留。持久引用所对应的本地结构必须在被引用对象的终结器执行之前保持有效。如果为同一个对象创建新的持久引用,则该对象的终结器不会被执行,且早期持久引用所指向的本地内存不会被释放。可以通过在可能的情况下同时调用 napi_delete_reference 和 napi_reference_unref 来避免这种情况。
【There can be multiple persistent references created which refer to the same
object, each of which will either keep the object live or not based on its
individual count. Multiple persistent references to the same object
can result in unexpectedly keeping alive native memory. The native structures
for a persistent reference must be kept alive until finalizers for the
referenced object are executed. If a new persistent reference is created
for the same object, the finalizers for that object will not be
run and the native memory pointed by the earlier persistent reference
will not be freed. This can be avoided by calling
napi_delete_reference in addition to napi_reference_unref when possible.】
更改历史:
-
版本 10(
NAPI_VERSION定义为10或更高):可以为所有值类型创建引用。新支持的值类型不支持弱引用语义,并且当引用计数为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。
【Returns napi_ok if the API succeeded.】
此 API 会使用指定的引用计数创建一个指向传入值的新引用。
【This API creates a new reference with the specified reference count to the value passed in.】
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。
【Returns napi_ok if the API succeeded.】
该 API 删除传入的引用。
【This API deletes the reference passed in.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会增加传入引用的引用计数,并返回增加后的引用计数。
【This API increments the reference count for the reference passed in and returns the resulting reference count.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会减少传入引用的引用计数,并返回结果引用计数。
【This API decrements the reference count for the reference passed in and returns the resulting reference count.】
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。
【Returns napi_ok if the API succeeded.】
如果仍然有效,此 API 会返回表示与 napi_ref 关联的 JavaScript 值的 napi_value。否则,结果将是 NULL。
【If still valid, this API returns the napi_value representing the
JavaScript value associated with the napi_ref. Otherwise, result
will be NULL.】
当前 Node.js 环境退出时的清理#>
【Cleanup on exit of the current Node.js environment】
虽然 Node.js 进程在退出时通常会释放其所有资源,但 Node.js 的嵌入者或将来的 Worker 支持可能要求插件注册清理钩子,这些钩子将在当前 Node.js 环境退出时运行。
【While a Node.js process typically releases all its resources when exiting, embedders of Node.js, or future Worker support, may require addons to register clean-up hooks that will be run once the current Node.js environment exits.】
Node-API 提供了用于注册和注销此类回调的函数。当这些回调被执行时,所有由插件持有的资源都应被释放。
【Node-API provides functions for registering and un-registering such callbacks. When those callbacks are run, all resources that are being held by the addon should be freed up.】
napi_add_env_cleanup_hook#>
NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_basic_env env,
napi_cleanup_hook fun,
void* arg);
注册 fun 作为一个函数,在当前 Node.js 环境退出时使用 arg 参数运行。
【Registers fun as a function to be run with the arg parameter once the
current Node.js environment exits.】
一个函数可以安全地使用不同的 arg 值多次指定。在这种情况下,它也会被调用多次。多次提供相同的 fun 和 arg 值是不允许的,并且会导致进程中止。
【A function can safely be specified multiple times with different
arg values. In that case, it will be called multiple times as well.
Providing the same fun and arg values multiple times is not allowed
and will lead the process to abort.】
钩子将以相反的顺序调用,即最后添加的钩子将最先被调用。
【The hooks will be called in reverse order, i.e. the most recently added one will be called first.】
可以使用 napi_remove_env_cleanup_hook 移除这个钩子。通常,这种情况发生在为其添加该钩子的资源本身即将被拆除时。
【Removing this hook can be done by using napi_remove_env_cleanup_hook.
Typically, that happens when the resource for which this hook was added
is being torn down anyway.】
对于异步清理,可以使用 napi_add_async_cleanup_hook。
【For asynchronous cleanup, napi_add_async_cleanup_hook is available.】
napi_remove_env_cleanup_hook#>
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_basic_env env,
void (*fun)(void* arg),
void* arg);
取消注册 fun,使其不再作为在当前 Node.js 环境退出时使用 arg 参数运行的函数。参数和函数值都需要完全匹配。
【Unregisters fun as a function to be run with the arg parameter once the
current Node.js environment exits. Both the argument and the function value
need to be exact matches.】
该函数必须最初使用 napi_add_env_cleanup_hook 注册,否则进程将中止。
【The function must have originally been registered
with napi_add_env_cleanup_hook, otherwise the process will abort.】
napi_add_async_cleanup_hook#>
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
node_api_basic_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 参数运行。
【Registers hook, which is a function of type napi_async_cleanup_hook, as
a function to be run with the remove_handle and arg parameters once the
current Node.js environment exits.】
与 napi_add_env_cleanup_hook 不同,该钩子允许异步操作。
【Unlike napi_add_env_cleanup_hook, the hook is allowed to be asynchronous.】
否则,行为通常与napi_add_env_cleanup_hook相同。
【Otherwise, behavior generally matches that of napi_add_env_cleanup_hook.】
如果 remove_handle 不是 NULL,一个不透明的值将存储在其中,之后必须传递给 napi_remove_async_cleanup_hook,无论该钩子是否已经被调用。通常,这种情况发生在为其添加该钩子的资源无论如何都要被拆除时。
【If remove_handle is not NULL, an opaque value will be stored in it
that must later be passed to napi_remove_async_cleanup_hook,
regardless of whether the hook has already been invoked.
Typically, that happens when the resource for which this hook was added
is being torn down anyway.】
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 值调用此函数。
【Unregisters the cleanup hook corresponding to remove_handle. This will prevent
the hook from being executed, unless it has already started executing.
This must be called on any napi_async_cleanup_hook_handle value obtained
from napi_add_async_cleanup_hook.】
在 Node.js 环境退出时完成#>
【Finalization on the exit of the Node.js environment】
Node.js 环境可能会在任意时间尽快被拆除,并且不允许执行 JavaScript,例如应 worker.terminate() 的请求。当环境正在被拆除时,JavaScript 对象、线程安全函数和环境实例数据的已注册 napi_finalize 回调会立即且独立地被调用。
【The Node.js environment may be torn down at an arbitrary time as soon as
possible with JavaScript execution disallowed, like on the request of
worker.terminate(). When the environment is being torn down, the
registered napi_finalize callbacks of JavaScript objects, thread-safe
functions and environment instance data are invoked immediately and
independently.】
napi_finalize 回调的调用会在手动注册的清理钩子之后进行调度。为了在环境关闭期间确保插件最终化的正确顺序,从而避免在 napi_finalize 回调中出现使用已释放资源的情况,插件应使用 napi_add_env_cleanup_hook 和 napi_add_async_cleanup_hook 注册清理钩子,以按正确顺序手动释放分配的资源。
【The invocation of napi_finalize callbacks is scheduled after the manually
registered cleanup hooks. In order to ensure a proper order of addon
finalization during environment shutdown to avoid use-after-free in the
napi_finalize callback, addons should register a cleanup hook with
napi_add_env_cleanup_hook and napi_add_async_cleanup_hook to manually
release the allocated resource in a proper order.】
模块注册#>
【Module registration】
Node-API 模块的注册方式与其他模块类似,只是使用以下方式,而不是使用 NODE_MODULE 宏:
【Node-API modules are registered in a manner similar to other modules
except that instead of using the NODE_MODULE macro the following
is used:】
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
下一个区别是 Init 方法的签名。对于 Node-API 模块,它如下所示:
【The next difference is the signature for the Init method. For a Node-API
module it is as follows:】
napi_value Init(napi_env env, napi_value exports);
Init 的返回值被视为模块的 exports 对象。Init 方法通过 exports 参数传递了一个空对象以供方便使用。如果 Init 返回 NULL,则作为 exports 传入的参数将被模块导出。Node-API 模块不能修改 module 对象,但可以将任意内容作为模块的 exports 属性指定。
【The return value from Init is treated as the exports object for the module.
The Init method is passed an empty object via the exports parameter as a
convenience. If Init returns NULL, the parameter passed as exports is
exported by the module. Node-API modules cannot modify the module object but
can specify anything as the exports property of the module.】
要将方法 hello 添加为函数,以便可以将其作为插件提供的方法调用:
【To add the method hello as a function so that it can be called as a method
provided by the addon:】
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() 返回的插件函数:
【To set a function to be returned by the require() for the addon:】
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;
}
定义一个类,以便可以创建新实例(通常与 对象封装 一起使用):
【To define a class so that new instances can be created (often used with Object wrap):】
// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor properties[] = {
{ "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
};
napi_value cons;
status =
napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
if (status != napi_ok) return NULL;
status = napi_create_reference(env, cons, 1, &constructor);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "MyObject", cons);
if (status != napi_ok) return NULL;
return exports;
}
你也可以使用 NAPI_MODULE_INIT 宏,它作为 NAPI_MODULE 和定义 Init 函数的简写:
【You can also use the NAPI_MODULE_INIT macro, which acts as a shorthand
for NAPI_MODULE and defining an Init function:】
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 宏的主体。
【The parameters env and exports are provided to the body of the
NAPI_MODULE_INIT macro.】
所有 Node-API 插件都是上下文感知的,这意味着它们可能会被多次加载。在声明这样的模块时,有一些设计方面需要考虑。关于 上下文感知插件 的文档提供了更多详细信息。
【All Node-API addons are context-aware, meaning they may be loaded multiple times. There are a few design considerations when declaring such a module. The documentation on context-aware addons provides more details.】
在宏调用之后,变量 env 和 exports 将在函数体内可用。
【The variables env and exports will be available inside the function body
following the macro invocation.】
有关在对象上设置属性的更多详细信息,请参阅 使用 JavaScript 属性 部分。
【For more details on setting properties on objects, see the section on Working with JavaScript properties.】
有关构建附加模块的一般详细信息,请参阅现有的 API。
【For more details on building addon modules in general, refer to the existing API.】
使用 JavaScript 值#>
【Working with JavaScript values】
Node-API 提供了一组用于创建所有类型 JavaScript 值的 API。这些类型中的一些在 ECMAScript 语言规范 的 章节语言类型 下有所记录。
【Node-API exposes a set of APIs to create all types of JavaScript values. Some of these types are documented under Section language types of the ECMAScript Language Specification.】
从根本上说,这些 API 用于执行以下操作之一:
【Fundamentally, these APIs are used to do one of the following:】
- 创建一个新的 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 类型。
【Node-API values are represented by the type napi_value.
Any Node-API call that requires a JavaScript value takes in a napi_value.
In some cases, the API does check the type of the napi_value up-front.
However, for better performance, it's better for the caller to make sure that
the napi_value in question is of the JavaScript type expected by the API.】
枚举类型#>
【Enum types】
napi_key_collection_mode#>
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode;
描述 Keys/Properties 筛选枚举:
【Describes the Keys/Properties filter enums:】
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;
属性过滤位标志。它可以与位操作符一起使用来构建复合过滤器。
【Property filter bit flag. This works with bit operators to build a composite 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 语言规范 章节语言类型 中描述的类型。除了该部分中的类型外,napi_valuetype 还可以表示带有外部数据的 Function 和 Object。
【Describes the type of a napi_value. This generally corresponds to the types
described in Section language types of the ECMAScript Language Specification.
In addition to types in that section, napi_valuetype can also represent
Functions and Objects with external data.】
napi_external 类型的 JavaScript 值在 JavaScript 中表现为一个普通对象,无法在其上设置任何属性,也没有原型。
【A JavaScript value of type napi_external appears in JavaScript as a plain
object such that no properties can be set on it, and no prototype.】
napi_typedarray_type#>
typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
napi_bigint64_array,
napi_biguint64_array,
} napi_typedarray_type;
这表示 TypedArray 的底层二进制标量数据类型。这个枚举的元素对应于 ECMAScript 语言规范 的 类型化数组对象部分。
【This represents the underlying binary scalar datatype of the TypedArray.
Elements of this enum correspond to
Section TypedArray objects of the ECMAScript Language Specification.】
对象创建函数#>
【Object creation functions】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回对应于 JavaScript Array 类型的 Node-API 值。JavaScript 数组在 ECMAScript 语言规范的 数组对象 中有描述。
【This API returns a Node-API value corresponding to a JavaScript Array type.
JavaScript arrays are described in
Section Array objects of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回一个与 JavaScript Array 类型对应的 Node-API 值。
Array 的 length 属性将被设置为传入的 length 参数。
然而,当数组创建时,底层缓冲区不保证会被虚拟机预先分配。该行为由底层虚拟机实现决定。如果缓冲区必须是一个可以通过 C 直接读取和/或写入的连续内存块,请考虑使用 napi_create_external_arraybuffer。
【This API returns a Node-API value corresponding to a JavaScript Array type.
The Array's length property is set to the passed-in length parameter.
However, the underlying buffer is not guaranteed to be pre-allocated by the VM
when the array is created. That behavior is left to the underlying VM
implementation. If the buffer must be a contiguous block of memory that can be
directly read and/or written via C, consider using
napi_create_external_arraybuffer.】
JavaScript 数组在 ECMAScript 语言规范的 数组对象 中有所描述。
【JavaScript arrays are described in Section Array objects of the ECMAScript Language Specification.】
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的底层字节缓冲区的指针。可以通过传递NULL来选择性地忽略data。[out] result:一个napi_value,表示 JavaScript 的ArrayBuffer。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回一个对应于 JavaScript ArrayBuffer 的 Node-API 值。ArrayBuffer 用于表示固定长度的二进制数据缓冲区。它们通常用作 TypedArray 对象的后备缓冲区。分配的 ArrayBuffer 将具有一个底层字节缓冲区,其大小由传入的 length 参数决定。如果调用者希望直接操作缓冲区,该底层缓冲区可以选择性地返回给调用者。该缓冲区只能从本地代码直接写入。要从 JavaScript 写入此缓冲区,需要创建一个类型化数组或 DataView 对象。
【This API returns a Node-API value corresponding to a JavaScript ArrayBuffer.
ArrayBuffers are used to represent fixed-length binary data buffers. They are
normally used as a backing-buffer for TypedArray objects.
The ArrayBuffer allocated will have an underlying byte buffer whose size is
determined by the length parameter that's passed in.
The underlying buffer is optionally returned back to the caller in case the
caller wants to directly manipulate the buffer. This buffer can only be
written to directly from native code. To write to this buffer from JavaScript,
a typed array or DataView object would need to be created.】
JavaScript ArrayBuffer 对象在 ECMAScript 语言规范的 ArrayBuffer 对象部分 中有描述。
【JavaScript ArrayBuffer objects are described in
Section ArrayBuffer objects of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会分配一个 node::Buffer 对象。虽然它仍然是一个完全受支持的数据结构,但在大多数情况下使用 TypedArray 就足够了。
【This API allocates a node::Buffer object. While this is still a
fully-supported data structure, in most cases using a TypedArray will suffice.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 会分配一个 node::Buffer 对象,并用从传入缓冲区复制的数据初始化它。虽然这仍然是一个完全支持的数据结构,但在大多数情况下使用 TypedArray 就足够了。
【This API allocates a node::Buffer object and initializes it with data copied
from the passed-in buffer. While this is still a fully-supported data
structure, in most cases using a TypedArray will suffice.】
napi_create_date#>
napi_status napi_create_date(napi_env env,
double time,
napi_value* result);
[in] env:调用该 API 时所处的环境。[in] time:自协调世界时 (UTC) 1970 年 1 月 1 日起的 ECMAScript 时间值(以毫秒为单位)。[out] result:一个表示 JavaScriptDate的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该 API 不考虑闰秒;它们会被忽略,因为 ECMAScript 遵循 POSIX 时间规范。
【This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification.】
此 API 分配一个 JavaScript Date 对象。
【This API allocates a JavaScript Date object.】
JavaScript Date 对象在 ECMAScript 语言规范的 部分日期对象 中有描述。
【JavaScript Date objects are described in
Section Date objects of the ECMAScript Language Specification.】
napi_create_external#>
napi_status napi_create_external(napi_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] data:指向外部数据的原始指针。[in] finalize_cb:当外部值被回收时可选调用的回调。napi_finalize提供了更多详细信息。[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。[out] result:表示一个外部值的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 分配了一个附带外部数据的 JavaScript 值。这用于通过 JavaScript 代码传递外部数据,以便本地代码稍后可以使用 napi_get_value_external 检索该数据。
【This API allocates a JavaScript value with external data attached to it. This
is used to pass external data through JavaScript code, so it can be retrieved
later by native code using napi_get_value_external.】
该 API 添加了一个 napi_finalize 回调,当刚创建的 JavaScript 对象被垃圾回收时,该回调将被调用。
【The API adds a napi_finalize callback which will be called when the JavaScript
object just created has been garbage collected.】
创建的值不是对象,因此不支持附加属性。它被视为一种独立的值类型:使用外部值调用 napi_typeof() 会返回 napi_external。
【The created value is not an object, and therefore does not support additional
properties. It is considered a distinct value type: calling napi_typeof() with
an external value yields napi_external.】
napi_create_external_arraybuffer#>
napi_status
napi_create_external_arraybuffer(napi_env env,
void* external_data,
size_t byte_length,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] external_data:指向ArrayBuffer的底层字节缓冲区的指针。[in] byte_length:底层缓冲区的字节长度。[in] finalize_cb:可选回调,当ArrayBuffer被回收时调用。napi_finalize提供了更多细节。[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。[out] result:一个napi_value,表示 JavaScript 的ArrayBuffer。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
除 Node.js 外的一些运行时已停止支持外部缓冲区。
在除 Node.js 外的运行时中,该方法可能返回 napi_no_external_buffers_allowed,以表示不支持外部缓冲区。Electron 就是其中一种运行时,如本问题中所述 electron/issues/35801。
为了保持与所有运行时的最广泛兼容性,你可以在包含 node-api 头文件之前在你的插件中定义 NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED。这样做会隐藏创建外部缓冲区的两个函数。这将确保如果你不小心使用了其中一个方法,会发生编译错误。
【In order to maintain broadest compatibility with all runtimes
you may define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED in your addon before
includes for the node-api headers. Doing so will hide the 2 functions
that create external buffers. This will ensure a compilation error
occurs if you accidentally use one of these methods.】
此 API 返回与 JavaScript ArrayBuffer 对应的 Node-API 值。ArrayBuffer 的底层字节缓冲区是外部分配和管理的。调用者必须确保字节缓冲区在终结回调被调用之前保持有效。
【This API returns a Node-API value corresponding to a JavaScript ArrayBuffer.
The underlying byte buffer of the ArrayBuffer is externally allocated and
managed. The caller must ensure that the byte buffer remains valid until the
finalize callback is called.】
该 API 添加了一个 napi_finalize 回调,当刚创建的 JavaScript 对象被垃圾回收时,该回调将被调用。
【The API adds a napi_finalize callback which will be called when the JavaScript
object just created has been garbage collected.】
JavaScript 的 ArrayBuffer 在 ECMAScript 语言规范的 ArrayBuffer 对象部分 中有描述。
【JavaScript ArrayBuffers are described in
Section ArrayBuffer objects of the ECMAScript Language Specification.】
napi_create_external_buffer#>
napi_status napi_create_external_buffer(napi_env env,
size_t length,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] length:输入缓冲区的字节大小(应与新缓冲区的大小相同)。[in] data:指向要暴露给 JavaScript 的底层缓冲区的原始指针。[in] finalize_cb:可选回调,当ArrayBuffer被回收时调用。napi_finalize提供了更多细节。[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。[out] result:一个表示node::Buffer的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
除 Node.js 外的一些运行时已停止支持外部缓冲区。
在除 Node.js 外的运行时中,该方法可能返回 napi_no_external_buffers_allowed,以表示不支持外部缓冲区。Electron 就是其中一种运行时,如本问题中所述 electron/issues/35801。
为了保持与所有运行时的最广泛兼容性,你可以在包含 node-api 头文件之前在你的插件中定义 NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED。这样做会隐藏创建外部缓冲区的两个函数。这将确保如果你不小心使用了其中一个方法,会发生编译错误。
【In order to maintain broadest compatibility with all runtimes
you may define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED in your addon before
includes for the node-api headers. Doing so will hide the 2 functions
that create external buffers. This will ensure a compilation error
occurs if you accidentally use one of these methods.】
这个 API 会分配一个 node::Buffer 对象,并用传入缓冲区支持的数据初始化它。虽然这仍然是一个完全支持的数据结构,但在大多数情况下使用 TypedArray 就足够了。
【This API allocates a node::Buffer object and initializes it with data
backed by the passed in buffer. While this is still a fully-supported data
structure, in most cases using a TypedArray will suffice.】
该 API 添加了一个 napi_finalize 回调,当刚创建的 JavaScript 对象被垃圾回收时,该回调将被调用。
【The API adds a napi_finalize callback which will be called when the JavaScript
object just created has been garbage collected.】
对于 Node.js >=4,Buffer 是 Uint8Array。
【For Node.js >=4 Buffers are Uint8Arrays.】
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。
【Returns napi_ok if the API succeeded.】
此 API 分配一个默认的 JavaScript Object。它等同于在 JavaScript 中执行 new Object()。
【This API allocates a default JavaScript Object.
It is the equivalent of doing new Object() in JavaScript.】
JavaScript 的 Object 类型在 ECMAScript 语言规范的 区段对象类型 中有描述。
【The JavaScript Object type is described in Section object type of the
ECMAScript Language Specification.】
napi_create_object_with_properties#>
napi_status napi_create_object_with_properties(napi_env env,
napi_value prototype_or_null,
const napi_value* property_names,
const napi_value* property_values,
size_t property_count,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] prototype_or_null:新对象的原型对象。可以是表示 JavaScript 对象的napi_value用作原型,也可以是表示 JavaScriptnull的napi_value,或者是会被转换为null的nullptr。[in] property_names:表示属性名称的napi_value数组。[in] property_values:表示属性值的napi_value数组。[in] property_count:数组中的属性数量。[out] result:一个表示 JavaScriptObject的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会创建一个具有指定原型和属性的 JavaScript Object。这比先调用 napi_create_object 然后多次调用 napi_set_property 更高效,因为它可以原子地创建具有所有属性的对象,避免了潜在的 V8 map 转换。
【This API creates a JavaScript Object with the specified prototype and
properties. This is more efficient than calling napi_create_object followed
by multiple napi_set_property calls, as it can create the object with all
properties atomically, avoiding potential V8 map transitions.】
数组 property_names 和 property_values 必须具有由 property_count 指定的相同长度。属性会按照它们在数组中出现的顺序添加到对象中。
【The arrays property_names and property_values must have the same length
specified by property_count. The properties are added to the object in the
order they appear in the arrays.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 从 UTF8 编码的 C 字符串创建一个 JavaScript symbol 值。
【This API creates a JavaScript symbol value from a UTF8-encoded C string.】
JavaScript 的 symbol 类型在 ECMAScript 语言规范的 章节符号类型 中有描述。
【The JavaScript symbol type is described in Section symbol type
of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会在全局注册表中搜索具有给定描述的现有符号。如果符号已存在,将返回该符号;否则,将在注册表中创建一个新符号。
【This API searches in the global registry for an existing symbol with the given description. If the symbol already exists it will be returned, otherwise a new symbol will be created in the registry.】
JavaScript 的 symbol 类型在 ECMAScript 语言规范的 章节符号类型 中有描述。
【The JavaScript symbol type is described in Section symbol type of the ECMAScript
Language Specification.】
napi_create_typedarray#>
napi_status napi_create_typedarray(napi_env env,
napi_typedarray_type type,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] type:TypedArray中元素的标量数据类型。[in] length:TypedArray中的元素数量。[in] arraybuffer:表示类型化数组所使用的ArrayBuffer。[in] byte_offset:ArrayBuffer内用于开始映射TypedArray的字节偏移量。[out] result:一个napi_value,表示 JavaScript 的TypedArray。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 在现有的 ArrayBuffer 上创建一个 JavaScript TypedArray 对象。TypedArray 对象提供了一种类似数组的视图,用于访问底层数据缓冲区,其中每个元素具有相同的底层二进制标量数据类型。
【This API creates a JavaScript TypedArray object over an existing
ArrayBuffer. TypedArray objects provide an array-like view over an
underlying data buffer where each element has the same underlying binary scalar
datatype.】
要求 (length * size_of_element) + byte_offset 应该小于或等于传入数组的字节大小。如果不满足,将抛出 RangeError 异常。
【It's required that (length * size_of_element) + byte_offset should
be <= the size in bytes of the array passed in. If not, a RangeError exception
is raised.】
JavaScript TypedArray 对象在 ECMAScript 语言规范的 类型化数组对象部分 中有描述。
【JavaScript TypedArray objects are described in
Section TypedArray objects of the ECMAScript Language Specification.】
node_api_create_buffer_from_arraybuffer#>
napi_status NAPI_CDECL node_api_create_buffer_from_arraybuffer(napi_env env,
napi_value arraybuffer,
size_t byte_offset,
size_t byte_length,
napi_value* result)
[in] env:API 调用时所处的环境。[in] arraybuffer:将用于创建缓冲区的ArrayBuffer。[in] byte_offset:在ArrayBuffer内开始创建缓冲区的字节偏移量。[in] byte_length:要从ArrayBuffer创建的缓冲区的字节长度。[out] result:表示创建的 JavaScriptBuffer对象的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 从现有的 ArrayBuffer 创建一个 JavaScript Buffer 对象。Buffer 对象是 Node.js 特有的类,提供了一种在 JavaScript 中直接处理二进制数据的方法。
【This API creates a JavaScript Buffer object from an existing ArrayBuffer.
The Buffer object is a Node.js-specific class that provides a way to work with binary data directly in JavaScript.】
字节范围 [byte_offset, byte_offset + byte_length) 必须在 ArrayBuffer 的边界内。如果 byte_offset + byte_length 超过 ArrayBuffer 的大小,将会抛出 RangeError 异常。
【The byte range [byte_offset, byte_offset + byte_length)
must be within the bounds of the ArrayBuffer. If byte_offset + byte_length
exceeds the size of the ArrayBuffer, a RangeError exception is raised.】
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:一个napi_value,表示 JavaScript 的DataView。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 在现有的 ArrayBuffer 上创建一个 JavaScript DataView 对象。DataView 对象提供了一个类似数组的视图,用于底层数据缓冲区,但允许在 ArrayBuffer 中使用不同大小和类型的项目。
【This API creates a JavaScript DataView object over an existing ArrayBuffer.
DataView objects provide an array-like view over an underlying data buffer,
but one which allows items of different size and type in the ArrayBuffer.】
要求 byte_length + byte_offset 小于或等于传入数组的字节大小。如果不满足,将抛出 RangeError 异常。
【It is required that byte_length + byte_offset is less than or equal to the
size in bytes of the array passed in. If not, a RangeError exception is
raised.】
JavaScript DataView 对象在 ECMAScript 语言规范的 部分 数据视图对象 中有描述。
【JavaScript DataView objects are described in
Section DataView objects of the ECMAScript Language Specification.】
从 C 类型转换为 Node-API 的函数#>
【Functions to convert from C types to 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。
【Returns napi_ok if the API succeeded.】
此 API 用于将 C 的 int32_t 类型转换为 JavaScript 的 number 类型。
【This API is used to convert from the C int32_t type to the JavaScript
number type.】
JavaScript 的 number 类型在 ECMAScript 语言规范的 节号类型 中有描述。
【The JavaScript number type is described in
Section number type of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于将 C 的 uint32_t 类型转换为 JavaScript 的 number 类型。
【This API is used to convert from the C uint32_t type to the JavaScript
number type.】
JavaScript 的 number 类型在 ECMAScript 语言规范的 节号类型 中有描述。
【The JavaScript number type is described in
Section number type of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于将 C 的 int64_t 类型转换为 JavaScript 的 number 类型。
【This API is used to convert from the C int64_t type to the JavaScript
number type.】
JavaScript 的 number 类型在 ECMAScript 语言规范的 节号类型 中进行了描述。请注意,JavaScript 无法以完整精度表示 int64_t 的全部范围。超出 Number.MIN_SAFE_INTEGER -(2**53 - 1) 至 Number.MAX_SAFE_INTEGER (2**53 - 1) 范围的整数值将会丢失精度。
【The JavaScript number type is described in Section number type
of the ECMAScript Language Specification. Note the complete range of int64_t
cannot be represented with full precision in JavaScript. Integer values
outside the range of Number.MIN_SAFE_INTEGER -(2**53 - 1) -
Number.MAX_SAFE_INTEGER (2**53 - 1) will lose precision.】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于将 C 语言的 double 类型转换为 JavaScript 的 number 类型。
【This API is used to convert from the C double type to the JavaScript
number type.】
JavaScript 的 number 类型在 ECMAScript 语言规范的 节号类型 中有描述。
【The JavaScript number type is described in
Section number type of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 将 C 的 int64_t 类型转换为 JavaScript 的 BigInt 类型。
【This API converts the C int64_t type to the JavaScript BigInt type.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 将 C 的 uint64_t 类型转换为 JavaScript 的 BigInt 类型。
【This API converts the C uint64_t type to the JavaScript BigInt type.】
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。
【Returns napi_ok if the API succeeded.】
此 API 将一个无符号 64 位字数组转换为单个 BigInt 值。
【This API converts an array of unsigned 64-bit words into a single BigInt
value.】
得到的 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:字符串的字节长度,如果是以空字符结尾,则使用NAPI_AUTO_LENGTH。[out] result:一个表示 JavaScriptstring的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会从 ISO-8859-1 编码的 C 字符串创建一个 JavaScript string 值。原生字符串会被复制。
【This API creates a JavaScript string value from an ISO-8859-1-encoded C
string. The native string is copied.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
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:字符串的字节长度,如果是以空字符结尾,则使用NAPI_AUTO_LENGTH。[in] finalize_callback:在字符串被回收时调用的函数。该函数将使用以下参数被调用:[in] env:插件运行的环境。如果该字符串是在工作线程或主 Node.js 实例终止时收集的,则该值可能为 null。[in] data:这是作为void*指针的str值。[in] finalize_hint:这是传递给 API 的finalize_hint值。napi_finalize提供了更多详细信息。该参数是可选的。传递空值表示当对应的 JavaScript 字符串被回收时,不需要通知该插件。
[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。[out] result:一个表示 JavaScriptstring的napi_value。[out] copied:字符串是否被复制。如果被复制,终结器将已经被调用来销毁str。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该 API 从 ISO-8859-1 编码的 C 字符串创建一个 JavaScript string 值。原生字符串可能不会被复制,因此必须在 JavaScript 值的整个生命周期内存在。
【This API creates a JavaScript string value from an ISO-8859-1-encoded C
string. The native string may not be copied and must thus exist for the entire
life cycle of the JavaScript value.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 从 UTF16-LE 编码的 C 字符串创建一个 JavaScript string 值。原生字符串会被复制。
【This API creates a JavaScript string value from a UTF16-LE-encoded C string.
The native string is copied.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
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:这是作为void*指针的str值。[in] finalize_hint:这是传递给 API 的finalize_hint值。napi_finalize提供了更多详细信息。该参数是可选的。传递空值表示当对应的 JavaScript 字符串被回收时,不需要通知该插件。
[in] finalize_hint:在收集期间传递给 finalize 回调的可选提示。[out] result:一个表示 JavaScriptstring的napi_value。[out] copied:字符串是否被复制。如果被复制,终结器将已经被调用来销毁str。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
这个 API 会从 UTF16-LE 编码的 C 字符串创建一个 JavaScript string 值。原生字符串可能不会被复制,因此必须在 JavaScript 值的整个生命周期内存在。
【This API creates a JavaScript string value from a UTF16-LE-encoded C string.
The native string may not be copied and must thus exist for the entire life
cycle of the JavaScript value.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
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:字符串的字节长度,如果是以空字符结尾,则使用NAPI_AUTO_LENGTH。[out] result:一个表示 JavaScriptstring的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 从 UTF8 编码的 C 字符串创建一个 JavaScript string 值。原生字符串会被复制。
【This API creates a JavaScript string value from a UTF8-encoded C string.
The native string is copied.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
用于创建优化属性键的函数#>
【Functions to create optimized property keys】
许多 JavaScript 引擎,包括 V8,使用内化字符串作为键来设置和获取属性值。它们通常使用哈希表来创建和查询这些字符串。虽然每次创建键时会增加一些开销,但之后可以通过比较字符串指针而不是整个字符串来提高性能。
【Many JavaScript engines including V8 use internalized strings as keys to set and get property values. They typically use a hash table to create and lookup such strings. While it adds some cost per key creation, it improves the performance after that by enabling comparison of string pointers instead of the whole strings.】
如果一个新的 JavaScript 字符串打算用作属性键,那么对于某些 JavaScript 引擎来说,使用本节中的函数会更高效。否则,请使用 napi_create_string_utf8 或 node_api_create_external_string_utf8 系列函数,因为使用属性键创建方法创建/存储字符串可能会有额外开销。
【If a new JavaScript string is intended to be used as a property key, then for
some JavaScript engines it will be more efficient to use the functions in this
section. Otherwise, use the napi_create_string_utf8 or
node_api_create_external_string_utf8 series functions as there may be
additional overhead in creating/storing strings with the property key
creation methods.】
node_api_create_property_key_latin1#>
napi_status NAPI_CDECL node_api_create_property_key_latin1(napi_env env,
const char* str,
size_t length,
napi_value* result);
[in] env:调用该 API 时所处的环境。[in] str:表示 ISO-8859-1 编码字符串的字符缓冲区。[in] length:字符串的字节长度,如果是以空字符结尾,则使用NAPI_AUTO_LENGTH。[out] result:一个napi_value,表示一个优化过的 JavaScriptstring,用作对象的属性键。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 从 ISO-8859-1 编码的 C 字符串创建一个优化的 JavaScript string 值,可用作对象的属性键。原生字符串会被复制。与 napi_create_string_latin1 不同,后续使用相同 str 指针调用此函数可能会根据引擎的不同,在创建请求的 napi_value 时获得速度提升。
【This API creates an optimized JavaScript string value from
an ISO-8859-1-encoded C string to be used as a property key for objects.
The native string is copied. In contrast with napi_create_string_latin1,
subsequent calls to this function with the same str pointer may benefit from a speedup
in the creation of the requested napi_value, depending on the engine.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 会从 UTF16-LE 编码的 C 字符串创建一个优化的 JavaScript string 值,以用作对象的属性键。原生字符串会被复制。
【This API creates an optimized JavaScript string value from
a UTF16-LE-encoded C string to be used as a property key for objects.
The native string is copied.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
node_api_create_property_key_utf8#>
napi_status NAPI_CDECL node_api_create_property_key_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:一个napi_value,表示一个优化过的 JavaScriptstring,用作对象的属性键。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会从 UTF8 编码的 C 字符串创建一个优化后的 JavaScript string 值,用作对象的属性键。原生字符串会被复制。
【This API creates an optimized JavaScript string value from
a UTF8-encoded C string to be used as a property key for objects.
The native string is copied.】
JavaScript 的 string 类型在 ECMAScript 语言规范的 段字符串类型 中有描述。
【The JavaScript string type is described in
Section string type of the ECMAScript Language Specification.】
从 Node-API 转换为 C 类型的函数#>
【Functions to convert from Node-API to C types】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回数组的长度。
【This API returns the length of an array.】
Array 的长度在 ECMAScript 语言规范的 Section 数组实例长度 中有所描述。
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或SharedArrayBuffer的napi_value。[out] data:ArrayBuffer或SharedArrayBuffer的底层数据缓冲区是0,这可能是NULL或其他任何指针值。[out] byte_length:底层数据缓冲区的字节长度。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 用于获取 ArrayBuffer 或 SharedArrayBuffer 的底层数据缓冲区及其长度。
【This API is used to retrieve the underlying data buffer of an ArrayBuffer or SharedArrayBuffer and its length.】
警告: 使用此 API 时请小心。底层数据缓冲区的生命周期由 ArrayBuffer 或 SharedArrayBuffer 管理,即使在返回后也是如此。使用此 API 的一种可能安全的方法是结合 napi_create_reference 使用,它可以保证对 ArrayBuffer 或 SharedArrayBuffer 生命周期的控制。在同一个回调中使用返回的数据缓冲区也是安全的,只要在此期间没有调用可能触发垃圾回收(GC)的其他 API。
【WARNING: Use caution while using this API. The lifetime of the underlying data
buffer is managed by the ArrayBuffer or SharedArrayBuffer even after it's returned. A
possible safe way to use this API is in conjunction with
napi_create_reference, which can be used to guarantee control over the
lifetime of the ArrayBuffer or SharedArrayBuffer. It's also safe to use the returned data buffer
within the same callback as long as there are no calls to other APIs that might
trigger a GC.】
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的底层数据缓冲区。如果长度为0,则此值可能为NULL或其他任意指针值。[out] length:底层数据缓冲区的字节长度。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该方法返回与 napi_get_typedarray_info 相同的 data 和 byte_length。而 napi_get_typedarray_info 也接受 node::Buffer(一个 Uint8Array)作为值。
【This method returns the identical data and byte_length as
napi_get_typedarray_info. And napi_get_typedarray_info accepts a
node::Buffer (a Uint8Array) as the value too.】
此 API 用于检索 node::Buffer 的底层数据缓冲区及其长度。
【This API is used to retrieve the underlying data buffer of a node::Buffer
and its length.】
警告:使用此 API 时请小心,因为如果底层数据缓冲区由虚拟机管理,其生命周期无法保证。
【Warning: Use caution while using this API since the underlying data buffer's lifetime is not guaranteed if it's managed by the 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。
【Returns napi_ok if the API succeeded.】
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] 数据:TypedArray底层的数据缓冲区,已根据byte_offset值进行调整,以便指向TypedArray中的第一个元素。如果数组的长度为0,则此值可能为NULL或其他任意指针值。[out] arraybuffer:TypedArray所依赖的ArrayBuffer。[out] byte_offset:底层本地数组中数组第一个元素所在的字节偏移。data 参数的值已经被调整,使得 data 指向数组中的第一个元素。因此,本地数组的第一个字节位置为data - byte_offset。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回类型化数组的各种属性。
【This API returns various properties of a typed array.】
如果不需要该属性,任何输出参数都可以为 NULL。
【Any of the out parameters may be NULL if that property is unneeded.】
警告: 使用此 API 时请小心,因为底层数据缓冲区由虚拟机管理。
【Warning: Use caution while using this API since the underlying data buffer is managed by the 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。
【Returns napi_ok if the API succeeded.】
如果不需要该属性,任何输出参数都可以为 NULL。
【Any of the out parameters may be NULL if that property is unneeded.】
此 API 返回 DataView 的各种属性。
【This API returns various properties of a 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:时间值,类型为double,表示自协调世界时 (UTC) 1970 年 1 月 1 日午夜起的毫秒数。
该 API 不考虑闰秒;它们会被忽略,因为 ECMAScript 遵循 POSIX 时间规范。
【This API does not observe leap seconds; they are ignored, as ECMAScript aligns with POSIX time specification.】
如果 API 成功,则返回 napi_ok。如果传入的 napi_value 不是日期,则返回 napi_date_expected。
【Returns napi_ok if the API succeeded. If a non-date napi_value is passed
in it returns napi_date_expected.】
此 API 返回给定 JavaScript Date 的时间值的 C double 类型原始数据。
【This API returns the C double primitive of time value for the given JavaScript
Date.】
napi_get_value_bool#>
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
[in] env:调用该 API 时所处的环境。[in] value:napi_value,表示 JavaScript 的Boolean。[out] result:给定 JavaScriptBoolean的 C 布尔原始等价物。
如果 API 执行成功,返回 napi_ok。如果传入的 napi_value 不是布尔值,则返回 napi_boolean_expected。
【Returns napi_ok if the API succeeded. If a non-boolean napi_value is
passed in it returns napi_boolean_expected.】
此 API 返回给定 JavaScript Boolean 的 C 布尔原始类型等价值。
【This API returns the C boolean primitive equivalent of the given JavaScript
Boolean.】
napi_get_value_double#>
napi_status napi_get_value_double(napi_env env,
napi_value value,
double* result)
[in] env:调用该 API 时所处的环境。[in] value:napi_value,表示 JavaScript 的number。[out] result:给定 JavaScriptnumber的 C double 基本类型等价物。
如果 API 成功,则返回 napi_ok。如果传入的 napi_value 不是数字,则返回 napi_number_expected。
【Returns napi_ok if the API succeeded. If a non-number napi_value is passed
in it returns napi_number_expected.】
此 API 返回给定 JavaScript number 的 C double 基本类型等效值。
【This API returns the C double primitive equivalent of the given JavaScript
number.】
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。
【Returns napi_ok if the API succeeded. If a non-BigInt is passed in it
returns napi_bigint_expected.】
此 API 返回给定 JavaScript BigInt 的 C int64_t 原始类型等效值。如果需要,它会截断该值,并将 lossless 设置为 false。
【This API returns the C int64_t primitive equivalent of the given JavaScript
BigInt. If needed it will truncate the value, setting lossless to 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。
【Returns napi_ok if the API succeeded. If a non-BigInt is passed in it
returns napi_bigint_expected.】
此 API 返回给定 JavaScript BigInt 的 C uint64_t 原始类型等效值。如果需要,它会截断该值,并将 lossless 设置为 false。
【This API returns the C uint64_t primitive equivalent of the given JavaScript
BigInt. If needed it will truncate the value, setting lossless to 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是正数还是负数的整数。[输入/输出] word_count:必须初始化为words数组的长度。返回时,它将被设置为存储此BigInt所需的实际单词数。[out] words:指向一个预分配的64位字数组的指针。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 将单个 BigInt 值转换为符号位、64 位小端数组以及数组中的元素数量。sign_bit 和 words 都可以设置为 NULL,以仅获取 word_count。
【This API converts a single BigInt value into a sign bit, 64-bit little-endian
array, and the number of elements in the array. sign_bit and words may be
both set to NULL, in order to get only 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。
【Returns napi_ok if the API succeeded. If a non-external napi_value is
passed in it returns napi_invalid_arg.】
此 API 会检索之前传递给 napi_create_external() 的外部数据指针。
【This API retrieves the external data pointer that was previously passed to
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:napi_value,表示 JavaScript 的number。[out] result:给定 JavaScriptnumber的 Cint32原始类型等价值。
如果 API 调用成功,则返回 napi_ok。如果传入了一个非数字的 napi_value,则会出现 napi_number_expected。
【Returns napi_ok if the API succeeded. If a non-number napi_value
is passed in napi_number_expected.】
该 API 返回给定 JavaScript number 的 C int32 基本类型等效值。
【This API returns the C int32 primitive equivalent
of the given JavaScript number.】
如果数字超出了 32 位整数的范围,则结果会被截断为底部 32 位的等值。如果值大于 231 -1,这可能导致一个大的正数变为负数。
非有限数值(NaN、+Infinity 或 -Infinity)会将结果设置为零。
【Non-finite number values (NaN, +Infinity, or -Infinity) set the
result to zero.】
napi_get_value_int64#>
napi_status napi_get_value_int64(napi_env env,
napi_value value,
int64_t* result)
[in] env:调用该 API 时所处的环境。[in] value:napi_value,表示 JavaScript 的number。[out] result:给定 JavaScriptnumber的 Cint64原始等价值。
如果 API 成功,则返回 napi_ok。如果传入了非数字的 napi_value,则返回 napi_number_expected。
【Returns napi_ok if the API succeeded. If a non-number napi_value
is passed in it returns napi_number_expected.】
该 API 返回给定 JavaScript number 的 C int64 基本类型等效值。
【This API returns the C int64 primitive equivalent of the given JavaScript
number.】
number 值如果超出 Number.MIN_SAFE_INTEGER -(2**53 - 1) 到 Number.MAX_SAFE_INTEGER (2**53 - 1) 的范围,将会丢失精度。
非有限数值(NaN、+Infinity 或 -Infinity)会将结果设置为零。
【Non-finite number values (NaN, +Infinity, or -Infinity) set the
result to zero.】
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,则字符串的字节长度(不包括空字符)将返回到result中。[in] bufsize:目标缓冲区的大小。当该值不足时,返回的字符串将被截断并以空字符结尾。如果该值为零,则不会返回字符串,缓冲区也不会发生任何更改。[out] result:复制到缓冲区的字节数,不包括空终止符。
如果 API 成功,则返回 napi_ok。如果传入了非 string 类型的 napi_value,则返回 napi_string_expected。
【Returns napi_ok if the API succeeded. If a non-string napi_value
is passed in it returns napi_string_expected.】
此 API 返回与传入值对应的 ISO-8859-1 编码字符串。
【This API returns the ISO-8859-1-encoded string corresponding the value passed in.】
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,将返回字符串的字节长度(不包括空终止符)到result中。[in] bufsize:目标缓冲区的大小。当该值不足时,返回的字符串将被截断并以空字符结尾。如果该值为零,则不会返回字符串,缓冲区也不会发生任何更改。[out] result:复制到缓冲区的字节数,不包括空终止符。
如果 API 成功,则返回 napi_ok。如果传入了非 string 类型的 napi_value,则返回 napi_string_expected。
【Returns napi_ok if the API succeeded. If a non-string napi_value
is passed in it returns napi_string_expected.】
此 API 返回对应于传入值的 UTF8 编码字符串。
【This API returns the UTF8-encoded string corresponding the value passed in.】
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 字节代码单元计算,不包括空终止符)。[in] bufsize:目标缓冲区的大小。当该值不足时,返回的字符串将被截断并以空字符结尾。如果该值为零,则不会返回字符串,缓冲区也不会发生任何更改。[out] result:复制到缓冲区的 2 字节代码单元数量,不包括空终止符。
如果 API 成功,则返回 napi_ok。如果传入了非 string 类型的 napi_value,则返回 napi_string_expected。
【Returns napi_ok if the API succeeded. If a non-string napi_value
is passed in it returns napi_string_expected.】
此 API 返回对应于传入值的 UTF16 编码字符串。
【This API returns the UTF16-encoded string corresponding the value passed in.】
napi_get_value_uint32#>
napi_status napi_get_value_uint32(napi_env env,
napi_value value,
uint32_t* result)
[in] env:调用该 API 时所处的环境。[in] value:napi_value,表示 JavaScript 的number。[out] result:给定napi_value的 C 原始类型等价值,作为uint32_t。
如果 API 成功,则返回 napi_ok。如果传入了非数字的 napi_value,则返回 napi_number_expected。
【Returns napi_ok if the API succeeded. If a non-number napi_value
is passed in it returns napi_number_expected.】
该 API 返回给定 napi_value 的 C 原生等价,类型为 uint32_t。
【This API returns the C primitive equivalent of the given napi_value as a
uint32_t.】
获取全局实例的函数#>
【Functions to get global instances】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于返回用于表示给定布尔值的 JavaScript 单例对象。
【This API is used to return the JavaScript singleton object that is used to represent the given boolean value.】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回 global 对象。
【This API returns the global object.】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回 null 对象。
【This API returns the null object.】
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。
【Returns napi_ok if the API succeeded.】
此 API 返回 Undefined 对象。
【This API returns the Undefined object.】
使用 JavaScript 值和抽象操作#>
【Working with JavaScript values and abstract operations】
Node-API 提供了一组 API,用于对 JavaScript 值执行一些抽象操作。
【Node-API exposes a set of APIs to perform some abstract operations on JavaScript values.】
这些 API 支持执行以下操作之一:
【These APIs support doing one of the following:】
- 将 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。
【Returns napi_ok if the API succeeded.】
该 API 实现了 ECMAScript 语言规范 转换为布尔值部分 中定义的抽象操作 ToBoolean()。
【This API implements the abstract operation ToBoolean() as defined in
Section ToBoolean of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 实现了 ECMAScript 语言规范 第 ToNumber 节 中定义的抽象操作 ToNumber()。如果传入的值是对象,则此函数可能会运行 JS 代码。
【This API implements the abstract operation ToNumber() as defined in
Section ToNumber of the ECMAScript Language Specification.
This function potentially runs JS code if the passed-in value is an
object.】
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。
【Returns napi_ok if the API succeeded.】
该 API 实现了 ECMAScript 语言规范 转换为对象部分 中定义的抽象操作 ToObject()。
【This API implements the abstract operation ToObject() as defined in
Section ToObject of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 实现了 ECMAScript 语言规范 部分 ToString 中定义的抽象操作 ToString()。如果传入的值是对象,则此函数可能会执行 JS 代码。
【This API implements the abstract operation ToString() as defined in
Section ToString of the ECMAScript Language Specification.
This function potentially runs JS code if the passed-in value is an
object.】
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。
【Returns napi_ok if the API succeeded.】
- 如果
value的类型不是已知的 ECMAScript 类型,并且value不是 External 值,则返回napi_invalid_arg。
该 API 表现出类似于在对象上调用 typeof 运算符的行为,如 ECMAScript 语言规范 typeof 运算符 中定义的那样。然而,也存在一些差异:
【This API represents behavior similar to invoking the typeof Operator on
the object as defined in Section typeof operator of the ECMAScript Language
Specification. However, there are some differences:】
- 它支持检测外部值。
- 它将
null检测为一种独立类型,而 ECMAScript 的typeof会将其检测为object。
如果 value 的类型无效,将返回错误。
【If value has a type that is invalid, an error is returned.】
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。
【Returns napi_ok if the API succeeded.】
此 API 表示根据 ECMAScript 语言规范 Section instanceof 运算符 的定义,在对象上调用 instanceof 运算符。
【This API represents invoking the instanceof Operator on the object as
defined in Section instanceof operator of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
此 API 表示对对象调用 IsArray 操作,正如 ECMAScript 语言规范 部分 IsArray 中所定义的。
【This API represents invoking the IsArray operation on the object
as defined in Section IsArray of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 用于检查传入的 Object 是否是一个数组缓冲区。
【This API checks if the Object passed in is an array buffer.】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于检查传入的 Object 是否是缓冲区或 Uint8Array。如果调用者需要检查值是否为 Uint8Array,应该优先使用 napi_is_typedarray。
【This API checks if the Object passed in is a buffer or Uint8Array.
napi_is_typedarray should be preferred if the caller needs to check if the
value is a Uint8Array.】
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。
【Returns napi_ok if the API succeeded.】
该 API 检查传入的 Object 是否为日期。
【This API checks if the Object passed in is a date.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 用于检查传入的 Object 是否为 Error。
【This API checks if the Object passed in is an 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。
【Returns napi_ok if the API succeeded.】
这个 API 用于检查传入的 Object 是否是一个类型化数组。
【This API checks if the Object passed in is a typed array.】
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。
【Returns napi_ok if the API succeeded.】
此 API 检查传入的 Object 是否为 DataView。
【This API checks if the Object passed in is a 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。
【Returns napi_ok if the API succeeded.】
该 API 表示按照 ECMAScript 语言规范 段落 IsStrctEqual 中定义的严格相等算法的调用。
【This API represents the invocation of the Strict Equality algorithm as defined in Section IsStrctEqual of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded. If a non-detachable ArrayBuffer is
passed in it returns napi_detachable_arraybuffer_expected.】
通常,如果一个 ArrayBuffer 之前已经被分离,它就是不可分离的。引擎可能会对 ArrayBuffer 是否可分离施加额外的条件。例如,V8 要求 ArrayBuffer 必须是外部的,也就是说,是使用 napi_create_external_arraybuffer 创建的。
【Generally, an ArrayBuffer is non-detachable if it has been detached before.
The engine may impose additional conditions on whether an ArrayBuffer is
detachable. For example, V8 requires that the ArrayBuffer be external,
that is, created with napi_create_external_arraybuffer.】
此 API 表示根据 ECMAScript 语言规范 部分 detachArrayBuffer 中定义的 ArrayBuffer 分离操作的调用。
【This API represents the invocation of the ArrayBuffer detach operation as
defined in Section detachArrayBuffer of the ECMAScript Language Specification.】
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。
【Returns napi_ok if the API succeeded.】
如果 ArrayBuffer 的内部数据为 null,则认为它已被分离。
【The ArrayBuffer is considered detached if its internal data is null.】
此 API 表示调用 ECMAScript 语言规范 部分 isDetachedBuffer 中定义的 ArrayBuffer 的 IsDetachedBuffer 操作。
【This API represents the invocation of the ArrayBuffer IsDetachedBuffer
operation as defined in Section isDetachedBuffer of the ECMAScript Language
Specification.】
node_api_is_sharedarraybuffer#>
napi_status node_api_is_sharedarraybuffer(napi_env env, napi_value value, bool* result)
[in] env:调用该 API 时所处的环境。[in] value:要检查的 JavaScript 值。[out] result:给定的napi_value是否表示一个SharedArrayBuffer。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 用于检查传入的对象是否为 SharedArrayBuffer。
【This API checks if the Object passed in is a SharedArrayBuffer.】
node_api_create_sharedarraybuffer#>
napi_status node_api_create_sharedarraybuffer(napi_env env,
size_t byte_length,
void** data,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] byte_length:要创建的共享数组缓冲区的字节长度。[out] data:指向SharedArrayBuffer底层字节缓冲区的指针。可以通过传入NULL来选择性地忽略data。[out] result:一个napi_value,表示一个 JavaScriptSharedArrayBuffer。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回与 JavaScript SharedArrayBuffer 对应的 Node-API 值。SharedArrayBuffer 用于表示可以在多个 worker 之间共享的固定长度二进制数据缓冲区。
【This API returns a Node-API value corresponding to a JavaScript SharedArrayBuffer.
SharedArrayBuffers are used to represent fixed-length binary data buffers that
can be shared across multiple workers.】
分配的 SharedArrayBuffer 将具有一个底层字节缓冲区,其大小由传入的 byte_length 参数决定。 底层缓冲区可以选择返回给调用者,以便调用者直接操作该缓冲区。 这个缓冲区只能由原生代码直接写入。要从 JavaScript 写入此缓冲区,需要创建一个类型化数组或 DataView 对象。
【The SharedArrayBuffer allocated will have an underlying byte buffer whose size is
determined by the byte_length parameter that's passed in.
The underlying buffer is optionally returned back to the caller in case the
caller wants to directly manipulate the buffer. This buffer can only be
written to directly from native code. To write to this buffer from JavaScript,
a typed array or DataView object would need to be created.】
JavaScript SharedArrayBuffer 对象在 ECMAScript 语言规范的 共享数组缓冲区对象部分 中有描述。
【JavaScript SharedArrayBuffer objects are described in
Section SharedArrayBuffer objects of the ECMAScript Language Specification.】
使用 JavaScript 属性#>
【Working with JavaScript properties】
Node-API 提供了一组用于获取和设置 JavaScript 对象属性的 API。
【Node-API exposes a set of APIs to get and set properties on JavaScript objects.】
JavaScript 中的属性表示为键和值的元组。基本上,Node-API 中的所有属性键都可以表示为以下形式之一:
【Properties in JavaScript are represented as a tuple of a key and a value. Fundamentally, all property keys in Node-API can be represented in one of the following forms:】
- 命名:一个简单的 UTF8 编码字符串
- 整数索引:由
uint32_t表示的索引值 - JavaScript 值:在 Node-API 中,这些由
napi_value表示。这可以是表示string、number或symbol的napi_value。
Node-API 的值由类型 napi_value 表示。任何需要 JavaScript 值的 Node-API 调用都接受一个 napi_value。然而,确保所使用的 napi_value 符合 API 所期望的 JavaScript 类型是调用者的责任。
【Node-API values are represented by the type napi_value.
Any Node-API call that requires a JavaScript value takes in a napi_value.
However, it's the caller's responsibility to make sure that the
napi_value in question is of the JavaScript type expected by the API.】
本节中记录的 API 提供了一个简单的接口,用于获取和设置由 napi_value 表示的任意 JavaScript 对象的属性。
【The APIs documented in this section provide a simple interface to
get and set properties on arbitrary JavaScript objects represented by
napi_value.】
例如,考虑以下 JavaScript 代码片段:
【For instance, consider the following JavaScript code snippet:】
const obj = {};
obj.myProp = 123;
可以通过以下代码段使用 Node-API 值来完成等效操作:
【The equivalent can be done using Node-API values with the following snippet:】
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 代码片段:
【Indexed properties can be set in a similar manner. Consider the following JavaScript snippet:】
const arr = [];
arr[123] = 'hello';
可以通过以下代码段使用 Node-API 值来完成等效操作:
【The equivalent can be done using Node-API values with the following snippet:】
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 代码片段:
【Properties can be retrieved using the APIs described in this section. Consider the following JavaScript snippet:】
const arr = [];
const value = arr[123];
以下是 Node-API 对应物的大致等价物:
【The following is the approximate equivalent of the Node-API counterpart:】
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 示例:
【Finally, multiple properties can also be defined on an object for performance reasons. Consider the following 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 对应物的大致等价物:
【The following is the approximate equivalent of the Node-API counterpart:】
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;
结构#>
【Structures】
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 之外,它们对应于 ECMAScript 语言规范 的 区段属性 中列出的属性。它们可以是以下一个或多个位标志:
napi_default:属性上没有设置显式属性。默认情况下,属性是只读的,不可枚举且不可配置。napi_writable:该属性是可写的。napi_enumerable:该属性是可枚举的。napi_configurable:该属性是可配置的,如 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:可选的napi_value,指向一个 JavaScript 字符串或符号,用作属性的键。属性必须提供utf8name或name中的一个。value:如果属性是数据属性,则通过 get 访问属性时获取的值。如果传入了这个值,请将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的回调数据。
函数#>
【Functions】
napi_get_property_names#>
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result);
[in] env:调用 Node-API 时所处的环境。[in] 对象:要从中获取属性的对象。[out] result:一个napi_value,表示一个 JavaScript 值的数组,这些值表示对象的属性名。该 API 可以使用napi_get_array_length和napi_get_element来遍历result。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回 object 的可枚举属性名称,结果为字符串数组。object 中键为符号的属性将不会被包含在内。
【This API returns the names of the enumerable properties of object as an array
of strings. The properties of object whose key is a symbol will not be
included.】
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] 对象:要从中获取属性的对象。[in] key_mode:是否也检索原型属性。[in] key_filter:要检索哪些属性(可枚举/可读/可写)。[in] key_conversion:是否将编号属性键转换为字符串。[out] result:一个napi_value,表示一个 JavaScript 值的数组,这些值表示对象的属性名。可以使用napi_get_array_length和napi_get_element来迭代result。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回一个数组,包含该对象可用属性的名称。
【This API returns an array containing the names of the available properties of this object.】
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] 对象:要在其上设置属性的对象。[in] key:要设置的属性名称。[in] value:属性值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
这个 API 在传入的 Object 上设置了一个属性。
【This API set a property on the Object passed in.】
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] 对象:要从中获取属性的对象。[in] key:要检索的属性名称。[out] result:该属性的值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
该 API 从传入的 Object 中获取所请求的属性。
【This API gets the requested property from the Object passed in.】
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。
【Returns napi_ok if the API succeeded.】
这个 API 用于检查传入的 Object 是否具有指定的属性。
【This API checks if the Object passed in has the named property.】
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:属性删除是否成功。可以通过传入NULL来忽略result。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 尝试从 object 中删除 key 自有属性。
【This API attempts to delete the key own property from object.】
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。
【Returns napi_ok if the API succeeded.】
此 API 用于检查传入的 Object 是否具有指定的自身属性。key 必须是 string 或 symbol,否则会抛出错误。Node-API 不会在数据类型之间进行任何转换。
【This API checks if the Object passed in has the named own property. key must
be a string or a symbol, or an error will be thrown. Node-API will not
perform any conversion between data types.】
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] 对象:要在其上设置属性的对象。[in] utf8Name:要设置的属性名称。[in] value:属性值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法等同于调用 napi_set_property,并使用从传入的 utf8Name 字符串创建的 napi_value。
【This method is equivalent to calling napi_set_property with a napi_value
created from the string passed in as utf8Name.】
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] 对象:要从中获取属性的对象。[in] utf8Name:要获取的属性名称。[out] result:该属性的值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法等同于调用 napi_get_property,并使用从传入的 utf8Name 字符串创建的 napi_value。
【This method is equivalent to calling napi_get_property with a napi_value
created from the string passed in as utf8Name.】
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。
【Returns napi_ok if the API succeeded.】
此方法等同于调用 napi_has_property,并使用从传入的 utf8Name 字符串创建的 napi_value。
【This method is equivalent to calling napi_has_property with a napi_value
created from the string passed in as utf8Name.】
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] 对象:要从中设置属性的对象。[in] index:要设置的属性索引。[in] value:属性值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会在传入的 Object 上设置一个元素。
【This API sets an element on the Object passed in.】
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] 对象:要从中获取属性的对象。[in] index:要获取的属性索引。[out] result:该属性的值。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 获取请求索引处的元素。
【This API gets the element at the requested index.】
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。
【Returns napi_ok if the API succeeded.】
此 API 会返回传入的 Object 是否在请求的索引处有一个元素。
【This API returns if the Object passed in has an element at the
requested index.】
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:元素删除是否成功。可以通过传入NULL来忽略result。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 尝试从 object 中删除指定的 index。
【This API attempts to delete the specified index from object.】
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] 对象:要从中获取属性的对象。[in] property_count:properties数组中的元素数量。[in] properties:属性描述符数组。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法允许在给定对象上高效地定义多个属性。使用属性描述符(见 napi_property_descriptor)来定义属性。给定一个这样的属性描述符数组,此 API 将按照 DefineOwnProperty()(在 ECMA-262 规范的 定义自有属性部分 中描述)定义的方式,一次在对象上设置一个属性。
【This method allows the efficient definition of multiple properties on a given
object. The properties are defined using property descriptors (see
napi_property_descriptor). Given an array of such property descriptors,
this API will set the properties on the object one at a time, as defined by
DefineOwnProperty() (described in Section DefineOwnProperty of the ECMA-262
specification).】
napi_object_freeze#>
napi_status napi_object_freeze(napi_env env,
napi_value object);
[in] env:调用 Node-API 时所处的环境。[in] object:要冻结的对象。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法会冻结给定对象。这可以防止向对象添加新属性,防止删除现有属性,防止更改现有属性的可枚举性、可配置性或可写性,并防止更改现有属性的值。它还防止更改对象的原型。此内容在 ECMA-262 规范的 第 19.1.2.6 节 中有描述。
【This method freezes a given object. This prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. It also prevents the object's prototype from being changed. This is described in Section 19.1.2.6 of the ECMA-262 specification.】
napi_object_seal#>
napi_status napi_object_seal(napi_env env,
napi_value object);
[in] env:调用 Node-API 时所处的环境。[in] 对象:要封闭的对象。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法会封闭给定的对象。这可以防止向其添加新属性,并将所有现有属性标记为不可配置。这在 ECMA-262 规范的 第 19.1.2.20 节 中有描述。
【This method seals a given object. This prevents new properties from being added to it, as well as marking all existing properties as non-configurable. This is described in Section 19.1.2.20 of the ECMA-262 specification.】
使用 JavaScript 函数#>
【Working with JavaScript functions】
Node-API 提供了一组 API,允许 JavaScript 代码回调到原生代码。支持回调到原生代码的 Node-API 接受由 napi_callback 类型表示的回调函数。当 JavaScript 虚拟机回调到原生代码时,会调用提供的 napi_callback 函数。本节中记录的 API 允许回调函数执行以下操作:
【Node-API provides a set of APIs that allow JavaScript code to
call back into native code. Node-APIs that support calling back
into native code take in a callback functions represented by
the napi_callback type. When the JavaScript VM calls back to
native code, the napi_callback function provided is invoked. The APIs
documented in this section allow the callback function to do the
following:】
- 获取有关回调被调用的上下文信息。
- 获取传入回调的参数。
- 从回调函数返回一个
napi_value。
此外,Node-API 提供了一组函数,允许从本地代码调用 JavaScript 函数。可以像普通的 JavaScript 函数调用一样调用函数,也可以作为构造函数调用。
【Additionally, Node-API provides a set of functions which allow calling JavaScript functions from native code. One can either call a function like a regular JavaScript function call, or as a constructor function.】
通过 napi_property_descriptor 项的 data 字段传递给此 API 的任何非 NULL 数据都可以与 object 关联,并在 object 被垃圾回收时释放,方法是将 object 和数据一起传递给 napi_add_finalizer。
【Any non-NULL data which is passed to this API via the data field of the
napi_property_descriptor items can be associated with object and freed
whenever object is garbage-collected by passing both object and the data to
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:napi_value,表示返回的 JavaScript 对象。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法允许从本地插件调用 JavaScript 函数对象。这是从插件的本地代码回调到 JavaScript 的主要机制。对于在异步操作后调用 JavaScript 的特殊情况,请参阅 napi_make_callback。
【This method allows a JavaScript function object to be called from a native
add-on. This is the primary mechanism of calling back from the add-on's
native code into JavaScript. For the special case of calling into JavaScript
after an async operation, see napi_make_callback.】
一个示例用例可能如下所示。考虑以下 JavaScript 代码片段:
【A sample use case might look as follows. Consider the following JavaScript snippet:】
function AddTwo(num) {
return num + 2;
}
global.AddTwo = AddTwo;
然后,可以使用以下代码从本地插件调用上述函数:
【Then, the above function can be invoked from a native add-on using the following code:】
// 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] 数据:用户提供的数据上下文。当函数稍后被调用时,这些数据将传回函数中。[out] result:表示新创建函数的 JavaScript 函数对象的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 允许插件作者在本地代码中创建一个函数对象。这是从 JavaScript 调用插件本地代码的主要机制。
【This API allows an add-on author to create a function object in native code. This is the primary mechanism to allow calling into the add-on's native code from JavaScript.】
新创建的函数在此调用之后不会自动从脚本中可见。相反,必须在任何对 JavaScript 可见的对象上显式设置一个属性,才能让脚本访问该函数。
【The newly created function is not automatically visible from script after this call. Instead, a property must be explicitly set on any object that is visible to JavaScript, in order for the function to be accessible from script.】
为了将一个函数作为插件模块导出的一部分,需要将新创建的函数设置在 exports 对象上。一个示例模块可能如下所示:
【In order to expose a function as part of the add-on's module exports, set the newly created function on the exports object. A sample module might look as follows:】
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 中使用附加组件,如下所示:
【Given the above code, the add-on can be used from JavaScript as follows:】
const myaddon = require('./addon');
myaddon.sayHello();
传递给 require() 的字符串是 binding.gyp 中负责创建 .node 文件的目标名称。
【The string passed to require() is the name of the target in binding.gyp
responsible for creating the .node file.】
通过 data 参数传递给此 API 的任何非 NULL 数据都可以与生成的 JavaScript 函数(在 result 参数中返回)关联,并且可以在函数被垃圾回收时,通过将 JavaScript 函数和数据都传递给 napi_add_finalizer 来释放。
【Any non-NULL data which is passed to this API via the data parameter can
be associated with the resulting JavaScript function (which is returned in the
result parameter) and freed whenever the function is garbage-collected by
passing both the JavaScript function and the data to napi_add_finalizer.】
JavaScript Function 在 ECMAScript 语言规范的 部分函数对象 中有描述。
【JavaScript Functions are described in Section Function objects of the ECMAScript
Language Specification.】
napi_get_cb_info#>
napi_status napi_get_cb_info(napi_env env,
napi_callback_info cbinfo,
size_t* argc,
napi_value* argv,
napi_value* thisArg,
void** data)
[in] env:调用该 API 时所处的环境。[in] cbinfo:传递给回调函数的回调信息。[in-out] argc:指定提供的argv数组的长度,并接收实际的参数数量。argc可以通过传递NULL来选择性地忽略。[out] argv:要将参数复制到其中的napi_valueC 数组。如果参数数量多于提供的数量,则仅复制请求数量的参数。如果提供的参数少于声明的数量,其余的argv将填充表示undefined的napi_value值。通过传递NULL可以选择忽略argv。[out] thisArg:接收调用的 JavaScriptthis参数。通过传递NULL可以选择忽略thisArg。[out] data:接收回调的数据指针。可以通过传入NULL来选择性地忽略data。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法在回调函数中使用,用于从给定的回调信息中检索关于调用的详细信息,如参数和 this 指针。
【This method is used within a callback function to retrieve details about the
call like the arguments and the this pointer from a given callback info.】
napi_get_new_target#>
napi_status napi_get_new_target(napi_env env,
napi_callback_info cbinfo,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] cbinfo:传递给回调函数的回调信息。[out] result:构造函数调用的new.target。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回构造函数调用的 new.target。如果当前回调不是构造函数调用,则结果为 NULL。
【This API returns the new.target of the constructor call. If the current
callback is not a constructor call, the result is NULL.】
napi_new_instance#>
napi_status napi_new_instance(napi_env env,
napi_value cons,
size_t argc,
napi_value* argv,
napi_value* result)
[in] env:调用该 API 时所处的环境。[in] cons:表示要作为构造函数调用的 JavaScript 函数的napi_value。[in] argc:argv数组中元素的数量。[in] argv:作为napi_value的 JavaScript 值数组,表示构造函数的参数。如果argc为零,则可以通过传入NULL来省略此参数。[out] result:表示返回的 JavaScript 对象的napi_value,在本例中是构造的对象。
此方法用于使用给定的 napi_value(表示对象的构造函数)来实例化一个新的 JavaScript 值。例如,请考虑以下代码片段:
【This method is used to instantiate a new JavaScript value using a given
napi_value that represents the constructor for the object. For example,
consider the following snippet:】
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg);
可以使用以下代码片段在 Node-API 中近似计算以下内容:
【The following can be approximated in Node-API using the following snippet:】
// 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。
【Returns napi_ok if the API succeeded.】
对象封装#>
【Object wrap】
Node-API 提供了一种方式来“封装”C++类及其实例,以便可以从 JavaScript 调用类的构造函数和方法。
【Node-API offers a way to "wrap" C++ classes and instances so that the class constructor and methods can be called from JavaScript.】
napi_define_classAPI 定义了一个 JavaScript 类,该类包含构造函数、静态属性和方法,以及与 C++ 类对应的实例属性和方法。- 当 JavaScript 代码调用构造函数时,构造函数回调使用
napi_wrap将新的 C++ 实例封装在 JavaScript 对象中,然后返回该封装对象。 - 当 JavaScript 代码调用类的方法或属性访问器时,会调用相应的
napi_callbackC++ 函数。对于实例回调,napi_unwrap获取作为调用目标的 C++ 实例。
对于封装的对象,区分在类原型上调用的函数和在类实例上调用的函数可能很困难。解决这个问题的常用模式是保存对类构造函数的持久引用,以便以后进行 instanceof 检查。
【For wrapped objects it may be difficult to distinguish between a function
called on a class prototype and a function called on an instance of a class.
A common pattern used to address this problem is to save a persistent
reference to the class constructor for later instanceof checks.】
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...
}
一旦不再需要引用,就必须将其释放。
【The reference must be freed once it is no longer needed.】
有时 napi_instanceof() 无法确保某个 JavaScript 对象是特定原生类型的封装对象。尤其是当封装的 JavaScript 对象通过静态方法而不是作为原型方法的 this 值传回到插件时,就会出现这种情况。在这种情况下,它们可能会被错误地解包。
【There are occasions where napi_instanceof() is insufficient for ensuring that
a JavaScript object is a wrapper for a certain native type. This is the case
especially when wrapped JavaScript objects are passed back into the addon via
static methods rather than as the this value of prototype methods. In such
cases there is a chance that they may be unwrapped incorrectly.】
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() 是一个接受两个参数的方法。第一个参数是数据库句柄,第二个参数是查询句柄。在内部,它会解开第一个参数并将得到的指针转换为本地数据库句柄。然后,它会解开第二个参数并将得到的指针转换为查询句柄。如果参数顺序错误,类型转换仍然可以进行,但很有可能底层的数据库操作会失败,甚至可能导致非法内存访问。
【In the above example myAddon.queryHasRecords() is a method that accepts two
arguments. The first is a database handle and the second is a query handle.
Internally, it unwraps the first argument and casts the resulting pointer to a
native database handle. It then unwraps the second argument and casts the
resulting pointer to a query handle. If the arguments are passed in the wrong
order, the casts will work, however, there is a good chance that the underlying
database operation will fail, or will even cause an invalid memory access.】
为了确保从第一个参数获取的指针确实是指向数据库句柄的指针,以及从第二个参数获取的指针确实是指向查询句柄的指针,queryHasRecords() 的实现必须进行类型验证。在 napi_ref 中保留用于实例化数据库句柄的 JavaScript 类构造函数以及用于实例化查询句柄的构造函数会有所帮助,因为这样可以使用 napi_instanceof() 来确保传递给 queryHasRecords() 的实例确实是正确的类型。
【To ensure that the pointer retrieved from the first argument is indeed a pointer
to a database handle and, similarly, that the pointer retrieved from the second
argument is indeed a pointer to a query handle, the implementation of
queryHasRecords() has to perform a type validation. Retaining the JavaScript
class constructor from which the database handle was instantiated and the
constructor from which the query handle was instantiated in napi_refs can
help, because napi_instanceof() can then be used to ensure that the instances
passed into queryHashRecords() are indeed of the correct type.】
不幸的是,napi_instanceof() 并不能防止原型被篡改。例如,数据库句柄实例的原型可以被设置为查询句柄实例构造函数的原型。在这种情况下,数据库句柄实例可能会表现得像一个查询句柄实例,并且它将通过针对查询句柄实例的 napi_instanceof() 检测,但仍然包含指向数据库句柄的指针。
【Unfortunately, napi_instanceof() does not protect against prototype
manipulation. For example, the prototype of the database handle instance can be
set to the prototype of the constructor for query handle instances. In this
case, the database handle instance can appear as a query handle instance, and it
will pass the napi_instanceof() test for a query handle instance, while still
containing a pointer to a database handle.】
为此,Node-API 提供了类型标记功能。
【To this end, Node-API provides type-tagging capabilities.】
类型标记是一个对于插件唯一的 128 位整数。Node-API 提供了 napi_type_tag 结构用于存储类型标记。当将该值与 JavaScript 对象或存储在 napi_value 中的 外部 一起传递给 napi_type_tag_object() 时,JavaScript 对象将被“标记”类型标记。这种“标记”在 JavaScript 端是不可见的。当一个 JavaScript 对象传入本地绑定时,可以使用 napi_check_object_type_tag() 结合原始类型标记来判断该 JavaScript 对象是否之前已经被“标记”了类型标记。这就创建了一种比 napi_instanceof() 更高精度的类型检查能力,因为这种类型标记可以在原型操作和插件卸载/重载后仍然保持。
【A type tag is a 128-bit integer unique to the addon. Node-API provides the
napi_type_tag structure for storing a type tag. When such a value is passed
along with a JavaScript object or external stored in a napi_value to
napi_type_tag_object(), the JavaScript object will be "marked" with the
type tag. The "mark" is invisible on the JavaScript side. When a JavaScript
object arrives into a native binding, napi_check_object_type_tag() can be used
along with the original type tag to determine whether the JavaScript object was
previously "marked" with the type tag. This creates a type-checking capability
of a higher fidelity than napi_instanceof() can provide, because such type-
tagging survives prototype manipulation and addon unloading/reloading.】
继续上述示例,下面的基础插件实现演示了如何使用 napi_type_tag_object() 和 napi_check_object_type_tag()。
【Continuing the above example, the following skeleton addon implementation
illustrates the use of napi_type_tag_object() and
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] 构造函数:处理类实例构造的回调函数。在封装 C++ 类时,该方法必须是具有napi_callback签名的静态成员。不能使用 C++ 类构造函数。napi_callback提供了更多细节。[in] data:可选数据,将作为回调信息的data属性传递给构造函数回调。[in] property_count:properties数组参数中的项目数量。[in] properties:描述类上的静态和实例数据属性、访问器以及方法的属性描述符数组。参见napi_property_descriptor。[out] result:表示该类构造函数的napi_value。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
定义一个 JavaScript 类,包括:
【Defines a JavaScript class, including:】
- 一个具有类名的 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。
【When wrapping a C++ class, the C++ constructor callback passed via constructor
should be a static method on the class that calls the actual class constructor,
then wraps the new C++ instance in a JavaScript object, and returns the wrapper
object. See napi_wrap for details.】
从 napi_define_class 返回的 JavaScript 构造函数通常会被保存,并在稍后用于从原生代码构造该类的新实例,和/或检查提供的值是否为该类的实例。在这种情况下,为了防止该函数值被垃圾回收,可以使用 napi_create_reference 创建对它的强持久引用,从而确保引用计数保持 >= 1。
【The JavaScript constructor function returned from napi_define_class is
often saved and used later to construct new instances of the class from native
code, and/or to check whether provided values are instances of the class. In
that case, to prevent the function value from being garbage-collected, a
strong persistent reference to it can be created using
napi_create_reference, ensuring that the reference count is kept >= 1.】
通过 data 参数或 napi_property_descriptor 数组项的 data 字段传递给此 API 的任何非 NULL 数据都可以与生成的 JavaScript 构造函数(返回在 result 参数中)关联,并且可以在类被垃圾回收时通过将 JavaScript 函数和数据一起传递给 napi_add_finalizer 来释放。
【Any non-NULL data which is passed to this API via the data parameter or via
the data field of the napi_property_descriptor array items can be associated
with the resulting JavaScript constructor (which is returned in the result
parameter) and freed whenever the class is garbage-collected by passing both
the JavaScript function and the data to napi_add_finalizer.】
napi_wrap#>
napi_status napi_wrap(napi_env env,
napi_value js_object,
void* native_object,
napi_finalize finalize_cb,
void* finalize_hint,
napi_ref* result);
[in] env:调用该 API 时所处的环境。[in] js_object:将作为本地对象封装器的 JavaScript 对象。[in] native_object:将被封装到 JavaScript 对象中的本地实例。[in] finalize_cb:可选的本地回调,当 JavaScript 对象被垃圾回收时,可用于释放本地实例。napi_finalize提供了更多详细信息。[in] finalize_hint:可选的上下文提示,会传递给 finalize 回调。[out] result:可选的封装对象引用。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
将本地实例封装到 JavaScript 对象中。可以使用 napi_unwrap() 在以后检索该本地实例。
【Wraps a native instance in a JavaScript object. The native instance can be
retrieved later using napi_unwrap().】
当 JavaScript 代码调用使用 napi_define_class() 定义的类的构造函数时,会调用构造函数的 napi_callback。
在构造原生类的实例之后,回调函数必须调用 napi_wrap(),将新构造的实例封装到已经创建好的 JavaScript 对象中,该对象就是构造函数回调的 this 参数。(该 this 对象是从构造函数的 prototype 创建的,因此它已经定义了所有实例属性和方法。)
【When JavaScript code invokes a constructor for a class that was defined using
napi_define_class(), the napi_callback for the constructor is invoked.
After constructing an instance of the native class, the callback must then call
napi_wrap() to wrap the newly constructed instance in the already-created
JavaScript object that is the this argument to the constructor callback.
(That this object was created from the constructor function's prototype,
so it already has definitions of all the instance properties and methods.)】
通常在封装一个类实例时,应该提供一个 finalize 回调,该回调只需删除作为 data 参数传递给 finalize 回调的原生实例。
【Typically when wrapping a class instance, a finalize callback should be
provided that simply deletes the native instance that is received as the data
argument to the finalize callback.】
可选返回引用最初是一个弱引用,这意味着它的引用计数为0。通常在异步操作中,如果需要保持实例有效,这个引用计数会被临时增加。
【The optional returned reference is initially a weak reference, meaning it has a reference count of 0. Typically this reference count would be incremented temporarily during async operations that require the instance to remain valid.】
⚠️注意:可选返回的引用(如果获得)应仅在 finalize 回调调用时通过 napi_delete_reference 删除。如果在此之前删除,可能永远不会调用 finalize 回调。因此,在获取引用时,还需要一个 finalize 回调,以确保引用能够正确释放。
【Caution: The optional returned reference (if obtained) should be deleted via
napi_delete_reference ONLY in response to the finalize callback
invocation. If it is deleted before then, then the finalize callback may never
be invoked. Therefore, when obtaining a reference a finalize callback is also
required in order to enable correct disposal of the reference.】
终结器回调可能会被延迟,这会留下一个窗口期,在此期间对象已经被垃圾回收(弱引用无效),但终结器尚未被调用。在对 napi_wrap() 返回的弱引用使用 napi_get_reference_value() 时,你仍然应该处理空结果。
【Finalizer callbacks may be deferred, leaving a window where the object has
been garbage collected (and the weak reference is invalid) but the finalizer
hasn't been called yet. When using napi_get_reference_value() on weak
references returned by napi_wrap(), you should still handle an empty result.】
在同一个对象上第二次调用 napi_wrap() 会返回错误。要将另一个本地实例与该对象关联,请先使用 napi_remove_wrap()。
【Calling napi_wrap() a second time on an object will return an error. To
associate another native instance with the object, use napi_remove_wrap()
first.】
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。
【Returns napi_ok if the API succeeded.】
检索以前使用 napi_wrap() 封装在 JavaScript 对象中的本地实例。
【Retrieves a native instance that was previously wrapped in a JavaScript
object using napi_wrap().】
当 JavaScript 代码调用类上的方法或属性访问器时,相应的 napi_callback 会被调用。如果回调是用于实例方法或访问器,那么回调中的 this 参数就是封装对象;通过在封装对象上调用 napi_unwrap() 可以获取被调用的目标 C++ 实例。
【When JavaScript code invokes a method or property accessor on the class, the
corresponding napi_callback is invoked. If the callback is for an instance
method or accessor, then the this argument to the callback is the wrapper
object; the wrapped C++ instance that is the target of the call can be obtained
then by calling napi_unwrap() on the wrapper object.】
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。
【Returns napi_ok if the API succeeded.】
获取之前使用 napi_wrap() 封装在 JavaScript 对象 js_object 中的本地实例,并移除该封装。如果封装关联了终结回调,当 JavaScript 对象被垃圾回收时,该回调将不再被调用。
【Retrieves a native instance that was previously wrapped in the JavaScript
object js_object using napi_wrap() and removes the wrapping. If a finalize
callback was associated with the wrapping, it will no longer be called when the
JavaScript object becomes garbage-collected.】
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。
【Returns napi_ok if the API succeeded.】
将 type_tag 指针的值与 JavaScript 对象关联起来。然后可以使用 napi_check_object_type_tag() 来比较附加到对象上的标签与插件所拥有的标签,以确保对象具有正确的类型。
【Associates the value of the type_tag pointer with the JavaScript object or
external. napi_check_object_type_tag() can then be used to compare the tag
that was attached to the object with one owned by the addon to ensure that the
object has the right type.】
如果对象已经有关联的类型标记,此 API 将返回 napi_invalid_arg。
【If the object already has an associated type tag, this API will return
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。
【Returns napi_ok if the API succeeded.】
将作为 type_tag 提供的指针与 js_object 上可以找到的任何标签进行比较。如果在 js_object 上未找到标签,或者找到的标签与 type_tag 不匹配,则将 result 设置为 false。如果找到的标签与 type_tag 匹配,则将 result 设置为 true。
【Compares the pointer given as type_tag with any that can be found on
js_object. If no tag is found on js_object or, if a tag is found but it does
not match type_tag, then result is set to false. If a tag is found and it
matches type_tag, then result is set to true.】
napi_add_finalizer#>
napi_status napi_add_finalizer(napi_env env,
napi_value js_object,
void* finalize_data,
node_api_basic_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:可选的上下文提示,会传递给 finalize 回调。[out] result:可选的 JavaScript 对象引用。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
添加一个 napi_finalize 回调,当 js_object 中的 JavaScript 对象被垃圾回收时,该回调将被调用。
【Adds a napi_finalize callback which will be called when the JavaScript object
in js_object has been garbage-collected.】
可以在单个 JavaScript 对象上多次调用此 API。
【This API can be called multiple times on a single JavaScript object.】
⚠️注意:可选返回的引用(如果获得)应仅在 finalize 回调调用时通过 napi_delete_reference 删除。如果在此之前删除,可能永远不会调用 finalize 回调。因此,在获取引用时,还需要一个 finalize 回调,以确保引用能够正确释放。
【Caution: The optional returned reference (if obtained) should be deleted via
napi_delete_reference ONLY in response to the finalize callback
invocation. If it is deleted before then, then the finalize callback may never
be invoked. Therefore, when obtaining a reference a finalize callback is also
required in order to enable correct disposal of the reference.】
node_api_post_finalizer#>
napi_status node_api_post_finalizer(node_api_basic_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:可选的上下文提示,会传递给 finalize 回调。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
安排 napi_finalize 回调在事件循环中异步调用。
【Schedules a napi_finalize callback to be called asynchronously in the
event loop.】
通常,终结器会在垃圾回收器 (GC) 回收对象时被调用。在那时,调用任何可能导致 GC 状态变化的 Node-API 都会被禁用,并且会导致 Node.js 崩溃。
【Normally, finalizers are called while the GC (garbage collector) collects objects. At that point calling any Node-API that may cause changes in the GC state will be disabled and will crash Node.js.】
node_api_post_finalizer 通过允许插件将对这些 Node-API 的调用推迟到垃圾回收(GC)终结之外的时间点,从而帮助解决这一限制。
简单的异步操作#>
【Simple asynchronous operations】
插件模块通常需要利用 libuv 的异步辅助工具来实现其功能。这使它们能够安排异步执行的工作,以便在工作完成之前就返回它们的方法。这可以避免阻塞整个 Node.js 应用的执行。
【Addon modules often need to leverage async helpers from libuv as part of their implementation. This allows them to schedule work to be executed asynchronously so that their methods can return in advance of the work being completed. This allows them to avoid blocking overall execution of the Node.js application.】
Node-API 为这些支持函数提供了一个 ABI 稳定的接口,涵盖了最常见的异步使用场景。
【Node-API provides an ABI-stable interface for these supporting functions which covers the most common asynchronous use cases.】
Node-API 定义了 napi_async_work 结构,用于管理异步工作者。实例通过 napi_create_async_work 和 napi_delete_async_work 创建/删除。
【Node-API defines the napi_async_work structure which is used to manage
asynchronous workers. Instances are created/deleted with
napi_create_async_work and napi_delete_async_work.】
execute 和 complete 回调都是函数,分别在执行器准备执行时和完成任务时被调用。
【The execute and complete callbacks are functions that will be
invoked when the executor is ready to execute and when it completes its
task respectively.】
execute 函数应避免进行任何可能执行 JavaScript 或与 JavaScript 对象交互的 Node-API 调用。通常,任何需要进行 Node-API 调用的代码都应在 complete 回调中进行。避免在 execute 回调中使用 napi_env 参数,因为它很可能会执行 JavaScript。
【The execute function should avoid making any Node-API calls
that could result in the execution of JavaScript or interaction with
JavaScript objects. Most often, any code that needs to make Node-API
calls should be made in complete callback instead.
Avoid using the napi_env parameter in the execute callback as
it will likely execute JavaScript.】
这些函数实现了以下接口:
【These functions implement the following interfaces:】
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 调用时传入。
【When these methods are invoked, the data parameter passed will be the
addon-provided void* data that was passed into the
napi_create_async_work call.】
一旦创建了异步工作者,就可以使用 napi_queue_async_work 函数将其排队执行:
【Once created the async worker can be queued
for execution using the napi_queue_async_work function:】
napi_status napi_queue_async_work(node_api_basic_env env,
napi_async_work work);
如果工作在开始执行之前需要取消,可以使用 napi_cancel_async_work。
在调用 napi_cancel_async_work 之后,complete 回调将以 napi_cancelled 状态值被调用。即使工作已被取消,也不应在 complete 回调调用之前删除该工作。
【After calling napi_cancel_async_work, the complete callback
will be invoked with a status value of napi_cancelled.
The work should not be deleted before the complete
callback invocation, even when it was cancelled.】
napi_create_async_work#>
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
napi_async_work* result);
[in] env:调用该 API 时所处的环境。[in] async_resource:一个可选对象,与异步工作相关,并将传递给可能的async_hooksinit钩子。[in] async_resource_name:用于标识通过async_hooksAPI 提供的诊断信息的资源类型。[in] execute:应该调用的本地函数,用于异步执行逻辑。给定的函数会从工作线程池中调用,并且可以与主事件循环线程并行执行。[in] complete:当异步逻辑完成或被取消时将调用的本地函数。所给函数将在主事件循环线程中被调用。napi_async_complete_callback提供了更多详细信息。[in] data:用户提供的数据上下文。这将被传回到 execute 和 complete 函数中。[out] result:napi_async_work*,这是新创建的异步工作的句柄。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 分配一个工作对象,用于异步执行逻辑。一旦不再需要该工作,应使用 napi_delete_async_work 释放它。
【This API allocates a work object that is used to execute logic asynchronously.
It should be freed using napi_delete_async_work once the work is no longer
required.】
async_resource_name 应该是一个以空字符结尾的 UTF-8 编码字符串。
async_resource_name 标识符由用户提供,应该能够代表正在执行的异步工作的类型。也建议对该标识符使用命名空间,例如包含模块名称。更多信息请参见 async_hooks 文档。
【The async_resource_name identifier is provided by the user and should be
representative of the type of async work being performed. It is also recommended
to apply namespacing to the identifier, e.g. by including the module name. See
the async_hooks documentation for more information.】
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。
【Returns napi_ok if the API succeeded.】
此 API 释放先前分配的工作对象。
【This API frees a previously allocated work object.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
napi_queue_async_work#>
napi_status napi_queue_async_work(node_api_basic_env env,
napi_async_work work);
[in] env:调用该 API 时所处的环境。[in] work:由napi_create_async_work调用返回的句柄。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 请求将先前分配的工作安排执行。一旦它成功返回,就不得再次使用相同的 napi_async_work 项调用此 API,否则结果将是未定义的。
【This API requests that the previously allocated work be scheduled
for execution. Once it returns successfully, this API must not be called again
with the same napi_async_work item or the result will be undefined.】
napi_cancel_async_work#>
napi_status napi_cancel_async_work(node_api_basic_env env,
napi_async_work work);
[in] env:调用该 API 时所处的环境。[in] work:由napi_create_async_work调用返回的句柄。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 会取消尚未开始的排队工作。如果工作已开始执行,则无法取消,并会返回 napi_generic_failure。如果取消成功,complete 回调将以 napi_cancelled 的状态值被调用。在 complete 回调调用之前,即使工作已成功取消,也不应删除该工作。
【This API cancels queued work if it has not yet
been started. If it has already started executing, it cannot be
cancelled and napi_generic_failure will be returned. If successful,
the complete callback will be invoked with a status value of
napi_cancelled. The work should not be deleted before the complete
callback invocation, even if it has been successfully cancelled.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
自定义异步操作#>
【Custom asynchronous operations】
上面提到的简单异步工作 API 可能不适用于每种场景。在使用任何其他异步机制时,需要以下 API 来确保异步操作被运行时正确跟踪。
【The simple asynchronous work APIs above may not be appropriate for every scenario. When using any other asynchronous mechanism, the following APIs are necessary to ensure an asynchronous operation is properly tracked by the runtime.】
napi_async_init#>
napi_status napi_async_init(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_context* result)
[in] env:调用该 API 时所处的环境。[in] async_resource:与异步工作相关的对象,它将传递给可能的async_hooksinit钩子,并且可以通过async_hooks.executionAsyncResource()访问。[in] async_resource_name:用于标识通过async_hooksAPI 提供的诊断信息的资源类型。[out] result:初始化的异步上下文。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
async_resource 对象需要保持存活直到 napi_async_destroy,以确保 async_hooks 相关的 API 正常工作。为了与之前版本保持 ABI 兼容,napi_async_context 并不会对 async_resource 对象保持强引用,以避免引入可能的内存泄漏。然而,如果在 napi_async_context 被 napi_async_destroy 销毁之前,async_resource 被 JavaScript 引擎回收,调用 napi_async_context 相关的 API(例如 napi_open_callback_scope 和 napi_make_callback)可能会导致使用 AsyncLocalStorage API 时异步上下文丢失等问题。
【The async_resource object needs to be kept alive until
napi_async_destroy to keep async_hooks related API acts correctly. In
order to retain ABI compatibility with previous versions, napi_async_contexts
are not maintaining the strong reference to the async_resource objects to
avoid introducing causing memory leaks. However, if the async_resource is
garbage collected by JavaScript engine before the napi_async_context was
destroyed by napi_async_destroy, calling napi_async_context related APIs
like napi_open_callback_scope and napi_make_callback can cause
problems like loss of async context when using the AsyncLocalStorage API.】
为了保持与以前版本的 ABI 兼容性,传递 NULL 给 async_resource 并不会导致错误。然而,这不推荐使用,因为这会导致与 async_hooks init 钩子 和 async_hooks.executionAsyncResource() 的行为不符合预期,因为底层的 async_hooks 实现现在需要该资源以提供异步回调之间的关联。
【In order to retain ABI compatibility with previous versions, passing NULL
for async_resource does not result in an error. However, this is not
recommended as this will result in undesirable behavior with async_hooks
init hooks and async_hooks.executionAsyncResource() as the resource is
now required by the underlying async_hooks implementation in order to provide
the linkage between async callbacks.】
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。
【Returns napi_ok if the API succeeded.】
即使存在挂起的 JavaScript 异常,也可以调用此 API。
【This API can be called even if there is a pending JavaScript exception.】
napi_make_callback#>
NAPI_EXTERN napi_status napi_make_callback(napi_env env,
napi_async_context async_context,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result);
[in] env:调用该 API 时所处的环境。[in] async_context:用于调用回调的异步操作的上下文。通常,这应是先前从napi_async_init获取的值。为了保持与之前版本的 ABI 兼容性,将async_context传递为NULL不会导致错误。然而,这会导致异步钩子的操作不正确。潜在问题包括在使用AsyncLocalStorageAPI 时异步上下文丢失。[in] recv:传递给被调用函数的this值。[in] func:表示要调用的 JavaScript 函数的napi_value。[in] argc:argv数组中元素的数量。[in] argv:作为napi_value的 JavaScript 值数组,表示传递给函数的参数。如果argc为零,则可以通过传入NULL来省略此参数。[out] result:napi_value,表示返回的 JavaScript 对象。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此方法允许从本地插件调用 JavaScript 函数对象。该 API 类似于 napi_call_function。然而,它用于在从异步操作返回后(当调用栈上没有其他脚本时)从本地代码回调到 JavaScript。它是围绕 node::MakeCallback 的一个相当简单的封装。
【This method allows a JavaScript function object to be called from a native
add-on. This API is similar to napi_call_function. However, it is used to call
from native code back into JavaScript after returning from an async
operation (when there is no other script on the stack). It is a fairly simple
wrapper around node::MakeCallback.】
请注意,从 napi_async_complete_callback 内部不需要使用 napi_make_callback;在这种情况下,回调的异步上下文已经设置完毕,因此直接调用 napi_call_function 就足够且适当。在实现不使用 napi_create_async_work 的自定义异步行为时,可能需要使用 napi_make_callback 函数。
【Note it is not necessary to use napi_make_callback from within a
napi_async_complete_callback; in that situation the callback's async
context has already been set up, so a direct call to napi_call_function
is sufficient and appropriate. Use of the napi_make_callback function
may be required when implementing custom async behavior that does not use
napi_create_async_work.】
在回调期间,JavaScript 安排在微任务队列中的任何 process.nextTick 或 Promise 都会在返回到 C/C++ 之前执行。
【Any process.nextTicks or Promises scheduled on the microtask queue by
JavaScript during the callback are ran before returning back to C/C++.】
napi_open_callback_scope#>
NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env,
napi_value resource_object,
napi_async_context context,
napi_callback_scope* result)
[in] env:调用该 API 时所处的环境。[in] resource_object:与异步工作相关的对象,会传递给可能的async_hooksinit钩子。该参数已被弃用,运行时会被忽略。请改用napi_async_init中的async_resource参数。[in] context:调用回调的异步操作的上下文。这应该是之前从napi_async_init获取的值。[out] result:新创建的作用域。
有些情况下(例如,解决 promises)在调用某些 Node-API 时,必须有与回调关联的作用域存在。如果堆栈上没有其他脚本,可以使用 napi_open_callback_scope 和 napi_close_callback_scope 函数来打开/关闭所需的作用域。
【There are cases (for example, resolving promises) where it is
necessary to have the equivalent of the scope associated with a callback
in place when making certain Node-API calls. If there is no other script on
the stack the napi_open_callback_scope and
napi_close_callback_scope functions can be used to open/close
the required 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。
【This API can be called even if there is a pending JavaScript exception.】
版本管理#>
【Version management】
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_basic_env env,
const napi_node_version** version);
[in] env:调用该 API 时所处的环境。[out] version:指向 Node.js 本身版本信息的指针。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此函数会将当前运行的 Node.js 的主版本、次版本和补丁版本填充到 version 结构中,并将 release 字段填充为 process.release.name 的值。
【This function fills the version struct with the major, minor, and patch
version of Node.js that is currently running, and the release field with the
value of process.release.name.】
返回的缓冲区是静态分配的,不需要释放。
【The returned buffer is statically allocated and does not need to be freed.】
napi_get_version#>
napi_status napi_get_version(node_api_basic_env env,
uint32_t* result);
[in] env:调用该 API 时所处的环境。[out] result:支持的最高版本的 Node-API。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 返回 Node.js 运行时支持的最高 Node-API 版本。Node-API 计划是增量添加的,这样较新的 Node.js 版本可能会支持额外的 API 函数。为了允许一个插件在运行支持该函数的 Node.js 版本时使用较新的函数,同时在运行不支持该函数的 Node.js 版本时提供备用行为:
【This API returns the highest Node-API version supported by the Node.js runtime. Node-API is planned to be additive such that newer releases of Node.js may support additional API functions. In order to allow an addon to use a newer function when running with versions of Node.js that support it, while providing fallback behavior when running with Node.js versions that don't support it:】
- 调用
napi_get_version()来确定该 API 是否可用。 - 如果可用,使用
uv_dlsym()动态加载指向该函数的指针。 - 使用动态加载的指针来调用函数。
- 如果该函数不可用,请提供一个不使用该函数的替代实现。
内存管理#>
【Memory management】
napi_adjust_external_memory#>
NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_basic_env env,
int64_t change_in_bytes,
int64_t* result);
[in] env:调用该 API 时所处的环境。[in] change_in_bytes:由 JavaScript 对象保持活动状态的外部分配内存的变化量。[out] result:调整后的值。该值应反映包含给定change_in_bytes后的外部内存总量。返回值的绝对值不应被依赖。例如,具体实现可能为所有插件使用单个计数器,或者为每个插件使用各自的计数器。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此函数向运行时指示由 JavaScript 对象保留的外部分配内存的数量(即指向其自己由本地插件分配的内存的 JavaScript 对象)。注册外部分配的内存可能会,但不保证,会比平时更频繁地触发全局垃圾回收。
【This function gives the runtime an indication of the amount of externally allocated memory that is kept alive by JavaScript objects (i.e. a JavaScript object that points to its own memory allocated by a native addon). Registering externally allocated memory may, but is not guaranteed to, trigger global garbage collections more often than it would otherwise.】
该函数的调用预期应确保,附加组件不会使外部内存的减少超过其增加的外部内存量。
【This function is expected to be called in a manner such that an addon does not decrease the external memory more than it has increased the external memory.】
Promise#>
【Promises】
Node-API 提供了用于创建 Promise 对象的功能,如 ECMA 规范的 Promise 对象部分 所述。它将 Promise 实现为一对对象。当通过 napi_create_promise() 创建一个 Promise 时,会创建一个“延迟”(deferred)对象,并与 Promise 一起返回。延迟对象绑定到创建的 Promise,并且是使用 napi_resolve_deferred() 或 napi_reject_deferred() 唯一可以解决或拒绝 Promise 的方式。通过 napi_create_promise() 创建的延迟对象会被 napi_resolve_deferred() 或 napi_reject_deferred() 释放。Promise 对象可以返回给 JavaScript,在那里可以以通常的方式使用它。
【Node-API provides facilities for creating Promise objects as described in
Section Promise objects of the ECMA specification. It implements promises as a pair of
objects. When a promise is created by napi_create_promise(), a "deferred"
object is created and returned alongside the Promise. The deferred object is
bound to the created Promise and is the only means to resolve or reject the
Promise using napi_resolve_deferred() or napi_reject_deferred(). The
deferred object that is created by napi_create_promise() is freed by
napi_resolve_deferred() or napi_reject_deferred(). The Promise object may
be returned to JavaScript where it can be used in the usual fashion.】
例如,要创建一个 promise 并将其传递给异步 worker:
【For example, to create a promise and pass it to an asynchronous worker:】
napi_deferred deferred;
napi_value promise;
napi_status status;
// Create the promise.
status = napi_create_promise(env, &deferred, &promise);
if (status != napi_ok) return NULL;
// Pass the deferred to a function that performs an asynchronous action.
do_something_asynchronous(deferred);
// Return the promise to JS
return promise;
上述函数 do_something_asynchronous() 会执行其异步操作,然后它会解决或拒绝延迟对象,从而结束该 Promise 并释放延迟对象:
【The above function do_something_asynchronous() would perform its asynchronous
action and then it would resolve or reject the deferred, thereby concluding the
promise and freeing the deferred:】
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()来分别解决或拒绝相关的 Promise。[out] promise:与延迟对象关联的 JavaScript Promise。
如果 API 成功,则返回 napi_ok。
【Returns napi_ok if the API succeeded.】
此 API 创建一个延迟对象和一个 JavaScript promise。
【This API creates a deferred object and a JavaScript promise.】
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 Promise。因此,它只能用于解决可以获取到对应延迟对象的 JavaScript Promise。这实际上意味着该 Promise 必须是使用 napi_create_promise() 创建的,并且从该调用返回的延迟对象必须被保留,以便传递给此 API。
【This API resolves a JavaScript promise by way of the deferred object
with which it is associated. Thus, it can only be used to resolve JavaScript
promises for which the corresponding deferred object is available. This
effectively means that the promise must have been created using
napi_create_promise() and the deferred object returned from that call must
have been retained in order to be passed to this API.】
延迟对象在成功完成后被释放。
【The deferred object is freed upon successful completion.】
napi_reject_deferred#>
napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection);
[in] env:调用该 API 时所处的环境。[in] deferred:与之关联的将要解决的承诺的延迟对象。[in] 拒绝:用于拒绝该承诺的值。
这个 API 会通过与之关联的延迟对象拒绝一个 JavaScript Promise。因此,它只能用于拒绝其对应的延迟对象可用的 JavaScript Promise。这实际上意味着该 Promise 必须是通过 napi_create_promise() 创建的,并且从该调用中返回的延迟对象必须被保留,以便传递给此 API。
【This API rejects a JavaScript promise by way of the deferred object
with which it is associated. Thus, it can only be used to reject JavaScript
promises for which the corresponding deferred object is available. This
effectively means that the promise must have been created using
napi_create_promise() and the deferred object returned from that call must
have been retained in order to be passed to this API.】
延迟对象在成功完成后被释放。
【The deferred object is freed upon successful completion.】
napi_is_promise#>
napi_status napi_is_promise(napi_env env,
napi_value value,
bool* is_promise);
[in] env:调用该 API 时所处的环境。[in] value:要检查的值[out] is_promise:标志,指示promise是否为原生 Promise 对象(即由底层引擎创建的 Promise 对象)。
脚本执行#>
【Script execution】
Node-API 提供了一个 API,用于使用底层 JavaScript 引擎执行包含 JavaScript 的字符串。
【Node-API provides an API for executing a string containing JavaScript using the underlying JavaScript engine.】
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 代码并返回其结果,但有以下注意事项:
【This function executes a string of JavaScript code and returns its result with the following caveats:】
libuv 事件循环#>
【libuv event loop】
Node-API 提供了一个函数,用于获取与特定 napi_env 关联的当前事件循环。
【Node-API provides a function for getting the current event loop associated with
a specific napi_env.】
napi_get_uv_event_loop#>
NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_basic_env env,
struct uv_loop_s** loop);
[in] env:调用该 API 时所处的环境。[out] loop:当前的 libuv 循环实例。
注意:虽然 libuv 随着时间相对稳定,但它不提供 ABI 稳定性保证。应避免使用此函数。使用它可能导致插件在不同 Node.js 版本之间无法正常工作。异步线程安全函数调用 在许多用例中是一个替代方案。
【Note: While libuv has been relatively stable over time, it does not provide an ABI stability guarantee. Use of this function should be avoided. Its use may result in an addon that does not work across Node.js versions. asynchronous-thread-safe-function-calls are an alternative for many use cases.】
异步线程安全函数调用#>
【Asynchronous thread-safe function calls】
JavaScript 函数通常只能从本地插件的主线程调用。如果插件创建了额外的线程,那么那些需要 napi_env、napi_value 或 napi_ref 的 Node-API 函数不能从这些线程中调用。
【JavaScript functions can normally only be called from a native addon's main
thread. If an addon creates additional threads, then Node-API functions that
require a napi_env, napi_value, or napi_ref must not be called from those
threads.】
当一个插件有额外的线程,并且需要根据这些线程完成的处理来调用 JavaScript 函数时,这些线程必须与插件的主线程进行通信,以便主线程可以代表它们调用 JavaScript 函数。线程安全的函数 API 提供了一种简便的方法来实现这一点。
【When an addon has additional threads and JavaScript functions need to be invoked based on the processing completed by those threads, those threads must communicate with the addon's main thread so that the main thread can invoke the JavaScript function on their behalf. The thread-safe function APIs provide an easy way to do this.】
这些 API 提供了 napi_threadsafe_function 类型,以及用于创建、销毁和调用此类型对象的 API。
napi_create_threadsafe_function() 会为一个 napi_value 创建一个持久引用,该 napi_value 保存一个可以从多个线程调用的 JavaScript 函数。调用是异步发生的。这意味着将用于调用 JavaScript 回调的值会被放入队列中,并且队列中的每个值最终都会调用该 JavaScript 函数。
【These APIs provide the type napi_threadsafe_function as well as APIs to
create, destroy, and call objects of this type.
napi_create_threadsafe_function() creates a persistent reference to a
napi_value that holds a JavaScript function which can be called from multiple
threads. The calls happen asynchronously. This means that values with which the
JavaScript callback is to be called will be placed in a queue, and, for each
value in the queue, a call will eventually be made to the JavaScript function.】
在创建 napi_threadsafe_function 时,可以提供一个 napi_finalize 回调。当线程安全函数即将被销毁时,该回调将在主线程上被调用。它会接收在构造期间提供的上下文和终结数据,并提供一个机会用于清理线程,例如通过调用 uv_thread_join()。除了主循环线程,终结回调完成后,不应有其他线程使用该线程安全函数。
【Upon creation of a napi_threadsafe_function a napi_finalize callback can be
provided. This callback will be invoked on the main thread when the thread-safe
function is about to be destroyed. It receives the context and the finalize data
given during construction, and provides an opportunity for cleaning up after the
threads e.g. by calling uv_thread_join(). Aside from the main loop thread,
no threads should be using the thread-safe function after the finalize callback
completes.】
在调用 napi_create_threadsafe_function() 时提供的 context 可以通过在任意线程调用 napi_get_threadsafe_function_context() 来获取。
【The context given during the call to napi_create_threadsafe_function() can
be retrieved from any thread with a call to
napi_get_threadsafe_function_context().】
调用线程安全的函数#>
【Calling a thread-safe function】
napi_call_threadsafe_function() 可用于启动对 JavaScript 的调用。napi_call_threadsafe_function() 接受一个参数,用于控制 API 是否以阻塞方式运行。如果设置为 napi_tsfn_nonblocking,API 将以非阻塞方式运行,如果队列已满,则返回 napi_queue_full,阻止数据成功添加到队列中。如果设置为 napi_tsfn_blocking,API 将阻塞,直到队列中有可用空间。 如果线程安全函数的最大队列大小为 0,则 napi_call_threadsafe_function() 永远不会阻塞。
napi_call_threadsafe_function() 不应从 JavaScript 线程中以 napi_tsfn_blocking 调用,因为如果队列已满,可能会导致 JavaScript 线程死锁。
实际对 JavaScript 的调用由通过 call_js_cb 参数提供的回调控制。每当通过成功调用 napi_call_threadsafe_function() 将值放入队列时,call_js_cb 会在主线程上被调用一次。如果未提供此类回调,将使用默认回调,并且生成的 JavaScript 调用将没有参数。call_js_cb 回调会在其参数中接收到要调用的 JavaScript 函数作为 napi_value,以及创建 napi_threadsafe_function 时使用的 void* 上下文指针和由某个辅助线程创建的下一个数据指针。然后,回调可以使用诸如 napi_call_function() 的 API 调用 JavaScript。
【The actual call into JavaScript is controlled by the callback given via the
call_js_cb parameter. call_js_cb is invoked on the main thread once for each
value that was placed into the queue by a successful call to
napi_call_threadsafe_function(). If such a callback is not given, a default
callback will be used, and the resulting JavaScript call will have no arguments.
The call_js_cb callback receives the JavaScript function to call as a
napi_value in its parameters, as well as the void* context pointer used when
creating the napi_threadsafe_function, and the next data pointer that was
created by one of the secondary threads. The callback can then use an API such
as napi_call_function() to call into JavaScript.】
回调也可能在 env 和 call_js_cb 都设置为 NULL 时被调用,以表明不再可能调用 JavaScript,而队列中仍有可能需要释放的项目。这通常发生在 Node.js 进程退出时,而线程安全函数仍然处于活动状态。
【The callback may also be invoked with env and call_js_cb both set to NULL
to indicate that calls into JavaScript are no longer possible, while items
remain in the queue that may need to be freed. This normally occurs when the
Node.js process exits while there is a thread-safe function still active.】
没有必要通过 napi_make_callback() 调用 JavaScript,因为 Node-API 会在适合回调的上下文中运行 call_js_cb。
【It is not necessary to call into JavaScript via napi_make_callback() because
Node-API runs call_js_cb in a context appropriate for callbacks.】
在事件循环的每个周期中,可能会调用零个或多个排队的项目。应用不应依赖于除确保回调被调用和事件随时间推进而触发之外的特定行为。
【Zero or more queued items may be invoked in each tick of the event loop. Applications should not depend on a specific behavior other than progress in invoking callbacks will be made and events will be invoked as time moves forward.】
线程安全函数的引用计数#>
【Reference counting of thread-safe functions】
在 napi_threadsafe_function 对象存在期间,可以向其中添加和移除线程。因此,除了在创建时指定初始线程数之外,还可以调用 napi_acquire_threadsafe_function 来表示一个新线程将开始使用线程安全函数。同样,可以调用 napi_release_threadsafe_function 来表示一个现有线程将停止使用该线程安全函数。
【Threads can be added to and removed from a napi_threadsafe_function object
during its existence. Thus, in addition to specifying an initial number of
threads upon creation, napi_acquire_threadsafe_function can be called to
indicate that a new thread will start making use of the thread-safe function.
Similarly, napi_release_threadsafe_function can be called to indicate that an
existing thread will stop making use of the thread-safe function.】
napi_threadsafe_function 对象在每个使用该对象的线程都调用了 napi_release_threadsafe_function() 或在调用 napi_call_threadsafe_function 后收到 napi_closing 返回状态时会被销毁。在 napi_threadsafe_function 被销毁之前,队列会被清空。napi_release_threadsafe_function() 应该是与给定 napi_threadsafe_function 一起调用的最后一个 API,因为调用完成后,无法保证 napi_threadsafe_function 仍然被分配。出于同样的原因,在调用 napi_call_threadsafe_function 并收到 napi_closing 返回值后,不要使用线程安全函数。与 napi_threadsafe_function 相关的数据可以在传递给 napi_create_threadsafe_function() 的 napi_finalize 回调中释放。napi_create_threadsafe_function 的参数 initial_thread_count 标记了线程安全函数的初始获取次数,而不是在创建时多次调用 napi_acquire_threadsafe_function。
一旦使用 napi_threadsafe_function 的线程数变为零,就没有其他线程可以通过调用 napi_acquire_threadsafe_function() 来开始使用它。实际上,所有与之相关的后续 API 调用(除了 napi_release_threadsafe_function())都会返回 napi_closing 错误值。
【Once the number of threads making use of a napi_threadsafe_function reaches
zero, no further threads can start making use of it by calling
napi_acquire_threadsafe_function(). In fact, all subsequent API calls
associated with it, except napi_release_threadsafe_function(), will return an
error value of napi_closing.】
可以通过向 napi_release_threadsafe_function() 提供 napi_tsfn_abort 值来“中止”线程安全函数。这将导致与线程安全函数相关的所有后续 API(除了 napi_release_threadsafe_function())在其引用计数达到零之前就返回 napi_closing。特别是,napi_call_threadsafe_function() 将返回 napi_closing,从而通知线程不再可能对线程安全函数进行异步调用。这可以用作终止线程的标准。当从 napi_call_threadsafe_function() 接收到 napi_closing 返回值时,线程不得再使用该线程安全函数,因为它不再保证被分配。
【The thread-safe function can be "aborted" by giving a value of napi_tsfn_abort
to napi_release_threadsafe_function(). This will cause all subsequent APIs
associated with the thread-safe function except
napi_release_threadsafe_function() to return napi_closing even before its
reference count reaches zero. In particular, napi_call_threadsafe_function()
will return napi_closing, thus informing the threads that it is no longer
possible to make asynchronous calls to the thread-safe function. This can be
used as a criterion for terminating the thread. Upon receiving a return value
of napi_closing from napi_call_threadsafe_function() a thread must not use
the thread-safe function anymore because it is no longer guaranteed to
be allocated.】
决定是否保持进程运行#>
【Deciding whether to keep the process running】
与 libuv 句柄类似,线程安全函数可以被“引用”或“取消引用”。一个“被引用”的线程安全函数会导致它所在线程的事件循环保持活跃,直到该线程安全函数被销毁。相比之下,一个“被取消引用”的线程安全函数不会阻止事件循环退出。为此,存在 napi_ref_threadsafe_function 和 napi_unref_threadsafe_function 这些 API。
【Similarly to libuv handles, thread-safe functions can be "referenced" and
"unreferenced". A "referenced" thread-safe function will cause the event loop on
the thread on which it is created to remain alive until the thread-safe function
is destroyed. In contrast, an "unreferenced" thread-safe function will not
prevent the event loop from exiting. The APIs napi_ref_threadsafe_function and
napi_unref_threadsafe_function exist for this purpose.】
napi_unref_threadsafe_function 并不会将线程安全函数标记为可以被销毁,napi_ref_threadsafe_function 也不会阻止它被销毁。
【Neither does napi_unref_threadsafe_function mark the thread-safe functions as
able to be destroyed nor does napi_ref_threadsafe_function prevent it from
being destroyed.】
napi_create_threadsafe_function#>
NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result);
[in] env:调用该 API 时所处的环境。[in] func:一个可选的 JavaScript 函数,用于从另一个线程调用。如果在call_js_cb中传入NULL,则必须提供该函数。[in] async_resource:一个可选对象,与异步工作相关,并将传递给可能的async_hooksinit钩子。[in] async_resource_name:一个 JavaScript 字符串,用于为通过async_hooksAPI 提供的诊断信息所对应的资源类型提供标识符。[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 函数。此回调将在主线程上调用。如果未提供,将以无参数且this值为undefined的方式调用 JavaScript 函数。napi_threadsafe_function_call_js提供了更多详细信息。[out] result:异步线程安全的 JavaScript 函数。
更改历史:
-
版本 10(
NAPI_VERSION定义为10或更高):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 的线程调用。
【This API may be called from any thread which makes use of 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。
不应从 JavaScript 线程使用 napi_tsfn_blocking 调用此 API,因为如果队列已满,可能会导致 JavaScript 线程死锁。
【This API should not be called with napi_tsfn_blocking from a JavaScript
thread, because, if the queue is full, it may cause the JavaScript thread to
deadlock.】
如果从任何线程调用 napi_release_threadsafe_function() 并将 abort 设置为 napi_tsfn_abort,此 API 将返回 napi_closing。仅当 API 返回 napi_ok 时,该值才会被添加到队列中。
【This API will return napi_closing if napi_release_threadsafe_function() was
called with abort set to napi_tsfn_abort from any thread. The value is only
added to the queue if the API returns napi_ok.】
这个 API 可以从任何使用 func 的线程调用。
【This API may be called from any thread which makes use of 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 被销毁。
【A thread should call this API before passing func to any other thread-safe
function APIs to indicate that it will be making use of func. This prevents
func from being destroyed when all other threads have stopped making use of
it.】
此 API 可以从任何线程调用,该线程将开始使用 func。
【This API may be called from any thread which will start making use of 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 可能已经被销毁。
【A thread should call this API when it stops making use of func. Passing func
to any thread-safe APIs after having called this API has undefined results, as
func may have been destroyed.】
此 API 可以从任何线程调用,该线程将停止使用 func。
【This API may be called from any thread which will stop making use of func.】
napi_ref_threadsafe_function#>
NAPI_EXTERN napi_status
napi_ref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func);
[in] env:调用该 API 时所处的环境。[in] func:要引用的线程安全函数。
此 API 用于指示在主线程上运行的事件循环在 func 被销毁之前不应退出。与 uv_ref 类似,它也是幂等的。
【This API is used to indicate that the event loop running on the main thread
should not exit until func has been destroyed. Similar to uv_ref it is
also idempotent.】
napi_unref_threadsafe_function 并不会将线程安全函数标记为可销毁,napi_ref_threadsafe_function 也不会阻止其被销毁。napi_acquire_threadsafe_function 和 napi_release_threadsafe_function 可用于该目的。
【Neither does napi_unref_threadsafe_function mark the thread-safe functions as
able to be destroyed nor does napi_ref_threadsafe_function prevent it from
being destroyed. napi_acquire_threadsafe_function and
napi_release_threadsafe_function are available for that purpose.】
此 API 只能从主线程调用。
【This API may only be called from the main thread.】
napi_unref_threadsafe_function#>
NAPI_EXTERN napi_status
napi_unref_threadsafe_function(node_api_basic_env env, napi_threadsafe_function func);
[in] env:调用该 API 时所处的环境。[in] func:线程安全的取消引用函数。
此 API 用于指示在主线程上运行的事件循环可能在 func 被销毁之前退出。与 uv_unref 类似,它也是幂等的。
【This API is used to indicate that the event loop running on the main thread
may exit before func is destroyed. Similar to uv_unref it is also
idempotent.】
此 API 只能从主线程调用。
【This API may only be called from the main thread.】
其他实用工具#>
【Miscellaneous utilities】
node_api_get_module_file_name#>
NAPI_EXTERN napi_status
node_api_get_module_file_name(node_api_basic_env env, const char** result);
[in] env:调用该 API 时所处的环境。[out] result:一个包含加载该插件的绝对路径的 URL。对于本地文件系统上的文件,它将以file://开头。该字符串以空字符终止,由env所拥有,因此不能修改或释放。
result 可能是一个空字符串,如果加载插件的过程中无法在加载时确定插件的文件名。