Node-API
Node-API (ранее N-API) — это API для создания нативных модулей расширения. Он независим от базовой среды выполнения JavaScript (например, V8) и поддерживается как часть самого Node.js. Это API с гарантией стабильности интерфейса бинарных файлов (ABI) в различных версиях Node.js. Он призван изолировать модули расширения от изменений в базовом движке JavaScript и позволит модулям, скомпилированным для одной основной версии, работать в последующих основных версиях Node.js без перекомпиляции. Руководство по стабильности ABI предоставляет более подробное объяснение.
Модули расширения создаются и упаковываются с помощью тех же подходов и инструментов, что и в разделе C++ модулей расширения. Единственное отличие — набор API, используемых нативным кодом. Вместо использования API V8 или Native Abstractions for Node.js, используются функции Node-API.
API, экспонируемые Node-API, как правило, используются для создания и манипулирования значениями JavaScript. Концепции и операции, как правило, соответствуют концепциям, указанным в спецификации языка ECMA-262. API обладают следующими свойствами:
- Все вызовы Node-API возвращают код состояния типа
napi_status. Этот код указывает, был ли вызов API успешным или неудачным. - Значение возврата API передаётся через параметр вывода.
- Все значения JavaScript абстрагированы за неким типом данных с именем
napi_value. - В случае кода ошибки дополнительную информацию можно получить, используя
napi_get_last_error_info. Более подробную информацию можно найти в разделе по обработке ошибок Обработка ошибок.
Node-API — это C API, гарантирующий стабильность ABI в разных версиях Node.js и уровнях компилятора. C++ API может быть проще в использовании. Для поддержки использования C++, проект поддерживает модуль обертки для C++ под названием node-addon-api. Этот оберточный модуль предоставляет интегрируемый C++ API. Бинарные файлы, построенные с помощью node-addon-api будут зависеть от символов функций Node-API на основе C, экспортируемых Node.js. node-addon-api — более эффективный способ написания кода, который вызывает Node-API. Например, следующий node-addon-api код. Первая секция показывает node-addon-api код, а вторая секция показывает то, что фактически используется в модуле расширения.
Object obj = Object::New(env); obj["foo"] = String::New(env, "bar");
napi_status status;
napi_value object, string;
status = napi_create_object(env, &object);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, &string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_set_named_property(env, object, "foo", string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
} В итоге, модуль расширения использует только экспортируемые C API. В результате он всё ещё получает преимущества стабильности ABI, предоставляемые C API.
При использовании node-addon-api вместо C API, начинайте с документации API docs для node-addon-api.
Ресурс Node-API предоставляет отличную информацию и советы для разработчиков, только начинающих работу с Node-API и node-addon-api.
Последствия стабильности ABI
Хотя Node-API гарантирует стабильность ABI, другие части Node.js этого не гарантируют, и любые внешние библиотеки, используемые из модуля расширения, также могут не гарантировать этого. В частности, ни один из следующих API не гарантирует стабильность ABI между основными версиями:
-
API Node.js на C++, доступные через любой из
#include <node.h> #include <node_buffer.h> #include <node_version.h> #include <node_object_wrap.h>
-
API libuv, также включённые в Node.js и доступные через
#include <uv.h>
-
API V8, доступные через
#include <v8.h>
Таким образом, для того, чтобы модуль расширения оставался совместимым с ABI в разных основных версиях Node.js, он должен использовать исключительно Node-API, ограничивая себя использованием
#include <node_api.h>
и проверяя для всех внешних библиотек, которые он использует, что внешние библиотеки предоставляют гарантии стабильности ABI, аналогичные Node-API.
Компиляция
В отличие от модулей, написанных на JavaScript, разработка и развертывание нативных модулей расширения Node.js с использованием Node-API требует дополнительного набора инструментов. Помимо базовых инструментов, необходимых для разработки под Node.js, разработчик нативного модуля расширения нуждается в инструментарии, способном компилировать код C и C++ в двоичный файл. Кроме того, в зависимости от способа развертывания нативного модуля расширения, пользователю нативного модуля расширения также потребуется установленный инструментарий для C/C++.
Для разработчиков Linux необходимые пакеты инструментария C/C++ легко доступны. GCC широко используется в сообществе Node.js для построения и тестирования на различных платформах. Для многих разработчиков инфраструктура компилятора LLVM также является хорошим выбором.
Для разработчиков macOS Xcode предоставляет все необходимые инструменты компилятора. Однако не требуется устанавливать весь IDE Xcode. Следующая команда устанавливает необходимый инструментарий:
xcode-select --install
Для разработчиков Windows Visual Studio предоставляет все необходимые инструменты компилятора. Однако не требуется устанавливать весь IDE Visual Studio. Следующая команда устанавливает необходимый инструментарий:
npm install --global windows-build-tools
Разделы ниже описывают дополнительные инструменты, доступные для разработки и развертывания нативных модулей расширения Node.js.
Инструменты сборки
Для успешной установки нативного модуля расширения все инструменты, перечисленные здесь, требуют, чтобы пользователи нативного модуля расширения имели установленный инструментарий C/C++.
node-gyp
node-gyp — это система сборки, основанная на gyp-next, форке инструмента Google GYP, и поставляется в комплекте с npm. Для работы GYP, а следовательно и node-gyp, требуется установленный Python.
Исторически node-gyp был инструментом выбора для создания нативных модулей расширения. Он широко используется и имеет документацию. Однако некоторые разработчики сталкивались с ограничениями в node-gyp.
CMake.js
CMake.js — это альтернативная система сборки, основанная на CMake.
CMake.js является хорошим выбором для проектов, которые уже используют CMake, или для разработчиков, сталкивающихся с ограничениями в node-gyp.
Загрузка предварительно скомпилированных бинарных файлов
Три перечисленных ниже инструмента позволяют разработчикам и поддерживающим нативные модули расширения создавать и загружать бинарные файлы на публичные или частные серверы. Эти инструменты обычно интегрированы с системами CI/CD сборки, такими как Travis CI и AppVeyor, для сборки и загрузки бинарных файлов для различных платформ и архитектур. Затем эти бинарные файлы доступны для скачивания пользователями, которым не нужно устанавливать инструментарий C/C++.
node-pre-gyp
node-pre-gyp — это инструмент, основанный на node-gyp, который добавляет возможность загружать бинарные файлы на сервер по выбору разработчика. node-pre-gyp имеет особенно хорошую поддержку загрузки бинарных файлов в Amazon S3.
prebuild
prebuild — инструмент, поддерживающий сборку с использованием node-gyp или CMake.js. В отличие от node-pre-gyp, который поддерживает различные серверы, prebuild загружает бинарные файлы только в релизы GitHub. prebuild — хороший выбор для проектов GitHub, использующих CMake.js.
prebuildify
prebuildify — инструмент, основанный на node-gyp. Преимущество prebuildify заключается в том, что скомпилированные бинарные файлы включаются в нативный модуль при его загрузке в npm. Бинарные файлы скачиваются из npm и сразу же доступны пользователю модуля при установке нативного модуля.
Использование
Для использования функций Node-API включите файл node_api.h, который находится в каталоге src в дереве разработки Node.js:
#include <node_api.h>
Это включит настройки по умолчанию NAPI_VERSION для данной версии Node.js. Чтобы обеспечить совместимость с определёнными версиями Node-API, версию можно указать явно при включении заголовка:
#define NAPI_VERSION 3 #include <node_api.h>
Это ограничит поверхность Node-API только функциональностью, доступной в указанных (и более ранних) версиях.
Некоторая часть поверхности Node-API является экспериментальной и требует явного включения:
#define NAPI_EXPERIMENTAL #include <node_api.h>
В этом случае вся поверхность API, включая любые экспериментальные API, будет доступна коду модуля.
Матрица версий Node-API
Версии Node-API являются аддитивными и имеют независимую версионирование от Node.js. Версия 4 является расширением версии 3, включающей все API версии 3 с некоторыми дополнениями. Это означает, что нет необходимости перекомпилировать для новых версий Node.js, которые поддерживают более позднюю версию.
| 1 | 2 | 3 | |
|---|---|---|---|
| v6.x | v6.14.2* | ||
| v8.x | v8.6.0** | v8.10.0* | v8.11.2 |
| v9.x | v9.0.0* | v9.3.0* | v9.11.0* |
| ≥ v10.x | все релизы | все релизы | все релизы |
| 4 | 5 | 6 | 7 | 8 | |
|---|---|---|---|---|---|
| v10.x | v10.16.0 | v10.17.0 | v10.20.0 | v10.23.0 | |
| v11.x | v11.8.0 | ||||
| v12.x | v12.0.0 | v12.11.0 | v12.17.0 | v12.19.0 | v12.22.0 |
| v13.x | v13.0.0 | v13.0.0 | |||
| v14.x | v14.0.0 | v14.0.0 | v14.0.0 | v14.12.0 | v14.17.0 |
| v15.x | v15.0.0 | v15.0.0 | v15.0.0 | v15.0.0 | v15.12.0 |
| v16.x | v16.0.0 | v16.0.0 | v16.0.0 | v16.0.0 | v16.0.0 |
* Node-API был экспериментальным.
** Node.js 8.0.0 включал Node-API как экспериментальный. Он был выпущен как Node-API версии 1, но продолжал развиваться до Node.js 8.6.0. API отличается в версиях до Node.js 8.6.0. Рекомендуется использовать Node-API версии 3 или более поздней.
Каждая документация по Node-API будет иметь заголовок added in:, а стабильные API будут иметь дополнительный заголовок Node-API version:. API напрямую доступны при использовании версии Node.js, которая поддерживает версию Node-API, показанную в Node-API version: или выше. При использовании версии Node.js, которая не поддерживает Node-API version: или если нет Node-API version: указанной, API будет доступно только если #define NAPI_EXPERIMENTAL предшествует включению node_api.h или js_native_api.h. Если API, похоже, недоступно в версии Node.js, которая позднее, чем указанная в added in:, то это, скорее всего, причина отсутствия.
Node-API, связанные строго с доступом к функциям ECMAScript из нативного кода, можно найти отдельно в js_native_api.h и js_native_api_types.h. API, определённые в этих заголовках, включены в node_api.h и node_api_types.h. Заголовки структурированы таким образом, чтобы разрешить реализации Node-API за пределами Node.js. Для этих реализаций Node.js-специфичные API могут быть не применимы.
Node.js-специфические части дополнения могут быть отделены от кода, который предоставляет фактическую функциональность для среды JavaScript, так что последняя может использоваться с несколькими реализациями Node-API. В приведённом ниже примере addon.c и addon.h относятся только к js_native_api.h. Это гарантирует, что addon.c может быть повторно использовано для компиляции как с Node.js реализацией Node-API, так и с любой другой реализацией Node-API за пределами Node.js.
addon_node.c — это отдельный файл, содержащий Node.js-специфическую точку входа в дополнение и который инициализирует дополнение, вызывая addon.c, когда дополнение загружается в среду Node.js.
// 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 NAPI_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 (!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;
NAPI_CALL(env, napi_create_object(env, &result));
napi_value exported_function;
NAPI_CALL(env, napi_create_function(env,
"doSomethingUseful",
NAPI_AUTO_LENGTH,
DoSomethingUseful,
NULL,
&exported_function));
NAPI_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() {
// This function body is expected to return a `napi_value`.
// The variables `napi_env env` and `napi_value exports` may be used within
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
return create_addon(env);
} API жизненного цикла среды
Раздел 8.7 Спецификации языка ECMAScript определяет понятие «Агент» как автономную среду, в которой выполняется JavaScript-код. Несколько таких агентов могут быть запущены и завершены либо одновременно, либо последовательно процессом.
Среда Node.js соответствует агенту ECMAScript. В основном процессе среда создается при запуске, а дополнительные среды могут быть созданы в отдельных потоках для использования в качестве потоков-работников. Когда Node.js встроен в другое приложение, основной поток приложения также может создавать и уничтожать среду Node.js несколько раз во время жизненного цикла процесса приложения, таким образом, каждая среда Node.js, созданная приложением, может в свою очередь во время своего жизненного цикла создавать и уничтожать дополнительные среды как потоки-работники.
С точки зрения нативного дополнения это означает, что предоставляемые им привязки могут вызываться многократно, из нескольких контекстов и даже одновременно из нескольких потоков.
Нативным дополнениям может потребоваться выделение глобального состояния, которое они используют на протяжении всего своего жизненного цикла, поэтому состояние должно быть уникальным для каждого экземпляра дополнения.
Для этого Node-API предоставляет способ выделения данных, таким образом, что его жизненный цикл привязан к жизненному циклу агента.
napi_set_instance_data
napi_status napi_set_instance_data(napi_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 во время сбора.
Возвращает napi_ok если API успешно выполнено.
Этот API связывает data с текущим работающим агентом. data может быть позже получен с помощью napi_get_instance_data(). Любые существующие данные, связанные с текущим работающим агентом, которые были установлены с помощью предыдущего вызова napi_set_instance_data(), будут перезаписаны. Если finalize_cb был предоставлен предыдущим вызовом, он не будет вызван.
napi_get_instance_data
napi_status napi_get_instance_data(napi_env env,
void** data); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[out] data: Элемент данных, который был ранее связан с текущим работающим агентом вызовомnapi_set_instance_data().
Возвращает napi_ok если API успешно выполнено.
Этот API извлекает данные, которые были ранее связаны с текущим работающим агентом через napi_set_instance_data(). Если данные не установлены, вызов будет успешным, и data будет установлено в NULL.
Основные типы данных Node-API
Node-API предоставляет следующие основные типы данных в качестве абстракций, используемых различными API. Эти API следует рассматривать как непрозрачные, доступ к которым возможен только через другие вызовы Node-API.
napi_status
Целочисленный код состояния, указывающий на успех или неудачу вызова Node-API. В настоящее время поддерживаются следующие коды состояния.
typedef enum {
napi_ok,
napi_invalid_arg,
napi_object_expected,
napi_string_expected,
napi_name_expected,
napi_function_expected,
napi_number_expected,
napi_boolean_expected,
napi_array_expected,
napi_generic_failure,
napi_pending_exception,
napi_cancelled,
napi_escape_called_twice,
napi_handle_scope_mismatch,
napi_callback_scope_mismatch,
napi_queue_full,
napi_closing,
napi_bigint_expected,
napi_date_expected,
napi_arraybuffer_expected,
napi_detachable_arraybuffer_expected,
napi_would_deadlock, /* unused */
} napi_status; Если при возврате API неудачного состояния требуется дополнительная информация, ее можно получить, вызвав napi_get_last_error_info.
napi_extended_error_info
typedef struct {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
} napi_extended_error_info; -
error_message: строка UTF8, содержащая описание ошибки, нейтральное по отношению к VM. -
engine_reserved: зарезервировано для VM-специфичных деталей ошибки. В настоящее время это не реализовано ни в одном VM. -
engine_error_code: VM-специфический код ошибки. В настоящее время это не реализовано ни в одном VM. -
error_code: код состояния Node-API, связанный с последней ошибкой.
Дополнительную информацию см. в разделе Обработка ошибок.
napi_env
napi_env используется для представления контекста, который подлежащая реализация Node-API может использовать для сохранения состояния, специфичного для VM. Эта структура передается в нативные функции при их вызове и должна передаваться обратно при выполнении вызовов Node-API. Конкретно, та же napi_env, что была передана при первоначальном вызове нативной функции, должна передаваться в любые последующие вложенные вызовы Node-API. Кэширование napi_env в целях общего повторного использования и передача napi_env между экземплярами одного и того же плагина, выполняемого на разных потоках Worker, запрещено. napi_env становится недействительным при разгрузке экземпляра нативного плагина. Уведомление об этом событии доставляется через обратные вызовы, предоставленные napi_add_env_cleanup_hook и napi_set_instance_data.
napi_value
Это непрозрачный указатель, используемый для представления значения JavaScript.
napi_threadsafe_function
Это непрозрачный указатель, представляющий функцию JavaScript, которая может вызываться асинхронно из нескольких потоков через napi_call_threadsafe_function().
napi_threadsafe_function_release_mode
Значение, передаваемое napi_release_threadsafe_function() для указания, должно ли потокобезопасная функция закрываться немедленно (napi_tsfn_abort) или просто освобождаться (napi_tsfn_release) и таким образом быть доступной для последующего использования через napi_acquire_threadsafe_function() и napi_call_threadsafe_function().
typedef enum {
napi_tsfn_release,
napi_tsfn_abort
} napi_threadsafe_function_release_mode;
napi_threadsafe_function_call_mode
Значение, передаваемое napi_call_threadsafe_function() для указания, должно ли вызов блокироваться, когда очередь, связанная с потокобезопасной функцией, заполнена.
typedef enum {
napi_tsfn_nonblocking,
napi_tsfn_blocking
} napi_threadsafe_function_call_mode; Типы управления памятью Node-API
napi_handle_scope
Это абстракция, используемая для управления и изменения жизненного цикла объектов, созданных в определённом контексте. В общем случае, значения Node-API создаются в контексте области видимости handle. Когда нативная функция вызывается из JavaScript, по умолчанию существует область видимости handle. Если пользователь явно не создаёт новую область видимости handle, значения Node-API будут созданы в области видимости handle по умолчанию. Для любых вызовов кода за пределами выполнения нативной функции (например, во время вызова обратного вызова libuv), модуль должен создать область видимости перед вызовом функций, которые могут привести к созданию значений JavaScript.
Области видимости handle создаются с помощью napi_open_handle_scope и уничтожаются с помощью napi_close_handle_scope. Закрытие области видимости может указать сборщику мусора, что все napi_value , созданные за время существования области видимости handle, больше не ссылаются из текущей области видимости.
Для более подробной информации см. раздел Управление жизненным циклом объектов.
napi_escapable_handle_scope
Области видимости с возможностью освобождения – это особый тип области видимости handle, который позволяет возвращать значения, созданные внутри определённой области видимости handle, в родительскую область видимости.
napi_ref
Это абстракция, используемая для ссылки на napi_value. Это позволяет пользователям управлять жизненным циклом значений JavaScript, включая явное определение их минимальной продолжительности жизни.
Для более подробной информации см. раздел Управление жизненным циклом объектов.
napi_type_tag
Значение из 128 бит, хранящееся как два беззнаковых 64-битных целых числа. Оно используется как UUID, с помощью которого объекты JavaScript могут быть "мечены" для обеспечения того, что они относятся к определённому типу. Это более строгая проверка, чем napi_instanceof, поскольку последняя может давать ложноположительные результаты, если прототип объекта был изменён. Разметка по типу наиболее полезна в сочетании с napi_wrap, поскольку она гарантирует, что указатель, полученный из обернутого объекта, может безопасно быть приведён к нативному типу, соответствующему метке типа, которая была применена к объекту JavaScript.
typedef struct {
uint64_t lower;
uint64_t upper;
} napi_type_tag;
napi_async_cleanup_hook_handle
Непрозрачное значение, возвращаемое napi_add_async_cleanup_hook. Его необходимо передать в napi_remove_async_cleanup_hook при завершении цепочки асинхронных событий очистки.
Типы обратных вызовов Node-API
napi_callback_info
Непрозрамый тип данных, передаваемый в функцию обратного вызова. Он может использоваться для получения дополнительной информации о контексте, в котором был вызван обратный вызов.
napi_callback
Тип указателя на функцию для нативных функций, предоставляемых пользователем, которые должны быть экспонированы JavaScript через Node-API. Функции обратного вызова должны удовлетворять следующему сигнату:
typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
Если нет причин, обсуждаемых в разделе Управление жизненным циклом объектов, создание области видимости handle и/или обратного вызова внутри napi_callback не требуется.
napi_finalize
Тип указателя на функцию, предоставляемую плагином, которая позволяет пользователю получать уведомления о том, что внешние данные готовы к очистке, потому что объект, с которым они были связаны, был собран сборщиком мусора. Пользователь должен предоставить функцию, удовлетворяющую следующему сигнату, которая будет вызвана при сборе объекта. В настоящее время napi_finalize может использоваться для выяснения того, когда собираются объекты, содержащие внешние данные.
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint); Если нет причин, обсуждаемых в разделе Управление жизненным циклом объектов, создание области видимости handle и/или обратного вызова внутри тела функции не требуется.
napi_async_execute_callback
Указатель на функцию, используемый с функциями, поддерживающими асинхронные операции. Функции обратного вызова должны удовлетворять следующему сигнату:
typedef void (*napi_async_execute_callback)(napi_env env, void* data);
Реализации этой функции должны избегать выполнения вызовов Node-API, которые выполняют JavaScript или взаимодействуют с объектами JavaScript. Вызовы Node-API должны выполняться в napi_async_complete_callback вместо этого. Не используйте параметр napi_env, так как это, скорее всего, приведёт к выполнению JavaScript.
napi_async_complete_callback
Указатель на функцию, используемый с функциями, поддерживающими асинхронные операции. Функции обратного вызова должны удовлетворять следующему сигнату:
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); Если нет причин, обсуждаемых в разделе Управление жизненным циклом объектов, создание области видимости handle и/или обратного вызова внутри тела функции не требуется.
napi_threadsafe_function_call_js
Указатель на функцию, используемый при асинхронных вызовах потокобезопасных функций. Обратный вызов будет вызван в главном потоке. Его цель – использовать элемент данных, поступающий через очередь из одного из вторичных потоков, для построения параметров, необходимых для вызова в JavaScript, обычно через napi_call_function, и затем осуществить вызов в JavaScript.
Данные, поступающие из вторичного потока через очередь, передаются в параметре data, а вызываемая функция JavaScript передаётся в параметре js_callback.
Node-API устанавливает среду до вызова этого обратного вызова, поэтому достаточно вызвать функцию JavaScript с помощью napi_call_function, а не с помощью napi_make_callback.
Функции обратного вызова должны удовлетворять следующему сигнату:
typedef void (*napi_threadsafe_function_call_js)(napi_env env,
napi_value js_callback,
void* context,
void* data); -
[in] env: Окружение для вызовов API, илиNULL, если функция многопоточного выполнения разрывается, иdataможет потребоваться освободить. -
[in] js_callback: Функция JavaScript для вызова, илиNULL, если функция многопоточного выполнения разрывается, иdataможет потребоваться освободить. Она также может бытьNULL, если функция многопоточного выполнения была создана безjs_callback. -
[in] context: Необязательные данные, с которыми была создана функция многопоточного выполнения. -
[in] data: Данные, созданные вторичным потоком. Ответственность обратного вызова — преобразовать эти данные низкого уровня в значения JavaScript (с помощью функций Node-API), которые можно передавать в качестве параметров при вызовеjs_callback. Этот указатель полностью управляется потоками и этим обратным вызовом. Поэтому этот обратный вызов должен освободить данные.
Если не требуется, по причинам, обсужденным в Управлении жизненным циклом объектов, создание обработчика и/или области обратного вызова внутри тела функции не обязательно.
napi_async_cleanup_hook
Указатель на функцию, используемый с napi_add_async_cleanup_hook. Он будет вызван при разрыве окружения.
Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
void* data); -
[in] handle: Обработчик, который необходимо передать вnapi_remove_async_cleanup_hookпосле завершения асинхронной очистки. -
[in] data: Данные, которые были переданы вnapi_add_async_cleanup_hook.
Тело функции должно инициировать асинхронные действия по очистке, по окончании которых handle должно быть передано в вызове napi_remove_async_cleanup_hook.
Обработка ошибок
Node-API использует как значения возврата, так и JavaScript-исключения для обработки ошибок. В следующих разделах объясняется подход для каждого случая.
Значения возврата
Все функции Node-API используют одинаковую схему обработки ошибок. Тип возвращаемого значения всех функций API — napi_status.
Значение возврата будет napi_ok, если запрос был выполнен успешно и не было брошено неперехваченное JavaScript-исключение. Если произошла ошибка И было брошено исключение, то будет возвращено значение napi_status для ошибки. Если было брошено исключение, и ошибка не произошла, будет возвращено napi_pending_exception.
В случаях, когда возвращается значение, отличное от napi_ok или napi_pending_exception, необходимо вызвать napi_is_exception_pending, чтобы проверить, ожидается ли исключение. Подробнее см. раздел об исключениях.
Полный набор возможных значений napi_status определен в napi_api_types.h.
Значение возврата napi_status предоставляет независимое от виртуальной машины представление произошедшей ошибки. В некоторых случаях полезно получить более подробную информацию, включая строковое представление ошибки и информацию, специфичную для виртуальной машины (движка).
Для получения этой информации предоставляется napi_get_last_error_info, возвращающая структуру napi_extended_error_info. Формат структуры napi_extended_error_info следующий:
typedef struct napi_extended_error_info {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
}; -
error_message: Текстовое представление произошедшей ошибки. -
engine_reserved: Непрозрачная ручка, предназначенная только для использования движком. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. -
error_code: Код состояния Node-API для последней ошибки.
napi_get_last_error_info возвращает информацию о последнем вызове Node-API.
Не полагайтесь на содержание или формат любой дополнительной информации, так как она не подчиняется SemVer и может измениться в любое время. Она предназначена только для целей ведения журнала.
napi_get_last_error_info
napi_status
napi_get_last_error_info(napi_env env,
const napi_extended_error_info** result); -
[in] env: Среда, в которой вызывается API. -
[out] result: Структураnapi_extended_error_infoс дополнительной информацией об ошибке.
Возвращает napi_ok в случае успешного выполнения API.
Этот API получает структуру napi_extended_error_info с информацией о последней произошедшей ошибке.
Содержимое возвращаемой структуры napi_extended_error_info остается действительным до тех пор, пока функция Node-API не вызывается на той же env. Это включает вызов napi_is_exception_pending, поэтому часто необходимо создать копию информации для последующего использования. Указатель, возвращаемый в error_message, указывает на статически определённую строку, поэтому безопасно использовать этот указатель, если вы скопировали его из поля error_message (которое будет перезаписано) до вызова другой функции Node-API.
Не полагайтесь на содержание или формат любой дополнительной информации, так как она не подчиняется SemVer и может измениться в любое время. Она предназначена только для целей ведения журнала.
Этот API может быть вызван даже если ожидается JavaScript-исключение.
Исключения
Любой вызов функции Node-API может привести к возникновению ожидаемого JavaScript-исключения. Это относится ко всем функциям API, даже к тем, которые могут не вызывать выполнение JavaScript.
Если значение napi_status возвращаемое функцией, равно napi_ok, значит, исключение не ожидается, и дополнительные действия не требуются. Если возвращаемое значение napi_status отличается от napi_ok или napi_pending_exception, для попытки восстановления и продолжения, вместо немедленного возврата, необходимо вызвать napi_is_exception_pending, чтобы определить, ожидается ли исключение.
Во многих случаях, когда вызывается функция Node-API, и уже ожидается исключение, функция вернёт значение napi_status с napi_pending_exception. Однако, это не относится ко всем функциям. Node-API позволяет вызывать подмножество функций, чтобы обеспечить некоторую минимальную очистку перед возвратом в JavaScript. В этом случае, napi_status будет отражать статус для функции. Он не будет отражать предыдущие ожидающие исключения. Для избежания путаницы, проверяйте состояние ошибки после каждого вызова функции.
Когда ожидается исключение, можно использовать один из двух подходов.
Первый подход заключается в выполнении необходимой очистки, а затем возврате, чтобы передать управление JavaScript. В рамках перехода обратно в JavaScript исключение будет брошено в месте кода JavaScript, где была вызвана нативная функция. Поведение большинства вызовов Node-API не определено, пока ожидается исключение, и многие просто вернут napi_pending_exception, поэтому делайте как можно меньше действий, а затем возвращайтесь в JavaScript, где исключение можно обработать.
Второй подход заключается в попытке обработать исключение. В некоторых случаях нативный код может перехватить исключение, принять соответствующие меры и продолжить работу. Это рекомендуется только в определенных случаях, когда известно, что исключение можно безопасно обработать. В таких случаях можно использовать napi_get_and_clear_last_exception для получения и очистки исключения. При успехе result будет содержать ссылку на последнее брошенное JavaScript-исключение Object. Если после получения исключения оказывается, что его нельзя обработать, его можно повторно бросить с помощью napi_throw, где error — значение JavaScript, которое нужно бросить.
Также доступны следующие служебные функции, в случае необходимости бросить исключение или определить, является ли napi_value экземпляром JavaScript-объекта Error: napi_throw_error, napi_throw_type_error, napi_throw_range_error и napi_is_error.
Также доступны следующие служебные функции для создания объекта Error: napi_create_error, napi_create_type_error и napi_create_range_error, где result — napi_value, ссылающийся на новый созданный JavaScript-объект Error.
Проект Node.js добавляет коды ошибок ко всем ошибкам, генерируемым внутренне. Цель состоит в том, чтобы приложения использовали эти коды ошибок для всех проверок ошибок. Соответствующие сообщения об ошибках останутся, но будут использоваться только для ведения журнала и отображения, с предположением, что сообщение может быть изменено без применения SemVer. Для поддержки этой модели в Node-API, как во внутренней функциональности, так и для модульной специфической функциональности (так как это хорошая практика), функции throw_ и create_ принимают необязательный параметр code, который представляет собой строку для добавления кода в объект ошибки. Если необязательный параметр NULL, то код не будет связан с ошибкой. Если код предоставлен, имя, связанное с ошибкой, также обновляется следующим образом:
originalName [code]
где originalName — исходное имя, связанное с ошибкой, а code — предоставленный код. Например, если код 'ERR_ERROR_1', и создаётся TypeError, имя будет:
TypeError [ERR_ERROR_1]
napi_throw
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error);
-
[in] env: Среда, в которой вызывается API. -
[in] error: Значение JavaScript, которое нужно бросить.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает предоставленное значение JavaScript.
napi_throw_error
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить для ошибки. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-объект Error с предоставленным текстом.
napi_throw_type_error
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить для ошибки. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-объект TypeError с предоставленным текстом.
napi_throw_range_error
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить для ошибки. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-объект RangeError с предоставленным текстом.
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: Булевое значение, установленное в true, еслиnapi_valueпредставляет ошибку, в противном случае — false.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет napi_value на предмет того, представляет ли он объект ошибки.
napi_create_error
NAPI_EXTERN napi_status napi_create_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который будет связан с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok , если API выполнилось успешно.
Этот API возвращает JavaScript Error со предоставленным текстом.
napi_create_type_error
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который будет связан с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok , если API выполнилось успешно.
Этот API возвращает JavaScript TypeError со предоставленным текстом.
napi_create_range_error
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который будет связан с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok , если API выполнилось успешно.
Этот API возвращает JavaScript RangeError со предоставленным текстом.
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в противном случае.
Возвращает napi_ok , если API выполнилось успешно.
Этот API может быть вызван даже если ожидается JavaScript-исключение.
napi_is_exception_pending
napi_status napi_is_exception_pending(napi_env env, bool* result);
-
[in] env: Окружение, в котором вызывается API. -
[out] result: Булево значение, которое устанавливается в true, если ожидается исключение.
Возвращает napi_ok , если API выполнилось успешно.
Этот API может быть вызван даже если ожидается JavaScript-исключение.
napi_fatal_exception
napi_status napi_fatal_exception(napi_env env, napi_value err);
-
[in] env: Окружение, в котором вызывается API. -
[in] err: Ошибка, которая передается в'uncaughtException'.
Вызвать 'uncaughtException' в JavaScript. Полезно, если асинхронный обратный вызов выбрасывает исключение без возможности восстановления.
Fatal errors
В случае невосстановимой ошибки в модуле нативном языке, может быть выброшена критическая ошибка, чтобы немедленно завершить процесс.
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: Длина местоположения в байтах, илиNAPI_AUTO_LENGTHесли оно завершается нулём. -
[in] message: Сообщение, связанное с ошибкой. -
[in] message_len: Длина сообщения в байтах, илиNAPI_AUTO_LENGTHесли оно завершается нулём.
Функция не возвращает значение, процесс будет завершён.
Этот API может быть вызван даже если ожидается JavaScript-исключение.
Управление жизненным циклом объектов
При выполнении вызовов Node-API могут возвращаться дескрипторы объектов в куче для базовой виртуальной машины в виде napi_values. Эти дескрипторы должны удерживать объекты "живыми" до тех пор, пока они больше не требуются кодом нативных функций, иначе объекты могут быть собраны сборщиком мусора до завершения их использования кодом нативных функций.
Когда возвращаются дескрипторы объектов, они связываются с "областью видимости". Срок жизни по умолчанию связан со сроком жизни вызова нативной функции. В результате по умолчанию дескрипторы остаются действительными, а объекты, связанные с этими дескрипторами, будут удерживаться живыми на протяжении всего срока жизни вызова нативной функции.
Однако во многих случаях необходимо, чтобы дескрипторы оставались действительными в течение срока жизни, который короче или длиннее, чем срок жизни нативной функции. В следующих разделах описаны функции Node-API, которые можно использовать для изменения срока жизни дескрипторов от значения по умолчанию.
Сокращение срока жизни дескрипторов по сравнению со сроком жизни нативной функции
Часто необходимо сделать срок жизни дескрипторов короче срока жизни нативной функции. Например, рассмотрим нативную функцию, которая содержит цикл, перебирающий элементы в большом массиве:
for (int i = 0; i < 1000000; i++) {
napi_value result;
napi_status status = napi_get_element(env, object, i, &result);
if (status != napi_ok) {
break;
}
// do something with element
} Это приведет к созданию большого числа дескрипторов, что потребует значительных ресурсов. Кроме того, даже если код нативной функции может использовать только последний дескриптор, все связанные объекты также будут храниться в живом состоянии, поскольку они все принадлежат одной и той же области видимости.
Для решения этой проблемы Node-API предоставляет возможность создания новых "областей видимости", к которым будут привязаны вновь созданные дескрипторы. После того, как эти дескрипторы больше не понадобятся, область видимости можно "закрыть", и все дескрипторы, связанные с этой областью видимости, будут аннулированы. Доступные методы для открытия/закрытия областей видимости — napi_open_handle_scope и napi_close_handle_scope.
Node-API поддерживает только одну вложенную иерархию областей видимости. В любой момент времени активна только одна область видимости, и все новые дескрипторы будут связаны с этой областью видимости, пока она активна. Области видимости должны закрываться в обратном порядке к тому, в котором они открывались. Кроме того, все области видимости, созданные в рамках нативной функции, должны быть закрыты перед возвратом из этой функции.
Применительно к предыдущему примеру добавление вызовов napi_open_handle_scope и napi_close_handle_scope обеспечит, что не более одного дескриптора будет действительным на протяжении всего выполнения цикла:
for (int i = 0; i < 1000000; i++) {
napi_handle_scope scope;
napi_status status = napi_open_handle_scope(env, &scope);
if (status != napi_ok) {
break;
}
napi_value result;
status = napi_get_element(env, object, i, &result);
if (status != napi_ok) {
break;
}
// do something with element
status = napi_close_handle_scope(env, scope);
if (status != napi_ok) {
break;
}
} При вложенности областей видимости существуют случаи, когда дескриптор из внутренней области видимости должен существовать дольше, чем срок жизни этой области видимости. Node-API поддерживает "извлекаемую область видимости" для поддержки этого случая. Извлекаемая область видимости позволяет одному дескриптору быть "продвинутым", так что он "выходит" из текущей области видимости, и срок жизни дескриптора меняется с текущей области видимости на внешнюю.
Доступные методы для открытия/закрытия извлекаемых областей видимости — napi_open_escapable_handle_scope и napi_close_escapable_handle_scope.
Запрос на продвижение дескриптора выполняется через napi_escape_handle, который может быть вызван только один раз.
napi_open_handle_scope
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
napi_handle_scope* result); -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющий новую область видимости.
Возвращает napi_ok если API выполнился успешно.
Этот API открывает новую область видимости.
napi_close_handle_scope
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
napi_handle_scope scope); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий область видимости, которую необходимо закрыть.
Возвращает napi_ok если API выполнился успешно.
Этот API закрывает переданную область видимости. Области видимости должны закрываться в обратном порядке их открытия.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
napi_open_escapable_handle_scope
NAPI_EXTERN napi_status
napi_open_escapable_handle_scope(napi_env env,
napi_handle_scope* result); -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющий новую область видимости.
Возвращает napi_ok если API выполнился успешно.
Этот API открывает новую область видимости, из которой один объект может быть продвинут во внешнюю область видимости.
napi_close_escapable_handle_scope
NAPI_EXTERN napi_status
napi_close_escapable_handle_scope(napi_env env,
napi_handle_scope scope); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий область видимости, которую необходимо закрыть.
Возвращает napi_ok если API выполнился успешно.
Этот API закрывает переданную область видимости. Области видимости должны закрываться в обратном порядке их открытия.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
napi_escape_handle
napi_status napi_escape_handle(napi_env env,
napi_escapable_handle_scope scope,
napi_value escapee,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий текущую область видимости. -
[in] escapee:napi_valueпредставляющий JavaScriptObjectдля извлечения. -
[out] result:napi_valueпредставляющий дескриптор извлеченногоObjectво внешней области видимости.
Возвращает napi_ok если API выполнился успешно.
Этот API продвигает дескриптор объекта JavaScript, чтобы он был действительным на протяжении всего срока жизни внешней области видимости. Он может быть вызван только один раз на область видимости. Если он вызывается более одного раза, будет возвращено сообщение об ошибке.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
Ссылки на объекты со сроком жизни, превышающим срок жизни нативной функции
В некоторых случаях дополнению потребуется возможность создавать и ссылаться на объекты со сроком жизни, превышающим срок действия одного вызова нативной функции. Например, для создания конструктора и последующего использования этого конструктора в запросе на создание экземпляров необходимо иметь возможность ссылаться на объект конструктора через множество различных запросов на создание экземпляров. Это невозможно с обычным дескриптором, возвращаемым в качестве napi_value, как описано в предыдущем разделе. Срок жизни обычного дескриптора управляется областями видимости, и все области видимости должны быть закрыты перед завершением нативной функции.
Node-API предоставляет методы для создания постоянных ссылок на объект. Каждая постоянная ссылка имеет связанный счетчик со значением 0 или выше. Счетчик определяет, будет ли ссылка удерживать соответствующий объект живым. Ссылки со счетчиком 0 не препятствуют сбору мусора и часто называются "слабыми" ссылками. Любой счетчик, больший 0, предотвратит сборку мусора объекта.
Ссылки могут быть созданы с начальным значением счетчика. Затем счетчик можно изменить с помощью napi_reference_ref и napi_reference_unref. Если объект собирается, а счетчик ссылки равен 0, все последующие вызовы получения объекта, связанного с ссылкой napi_get_reference_value, вернут NULL для возвращаемого napi_value. Попытка вызвать napi_reference_ref для ссылки, объект которой был собран, приводит к ошибке.
Ссылки должны быть удалены, когда они больше не нужны дополнению. При удалении ссылки она больше не будет препятствовать сбору мусора соответствующего объекта. Отсутствие удаления постоянной ссылки приводит к утечке памяти, при которой и нативная память для постоянной ссылки, и соответствующий объект в куче сохраняются навсегда.
Могут быть созданы несколько постоянных ссылок, которые ссылаются на один и тот же объект, каждая из которых будет удерживать объект живым или нет, в зависимости от ее собственного счетчика.
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представляющийObjectдля которого требуется ссылка. -
[in] initial_refcount: Начальное значение счетчика ссылок для новой ссылки. -
[out] result:napi_refуказывающий на новую ссылку.
Возвращает napi_ok если API выполнился успешно.
Этот API создает новую ссылку со значением счетчика ссылок, заданным для Object переданного объекта.
napi_delete_reference
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref);
-
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_refдля удаления.
Возвращает napi_ok если API выполнился успешно.
Этот API удаляет переданную ссылку.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
napi_reference_ref
NAPI_EXTERN napi_status napi_reference_ref(napi_env env,
napi_ref ref,
uint32_t* result); -
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_refдля которой нужно увеличить счетчик ссылок. -
[out] result: Новое значение счетчика ссылок.
Возвращает napi_ok если API выполнился успешно.
Этот API увеличивает счетчик ссылок для переданной ссылки и возвращает полученное значение счетчика ссылок.
napi_reference_unref
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
napi_ref ref,
uint32_t* result); -
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_refдля которой нужно уменьшить счетчик ссылок. -
[out] result: Новое значение счетчика ссылок.
Возвращает napi_ok если API выполнился успешно.
Этот API уменьшает счетчик ссылок для переданной ссылки и возвращает полученное значение счетчика ссылок.
napi_get_reference_value
NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,
napi_ref ref,
napi_value* result); переменная napi_value passed в этих методах — это дескриптор объекта, к которому относится ссылка.
-
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_ref, для которого запрашивается соответствующийObject. -
[out] result:napi_valueдляObject, на который ссылаетсяnapi_ref.
Возвращает napi_ok в случае успешного выполнения API.
Если значение still valid, этот API возвращает napi_value , представляющее JavaScript Object , связанное с napi_ref. В противном случае результат будет NULL.
Очистка при выходе текущего экземпляра Node.js
Хотя процесс Node.js обычно освобождает все свои ресурсы при выходе, разработчики Node.js или поддержка будущих рабочих процессов могут потребовать от дополнений зарегистрировать обработчики очистки, которые будут выполнены после выхода текущего экземпляра Node.js.
Node-API предоставляет функции для регистрации и отмены регистрации таких обратных вызовов. При выполнении этих обратных вызовов все ресурсы, удерживаемые дополнением, должны быть освобождены.
napi_add_env_cleanup_hook
NODE_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env,
void (*fun)(void* arg),
void* arg); Регистрирует fun как функцию, которая будет выполнена с параметром arg после завершения работы текущей среды Node.js.
Функцию можно безопасно указать несколько раз с различными значениями arg. В этом случае она будет вызвана несколько раз. Указание одинаковых значений fun и arg несколько раз запрещено и приведет к прерыванию процесса.
Обработчики будут вызваны в обратном порядке, т.е. последний добавленный будет вызван первым.
Удалить этот обработчик можно с помощью napi_remove_env_cleanup_hook. Обычно это происходит, когда ресурс, для которого был добавлен этот обработчик, всё равно уничтожается.
Для асинхронной очистки доступна функция napi_add_async_cleanup_hook.
napi_remove_env_cleanup_hook
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env,
void (*fun)(void* arg),
void* arg); Отменяет регистрацию fun как функции, которая будет выполнена с параметром arg после завершения работы текущей среды Node.js. И аргумент, и значение функции должны быть точными.
Функция должна была быть первоначально зарегистрирована с помощью napi_add_env_cleanup_hook, в противном случае процесс будет прерван.
napi_add_async_cleanup_hook
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
napi_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, как функцию, которая будет выполнена с параметрами remove_handle и arg после выхода из текущей среды Node.js.
В отличие от napi_add_env_cleanup_hook, обработчик может быть асинхронным.
В остальном поведение в целом соответствует napi_add_env_cleanup_hook.
Если remove_handle не равно NULL, в него будет сохранено неявное значение, которое необходимо передать в napi_remove_async_cleanup_hook, независимо от того, был ли уже вызван обработчик. Обычно это происходит, когда ресурс, для которого был добавлен этот обработчик, всё равно уничтожается.
napi_remove_async_cleanup_hook
NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(
napi_async_cleanup_hook_handle remove_handle); -
[in] remove_handle: Дескриптор асинхронного обработчика очистки, созданного с помощьюnapi_add_async_cleanup_hook.
Отменяет регистрацию обработчика очистки, соответствующего remove_handle. Это предотвратит выполнение обработчика, если он еще не начал выполняться. Этот метод необходимо вызвать для любого значения napi_async_cleanup_hook_handle, полученного из napi_add_async_cleanup_hook.
Регистрация модулей
Модули Node-API регистрируются аналогично другим модулям, за исключением того, что вместо использования макроса NODE_MODULE используется следующее:
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
Следующее отличие — сигнатура метода Init. Для модуля Node-API она имеет следующий вид:
napi_value Init(napi_env env, napi_value exports);
Возвращаемое значение метода Init рассматривается как объект exports для модуля. Метод Init получает пустой объект через параметр exports для удобства. Если Init возвращает NULL, параметр, переданный как exports , экспортируется модулем. Модули Node-API не могут изменять объект module, но могут задать любое значение в качестве свойства exports модуля.
Чтобы добавить метод hello как функцию, чтобы его можно было вызывать как метод, предоставляемый дополнением:
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor desc = {
"hello",
NULL,
Method,
NULL,
NULL,
NULL,
napi_writable | napi_enumerable | napi_configurable,
NULL
};
status = napi_define_properties(env, exports, 1, &desc);
if (status != napi_ok) return NULL;
return exports;
} Чтобы установить функцию, которая будет возвращаться методом require() для дополнения:
napi_value Init(napi_env env, napi_value exports) {
napi_value method;
napi_status status;
status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method);
if (status != napi_ok) return NULL;
return method;
} Чтобы определить класс, чтобы можно было создавать новые экземпляры (часто используется с обёрткой объекта):
// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor properties[] = {
{ "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
};
napi_value cons;
status =
napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
if (status != napi_ok) return NULL;
status = napi_create_reference(env, cons, 1, &constructor);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "MyObject", cons);
if (status != napi_ok) return NULL;
return exports;
} Вы также можете использовать макрос NAPI_MODULE_INIT, который действует как сокращение для NAPI_MODULE и определения функции Init:
NAPI_MODULE_INIT() {
napi_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;
} Все дополнения Node-API обладают контекстной осведомленностью, что означает, что они могут загружаться несколько раз. При объявлении такого модуля необходимо учитывать некоторые аспекты проектирования. Более подробную информацию см. в документации по модулям с контекстной осведомленностью.
Переменные env и exports будут доступны внутри тела функции после вызова макроса.
Дополнительную информацию о настройке свойств объектов см. в разделе Работа со свойствами JavaScript.
Для получения дополнительной информации о создании модулей дополнений в целом см. существующий API.
Работа с JavaScript-значениями
Node-API предоставляет набор API для создания всех типов JavaScript-значений. Некоторые из этих типов задокументированы в разделе 6 Спецификации языка ECMAScript.
В основе этих API лежит выполнение одного из следующих действий:
- Создание нового JavaScript-объекта
- Преобразование примитивного C-типа в значение Node-API
- Преобразование значения Node-API в примитивный C-тип
- Получение глобальных экземпляров, включая
undefinedиnull
Значения Node-API представляются типом napi_value. Любой вызов Node-API, требующий JavaScript-значения, принимает napi_value. В некоторых случаях API предварительно проверяет тип napi_value. Однако для лучшей производительности лучше, чтобы вызывающая сторона убедилась, что napi_value имеет ожидаемый JavaScript-тип, необходимый для API.
Типы перечислений
napi_key_collection_mode
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode; Описывает перечисления фильтров Keys/Properties:
napi_key_collection_mode ограничивает диапазон собранных свойств.
napi_key_own_only ограничивает собранные свойства только заданным объектом. napi_key_include_prototypes также будет включать все ключи цепочки прототипов объектов.
napi_key_filter
typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter; Биты фильтра свойств. Они могут быть объединены с помощью оператора OR для создания составного фильтра.
napi_key_conversion
typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion; napi_key_numbers_to_strings преобразует целочисленные индексы в строки. napi_key_keep_numbers вернёт числа для целочисленных индексов.
napi_valuetype
typedef enum {
// ES6 types (corresponds to typeof)
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
napi_bigint,
} napi_valuetype; Описывает тип napi_value. В целом он соответствует типам, описанным в разделе 6.1 Спецификации языка ECMAScript. В дополнение к типам в этом разделе, napi_valuetype также может представлять Function и Object с внешними данными.
JavaScript-значение типа napi_external отображается в JavaScript как обычный объект, к которому нельзя добавить свойства и у которого нет прототипа.
napi_typedarray_type
typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
napi_bigint64_array,
napi_biguint64_array,
} napi_typedarray_type; Это представляет собой основной бинарный скалярный тип данных TypedArray. Элементы этого перечисления соответствуют разделу 22.2 Спецификации языка ECMAScript.
Функции создания объектов
napi_create_array
napi_status napi_create_array(napi_env env, napi_value* result)
-
[in] env: Среда, в которой вызывается вызов Node-API. -
[out] result:napi_value, представляющий JavaScript-Array.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает значение Node-API, соответствующее типу JavaScript-Array. JavaScript-массивы описаны в разделе 22.1 Спецификации языка ECMAScript.
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:napi_value, представляющий JavaScript-Array.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает значение Node-API, соответствующее типу JavaScript-Array. Свойство длины Array устанавливается в переданное значение параметра длины. Однако подлежащий буфер не гарантируется предварительно выделенным виртуальной машиной при создании массива. Это поведение оставляется на усмотрение реализации подлежащей виртуальной машины. Если буфер должен быть непрерывным блоком памяти, который можно непосредственно читать и/или записывать через C, воспользуйтесь napi_create_external_arraybuffer.
JavaScript-массивы описаны в разделе 22.1 Спецификации языка ECMAScript.
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. -
[out] result:napi_value, представляющий JavaScript-ArrayBuffer.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает значение Node-API, соответствующее JavaScript-ArrayBuffer. ArrayBuffer используются для представления буферов фиксированной длины бинарных данных. Они обычно используются в качестве буфера для TypedArray объектов. Выделенный ArrayBuffer будет иметь подлежащий байтовый буфер, размер которого определяется параметром length, переданным в API. Подлежащий буфер опционально возвращается вызывающей стороне в случае, если она хочет напрямую манипулировать буфером. К этому буферу можно напрямую обращаться только из кода нативных языках. Для записи в этот буфер из JavaScript требуется создание объекта типа массива или DataView объекта.
JavaScript-объекты ArrayBuffer описаны в разделе 24.1 Спецификации языка ECMAScript.
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: Сырой указатель на подлежащий буфер. -
[out] result:napi_value, представляющийnode::Buffer.
Возвращает napi_ok при успешном выполнении API.
Этот API выделяет объект node::Buffer. Хотя эта структура данных полностью поддерживается, в большинстве случаев достаточно использования TypedArray.
napi_create_buffer_copy
napi_status napi_create_buffer_copy(napi_env env,
size_t length,
const void* data,
void** result_data,
napi_value* result) -
[in] env: Среда, в которой вызывается API. -
[in] size: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Сырой указатель на подлежащий буфер для копирования. -
[out] result_data: Указатель на новый подлежащий буфер данныхBuffer. -
[out] result:napi_value, представляющийnode::Buffer.
Возвращает napi_ok при успешном выполнении API.
Этот API выделяет объект node::Buffer и инициализирует его данными, скопированными из переданного буфера. Хотя эта структура данных полностью поддерживается, в большинстве случаев достаточно использования TypedArray.
napi_create_date
napi_status napi_create_date(napi_env env,
double time,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] time: Значение времени ECMAScript в миллисекундах с 01 января 1970 года по UTC. -
[out] result:napi_value, представляющий JavaScript-Date.
Возвращает napi_ok при успешном выполнении API.
Этот API не учитывает високосные секунды; они игнорируются, так как ECMAScript соответствует спецификации времени POSIX.
Этот API выделяет JavaScript-объект Date.
JavaScript-объекты Date описаны в разделе 20.3 Спецификации языка ECMAScript.
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представляющий внешнее значение.
Возвращает napi_ok при успешном выполнении API.
Этот API выделяет JavaScript-значение с присоединенными к нему внешними данными. Это используется для передачи внешних данных в JavaScript-код, чтобы их можно было получить позже с помощью кода нативного языка, используя napi_get_value_external.
API добавляет обработчик napi_finalize, который будет вызван, когда только что созданный JavaScript-объект готов для сборки мусора. Он похож на napi_wrap(), за исключением:
- данные нативного языка не могут быть получены позже с помощью
napi_unwrap(), - их нельзя удалить позже с помощью
napi_remove_wrap(), и - созданный API объект может быть использован с
napi_wrap().
Созданное значение не является объектом и, следовательно, не поддерживает дополнительные свойства. Оно рассматривается как отдельный тип значения: вызов napi_typeof() с внешним значением даёт napi_external.
napi_create_external_arraybuffer
napi_status
napi_create_external_arraybuffer(napi_env env,
void* external_data,
size_t byte_length,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) - Окружение, в котором вызывается API.
- Указатель на базовый байтовый буфер
ArrayBuffer. - Длина базового буфера в байтах.
- Необязательный обратный вызов, который вызывается, когда объект
ArrayBufferсобирается для удаления.napi_finalizeсодержит подробности. - Необязательный параметр, передаваемый обратному вызову finalize при сборе.
- Объект
napi_value, представляющий JavaScript-объектArrayBuffer.
Возвращает napi_ok, если API успешно выполнено.
Этот API возвращает значение Node-API, соответствующее JavaScript-объекту ArrayBuffer. Базовый байтовый буфер ArrayBuffer выделяется и управляется внешним образом. Вызывающая сторона должна гарантировать, что байтовый буфер остается валидным до тех пор, пока не будет вызван обратный вызов finalize.
API добавляет обратный вызов napi_finalize, который будет вызван, когда созданный JavaScript-объект готов к сборке мусора. Он похож на napi_wrap(), за исключением:
- невозможность получить доступ к данным позже с помощью
napi_unwrap(), - невозможность удалить объект позже с помощью
napi_remove_wrap(), и - созданный API объект может быть использован с
napi_wrap().
JavaScript-объекты ArrayBuffer описаны в разделе 24.1 спецификации языка ECMAScript.
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) - Окружение, в котором вызывается API.
- Размер входного буфера в байтах (должен быть таким же, как размер нового буфера).
- Сырой указатель на базовый буфер, который необходимо экспонировать для JavaScript.
- Необязательный обратный вызов, который вызывается, когда объект
ArrayBufferсобирается для удаления.napi_finalizeсодержит подробности. - Необязательный параметр, передаваемый обратному вызову finalize при сборе.
- Объект
napi_value, представляющий JavaScript-объектnode::Buffer.
Возвращает napi_ok, если API успешно выполнено.
Этот API выделяет объект node::Buffer и инициализирует его данными, поддерживаемыми переданным буфером. Хотя это по-прежнему полностью поддерживаемая структура данных, в большинстве случаев использование TypedArray будет достаточным.
API добавляет обратный вызов napi_finalize, который будет вызван, когда созданный JavaScript-объект готов к сборке мусора. Он похож на napi_wrap(), за исключением:
- невозможность получить доступ к данным позже с помощью
napi_unwrap(), - невозможность удалить объект позже с помощью
napi_remove_wrap(), и - созданный API объект может быть использован с
napi_wrap().
Для Node.js >=4 Buffers являются Uint8Array.
napi_create_object
napi_status napi_create_object(napi_env env, napi_value* result)
- Окружение, в котором вызывается API.
- Объект
napi_value, представляющий JavaScript-объектObject.
Возвращает napi_ok, если API успешно выполнено.
Этот API выделяет стандартный JavaScript-объект Object. Это эквивалентно выполнению new Object() в JavaScript.
Тип JavaScript-объекта Object описан в разделе 6.1.7 спецификации языка ECMAScript.
napi_create_symbol
napi_status napi_create_symbol(napi_env env,
napi_value description,
napi_value* result) - Окружение, в котором вызывается API.
- Необязательный
napi_value, который ссылается на JavaScript-объектstring, который будет установлен в качестве описания для символа. - Объект
napi_value, представляющий JavaScript-символsymbol.
Возвращает napi_ok, если API успешно выполнено.
Этот API создает JavaScript-значение symbol из UTF8-строки C.
Тип JavaScript-символа symbol описан в разделе 19.4 спецификации языка ECMAScript.
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) - Окружение, в котором вызывается API.
- Скалярный тип данных элементов в
TypedArray. - Количество элементов в
TypedArray. - Базовый буфер
ArrayBufferдля типизированного массива. - Смещение в байтах в
ArrayBufferот которого следует начать проектированиеTypedArray. - Объект
napi_value, представляющий JavaScript-объектTypedArray.
Возвращает napi_ok, если API успешно выполнено.
Этот API создает JavaScript-объект TypedArray над существующим ArrayBuffer. Объекты TypedArray предоставляют представление типа массив над базовым буфером данных, где каждый элемент имеет тот же базовый бинарный скалярный тип данных.
Требуется, чтобы (length * size_of_element) + byte_offset было меньше или равно размеру в байтах переданного массива. В противном случае возникает исключение RangeError.
JavaScript-объекты TypedArray описаны в разделе 22.2 спецификации языка ECMAScript.
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) - Окружение, в котором вызывается API.
- Количество элементов в
DataView. - Базовый буфер
ArrayBufferдляDataView. - Смещение в байтах в
ArrayBufferот которого следует начать проектированиеDataView. - Объект
napi_value, представляющий JavaScript-объектDataView.
Возвращает napi_ok, если API успешно выполнено.
Этот API создает JavaScript-объект DataView над существующим ArrayBuffer. Объекты DataView предоставляют представление типа массив над базовым буфером данных, но допускают элементы разного размера и типа в ArrayBuffer.
Требуется, чтобы byte_length + byte_offset было меньше или равно размеру в байтах переданного массива. В противном случае возникает исключение RangeError.
JavaScript-объекты DataView описаны в разделе 24.3 спецификации языка ECMAScript.
Функции преобразования типов C в Node-API
napi_create_int32
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
- Окружение, в котором вызывается API.
- Целое значение для представления в JavaScript.
- Объект
napi_value, представляющий JavaScript-числоnumber.
Возвращает napi_ok, если API успешно выполнено.
Этот API используется для преобразования типа C int32_t в тип JavaScript number.
Тип JavaScript number описан в разделе 6.1.6 спецификации языка ECMAScript.
napi_create_uint32
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result)
- Окружение, в котором вызывается API.
- Беззнаковое целое значение для представления в JavaScript.
- Объект
napi_value, представляющий JavaScript-числоnumber.
Возвращает napi_ok, если API успешно выполнено.
Этот API используется для преобразования типа C uint32_t в тип JavaScript number.
Тип JavaScript number описан в разделе 6.1.6 спецификации языка ECMAScript.
napi_create_int64
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result)
- Окружение, в котором вызывается API.
- Целое значение для представления в JavaScript.
- Объект
napi_value, представляющий JavaScript-числоnumber.
Возвращает napi_ok, если API успешно выполнено.
Этот API используется для преобразования типа C int64_t в тип JavaScript number.
Тип JavaScript number описан в разделе 6.1.6 спецификации языка ECMAScript. Обратите внимание, что весь диапазон int64_t не может быть представлен с полной точностью в JavaScript. Целые значения вне диапазона Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) потеряют точность.
napi_create_double
napi_status napi_create_double(napi_env env, double value, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение двойной точности, подлежащее представлению в JavaScript. -
[out] result:napi_value, представляющий JavaScriptnumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для преобразования типа C double в тип JavaScript number.
Тип JavaScript number описан в разделе 6.1.6 спецификации языка ECMAScript.
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:napi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok в случае успешного выполнения API.
Этот API преобразует тип C int64_t в тип JavaScript BigInt.
napi_create_bigint_uint64
napi_status napi_create_bigint_uint64(napi_env env,
uint64_t value,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] value: Беззнаковое целочисленное значение, подлежащее представлению в JavaScript. -
[out] result:napi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok в случае успешного выполнения API.
Этот API преобразует тип C uint64_t в тип JavaScript BigInt.
napi_create_bigint_words
napi_status napi_create_bigint_words(napi_env env,
int sign_bit,
size_t word_count,
const uint64_t* words,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] sign_bit: Определяет, будет ли полученноеBigIntположительным или отрицательным. -
[in] word_count: Длина массиваwords. -
[in] words: Массивuint64_tслов длиной 64 бита в формате little-endian. -
[out] result:napi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok в случае успешного выполнения API.
Этот API преобразует массив беззнаковых 64-битных слов в одно значение BigInt.
Полученное BigInt вычисляется следующим образом: (–1)sign_bit (words[0] × (264)0 + words[1] × (264)1 + …)
napi_create_string_latin1
napi_status napi_create_string_latin1(napi_env env,
const char* str,
size_t length,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку, закодированную в формате ISO-8859-1. -
[in] length: Длина строки в байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result:napi_value, представляющий JavaScriptstring.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт значение JavaScript string из C-строки, закодированной в формате ISO-8859-1. Исходная строка копируется.
Тип JavaScript string описан в разделе 6.1.4 спецификации языка ECMAScript.
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: Длина строки в двухбайтных кодовых единицах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result:napi_valueпредставляющий JavaScriptstring.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт значение JavaScript string из C-строки, закодированной в формате UTF16-LE. Исходная строка копируется.
Тип JavaScript string описан в разделе 6.1.4 спецификации языка ECMAScript.
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:napi_valueпредставляющий JavaScriptstring.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт значение JavaScript string из C-строки, закодированной в формате UTF8. Исходная строка копируется.
Тип JavaScript string описан в разделе 6.1.4 спецификации языка ECMAScript.
Функции для преобразования из Node-API в типы C
napi_get_array_length
napi_status napi_get_array_length(napi_env env,
napi_value value,
uint32_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptArrayдлину которого требуется запросить. -
[out] result:uint32представляющий длину массива.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает длину массива.
Длина Array описана в разделе 22.1.4.1 спецификации языка ECMAScript.
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:napi_valueпредставляющий запрашиваемыйArrayBuffer. -
[out] data: Базовый буфер данныхArrayBuffer. Если byte_length равен0, это может бытьNULLили любое другое значение указателя. -
[out] byte_length: Длина базового буфера данных в байтах.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для получения базового буфера данных ArrayBuffer и его длины.
ПРЕДУПРЕЖДЕНИЕ: Используйте с осторожностью. Жизненный цикл базового буфера данных управляется ArrayBuffer даже после его возврата. Возможный безопасный способ использования этого API — в сочетании с napi_create_reference, что позволяет гарантировать контроль над жизненным циклом ArrayBuffer . Также безопасно использовать возвращённый буфер данных в рамках одного и того же обработчика событий, пока не будут вызваны другие API, которые могут вызвать сборку мусора.
napi_get_buffer_info
napi_status napi_get_buffer_info(napi_env env,
napi_value value,
void** data,
size_t* length) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий запрашиваемыйnode::Buffer. -
[out] data: Базовый буфер данныхnode::Buffer. Если длина равна0, это может бытьNULLили любое другое значение указателя. -
[out] length: Длина базового буфера данных в байтах.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для получения базового буфера данных node::Buffer и его длины.
Предупреждение: Используйте с осторожностью, так как жизненный цикл базового буфера данных не гарантируется, если он управляется виртуальной машиной.
napi_get_prototype
napi_status napi_get_prototype(napi_env env,
napi_value object,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] object:napi_valueпредставляющий JavaScriptObject, прототип которого нужно вернуть. Это возвращает эквивалентObject.getPrototypeOf(что не то же самое, что свойствоprototypeфункции). -
[out] result:napi_valueпредставляющий прототип данного объекта.
Возвращает napi_ok в случае успешного выполнения API.
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:napi_valueпредставляющийTypedArrayсвойства которого необходимо запросить. -
[out] type: Тип данных элементов вTypedArray. -
[out] length: Количество элементов вTypedArray. -
[out] data: Буфер данных, лежащий в основеTypedArray, скорректированный значениемbyte_offset, чтобы указывать на первый элемент вTypedArray. Если длина массива равна0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer:ArrayBufferлежащий в основеTypedArray. -
[out] byte_offset: Смещение в байтах в базовом массиве, в котором находится первый элемент массивов. Значение для параметра data уже скорректировано таким образом, что data указывает на первый элемент в массиве. Поэтому первый байт базового массива будет вdata - byte_offset.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает различные свойства типизированного массива.
Любой из выходных параметров может быть NULL если это свойство не нужно.
Предупреждение: Будьте осторожны при использовании этого API, так как базовый буфер данных управляется виртуальной машиной.
napi_get_dataview_info
napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* byte_length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset) -
[in] env: Среда, в которой вызывается API. -
[in] dataview:napi_valueпредставляющийDataView, свойства которого нужно запросить. -
[out] byte_length: Количество байтов вDataView. -
[out] data: Буфер данных, лежащий в основеDataView. Если byte_length равен0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer:ArrayBufferлежащий в основеDataView. -
[out] byte_offset: Смещение в байтах внутри буфера данных, с которого следует начать проецированиеDataView.
Возвращает napi_ok если API выполнилось успешно.
Любой из выходных параметров может быть NULL если это свойство не нужно.
Этот API возвращает различные свойства DataView.
napi_get_date_value
napi_status napi_get_date_value(napi_env env,
napi_value value,
double* result) -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий объект JavaScriptDate. -
[out] result: Значение времени какdoubleпредставленное в миллисекундах с полуночи начала 01 января 1970 года UTC.
Этот API не учитывает високосные секунды; они игнорируются, поскольку ECMAScript соответствует спецификации времени POSIX.
Возвращает napi_ok если API выполнилось успешно. Если передан не объект даты napi_value, он возвращает napi_date_expected.
Этот API возвращает примитивный тип C double значения времени для данного объекта 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представляющий объект JavaScriptBoolean. -
[out] result: Примитивный тип C boolean, эквивалентный данному объекту JavaScriptBoolean.
Возвращает napi_ok если API выполнилось успешно. Если передан не булевый объект napi_value, он возвращает napi_boolean_expected.
Этот API возвращает примитивный тип C boolean, эквивалентный данному объекту 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представляющий объект JavaScriptnumber. -
[out] result: Примитивный тип C double, эквивалентный данному объекту JavaScriptnumber.
Возвращает napi_ok если API выполнилось успешно. Если передан не числовой объект napi_value, он возвращает napi_number_expected.
Этот API возвращает примитивный тип C double, эквивалентный данному объекту 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:napi_valueпредставляющий объект JavaScriptBigInt. -
[out] result: Примитивный тип Cint64_t, эквивалентный данному объекту JavaScriptBigInt. -
[out] lossless: Указывает, было ли значениеBigIntпреобразовано без потерь.
Возвращает napi_ok если API выполнилось успешно. Если передан не BigInt, он возвращает napi_bigint_expected.
Этот API возвращает примитивный тип C int64_t, эквивалентный данному объекту JavaScript BigInt. При необходимости он усечет значение, установив lossless в false.
napi_get_value_bigint_uint64
napi_status napi_get_value_bigint_uint64(napi_env env,
napi_value value,
uint64_t* result,
bool* lossless); -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий объект JavaScriptBigInt. -
[out] result: Примитивный тип Cuint64_t, эквивалентный данному объекту JavaScriptBigInt. -
[out] lossless: Указывает, было ли значениеBigIntпреобразовано без потерь.
Возвращает napi_ok если API выполнилось успешно. Если передан не BigInt, он возвращает napi_bigint_expected.
Этот API возвращает примитивный тип C uint64_t, эквивалентный данному объекту JavaScript BigInt. При необходимости он усечет значение, установив lossless в false.
napi_get_value_bigint_words
napi_status napi_get_value_bigint_words(napi_env env,
napi_value value,
int* sign_bit,
size_t* word_count,
uint64_t* words); -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий объект JavaScriptBigInt. -
[out] sign_bit: Целое число, указывающее, является ли объект JavaScriptBigIntположительным или отрицательным. -
[in/out] word_count: Должен быть инициализирован до длины массиваwords. После возврата он будет установлен в фактическое количество слов, необходимых для хранения этогоBigInt. -
[out] words: Указатель на предварительно выделенный 64-битный массив слов.
Возвращает napi_ok если API выполнилось успешно.
Этот API преобразует одно значение BigInt в бит знака, 64-битный массив с порядком байтов little-endian и количество элементов в массиве. sign_bit и words могут быть установлены в NULL, чтобы получить только word_count.
napi_get_value_external
napi_status napi_get_value_external(napi_env env,
napi_value value,
void** result) -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий внешнее значение JavaScript. -
[out] result: Указатель на данные, инкапсулированные во внешнем значении JavaScript.
Возвращает napi_ok если API выполнилось успешно. Если передан не внешний объект napi_value, он возвращает napi_invalid_arg.
Этот API извлекает указатель на внешние данные, который был ранее передан в napi_create_external().
napi_get_value_int32
napi_status napi_get_value_int32(napi_env env,
napi_value value,
int32_t* result) -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий объект JavaScriptnumber. -
[out] result: Примитивный тип Cint32, эквивалентный данному объекту JavaScriptnumber.
Возвращает napi_ok если API выполнилось успешно. Если передан не числовой объект napi_value napi_number_expected.
Этот API возвращает примитивный тип C int32, эквивалентный данному объекту JavaScript number.
Если число выходит за пределы диапазона 32-битного целого числа, то результат усекается до эквивалента младших 32 битов. Это может привести к тому, что большое положительное число станет отрицательным, если значение > 231 - 1.
Неконечные числовые значения (NaN, +Infinity, или -Infinity) устанавливают результат в ноль.
napi_get_value_int64
napi_status napi_get_value_int64(napi_env env,
napi_value value,
int64_t* result) -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий объект JavaScriptnumber. -
[out] result: Примитивный тип Cint64, эквивалентный данному объекту JavaScriptnumber.
Возвращает napi_ok если API выполнилось успешно. Если передан не числовой объект napi_value, он возвращает napi_number_expected.
Этот API возвращает примитивный тип C int64, эквивалентный данному объекту JavaScript number.
number значения вне диапазона Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) потеряют точность.
Неконечные числовые значения (NaN, +Infinity, или -Infinity) устанавливают результат в ноль.
napi_get_value_string_latin1
napi_status napi_get_value_string_latin1(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result) -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющий строку JavaScript. -
[in] buf: Буфер для записи строки, закодированной в ISO-8859-1. Если переданNULL, длина строки в байтах без учета завершающего нуля возвращается вresult. -
[in] bufsize: Размер целевого буфера. Когда этого значения недостаточно, возвращаемая строка усекается и завершается нулем. -
[out] result: Количество скопированных в буфер байтов, без учета завершающего нуля.
Возвращает napi_ok если API выполнилось успешно. Если передан не string napi_value, он возвращает napi_string_expected.
Этот API возвращает строку, закодированную в ISO-8859-1, соответствующую переданному значению.
napi_get_value_string_utf8
napi_status napi_get_value_string_utf8(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий строку JavaScript. -
[in] buf: Буфер для записи UTF8-строки. ЕслиNULLпередано, длина строки в байтах без учета нулевого терминатора возвращается вresult. -
[in] bufsize: Размер целевого буфера. Если этого значения недостаточно, возвращаемая строка усекается и завершается нулевым терминатором. -
[out] result: Количество байтов, скопированных в буфер, без учета нулевого терминатора.
Возвращает napi_ok при успешном выполнении API. Если передано не-string napi_value, возвращает napi_string_expected.
Этот API возвращает UTF8-кодированную строку, соответствующую переданному значению.
napi_get_value_string_utf16
napi_status napi_get_value_string_utf16(napi_env env,
napi_value value,
char16_t* buf,
size_t bufsize,
size_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий строку JavaScript. -
[in] buf: Буфер для записи UTF16-LE-кодированной строки. ЕслиNULLпередано, длина строки в 2-байтовых кодовых единицах без учета нулевого терминатора возвращается в данном параметре. -
[in] bufsize: Размер целевого буфера. Если этого значения недостаточно, возвращаемая строка усекается и завершается нулевым терминатором. -
[out] result: Количество 2-байтовых кодовых единиц, скопированных в буфер, без учета нулевого терминатора.
Возвращает napi_ok при успешном выполнении API. Если передано не-string napi_value, возвращает napi_string_expected.
Этот API возвращает UTF16-кодированную строку, соответствующую переданному значению.
napi_get_value_uint32
napi_status napi_get_value_uint32(napi_env env,
napi_value value,
uint32_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptnumber. -
[out] result: C-эквивалент данногоnapi_valueкакuint32_t.
Возвращает napi_ok при успешном выполнении API. Если передано не числовое napi_value значение, возвращает napi_number_expected.
Этот API возвращает C-эквивалент данного napi_value значения как uint32_t.
Функции получения глобальных экземпляров
napi_get_boolean
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение булевого значения для извлечения. -
[out] result:napi_valueпредставляющий JavaScriptBooleanсинглтон для извлечения.
Возвращает napi_ok при успешном выполнении API.
Этот API используется для возврата объекта JavaScript синглтона, используемого для представления данного булевого значения.
napi_get_global
napi_status napi_get_global(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_valueпредставляющий объект JavaScriptglobal.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает объект global.
napi_get_null
napi_status napi_get_null(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_valueпредставляющий объект JavaScriptnull.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает объект null.
napi_get_undefined
napi_status napi_get_undefined(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_valueпредставляющий значение JavaScript Undefined.
Возвращает napi_ok при успешном выполнении API.
Этот API возвращает объект Undefined.
Работа с JavaScript-значениями и абстрактными операциями
Node-API предоставляет набор API для выполнения некоторых абстрактных операций над JavaScript-значениями. Некоторые из этих операций описаны в разделе 7 спецификации языка ECMAScript.
Эти API поддерживают выполнение следующих действий:
- Преобразование JavaScript-значений к определённым типам JavaScript (таким как
numberилиstring). - Определение типа JavaScript-значения.
- Проверка равенства двух JavaScript-значений.
napi_coerce_to_bool
napi_status napi_coerce_to_bool(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_valueпредставляющий преобразованное JavaScript-значениеBoolean.
Возвращает napi_ok, если API успешно выполнено.
Этот API реализует абстрактную операцию ToBoolean(), как определено в разделе 7.1.2 спецификации языка ECMAScript.
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:napi_valueпредставляющий преобразованное JavaScript-значениеnumber.
Возвращает napi_ok, если API успешно выполнено.
Этот API реализует абстрактную операцию ToNumber(), как определено в разделе 7.1.3 спецификации языка ECMAScript. Эта функция потенциально выполняет JS-код, если переданное значение является объектом.
napi_coerce_to_object
napi_status napi_coerce_to_object(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_valueпредставляющий преобразованное JavaScript-значениеObject.
Возвращает napi_ok, если API успешно выполнено.
Этот API реализует абстрактную операцию ToObject(), как определено в разделе 7.1.13 спецификации языка ECMAScript.
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:napi_valueпредставляющий преобразованное JavaScript-значениеstring.
Возвращает napi_ok, если API успешно выполнено.
Этот API реализует абстрактную операцию ToString(), как определено в разделе 7.1.13 спецификации языка ECMAScript. Эта функция потенциально выполняет JS-код, если переданное значение является объектом.
napi_typeof
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение, тип которого нужно определить. -
[out] result: Тип JavaScript-значения.
Возвращает napi_ok, если API успешно выполнено.
-
napi_invalid_argесли типvalueне является известным типом ECMAScript иvalueне является значением External.
Этот API имитирует поведение оператора typeof, применяемого к объекту, как определено в разделе 12.5.5 спецификации языка ECMAScript. Однако существуют некоторые отличия:
- Поддержка обнаружения значения External.
- Обнаружение
nullкак отдельного типа, в то время как ECMAScripttypeofопределил быobject.
Если у value неверный тип, возвращается ошибка.
napi_instanceof
napi_status napi_instanceof(napi_env env,
napi_value object,
napi_value constructor,
bool* result) -
[in] env: Среда, в которой вызывается API. -
[in] object: JavaScript-значение для проверки. -
[in] constructor: JavaScript-объект функции конструктора для проверки. -
[out] result: Булево значение, установленное в true, еслиobject instanceof constructorравно true.
Возвращает napi_ok, если API успешно выполнено.
Этот API представляет вызов оператора instanceof для объекта, как определено в разделе 12.10.4 спецификации языка ECMAScript.
napi_is_array
napi_status napi_is_array(napi_env env, napi_value value, bool* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Является ли данный объект массивом.
Возвращает napi_ok, если API успешно выполнено.
Этот API представляет вызов операции IsArray для объекта, как определено в разделе 7.2.2 спецификации языка ECMAScript.
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.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданный Object буфером массива.
napi_is_buffer
napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли данноеnapi_valueобъект буфераnode::Buffer.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданное Object буфером.
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.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданное Object датой.
napi_is_error
napi_status napi_is_error(napi_env env, napi_value value, bool* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли переданноеnapi_valueобъектError.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданное Object ошибкой Error.
napi_is_typedarray
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли переданноеnapi_valueтипизированный массивTypedArray.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданное Object типизированным массивом.
napi_is_dataview
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли переданноеnapi_valueобъектDataView.
Возвращает napi_ok, если API успешно выполнено.
Этот API проверяет, является ли переданное Object объектом DataView.
napi_strict_equals
napi_status napi_strict_equals(napi_env env,
napi_value lhs,
napi_value rhs,
bool* result) -
[in] env: Среда, в которой вызывается API. -
[in] lhs: JavaScript-значение для проверки. -
[in] rhs: JavaScript-значение для сравнения. -
[out] result: Являются ли два объектаnapi_valueравными.
Возвращает napi_ok, если API успешно выполнено.
Этот API представляет вызов алгоритма строгого равенства, как определено в разделе 7.2.14 спецификации языка ECMAScript.
napi_detach_arraybuffer
napi_status napi_detach_arraybuffer(napi_env env,
napi_value arraybuffer) -
[in] env: Среда, в которой вызывается API. -
[in] arraybuffer: JavaScript-значениеArrayBufferдля открепления.
Возвращает napi_ok, если API успешно выполнено. Если передан ArrayBuffer , который нельзя открепить, возвращает napi_detachable_arraybuffer_expected.
В целом, ArrayBuffer неотсоединяемый, если он был отсоединен ранее. Движок может наложить дополнительные условия на то, является ли ArrayBuffer отсоединяемым. Например, V8 требует, чтобы ArrayBuffer был внешним, то есть созданным с помощью napi_create_external_arraybuffer.
Этот API представляет вызов операции отсоединения ArrayBuffer как определено в Разделе 24.1.1.3 спецификации языка ECMAScript.
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отсоединённым.
Возвращает napi_ok в случае успешного выполнения API.
ArrayBuffer считается отсоединённым, если его внутренние данные null.
Этот API представляет вызов операции ArrayBuffer IsDetachedBuffer как определено в Разделе 24.1.1.2 спецификации языка ECMAScript.
Работа с свойствами JavaScript
Node-API предоставляет набор API для получения и установки свойств объектов JavaScript. Некоторые из этих типов документированы в разделе 7 Спецификации языка ECMAScript.
Свойства в JavaScript представлены в виде кортежа из ключа и значения. В Node-API все ключи свойств в принципе могут быть представлены в одном из следующих форматов:
- Именованные: простая строка UTF8
- Индексированные по целочисленному значению: значение индекса, представленное как
uint32_t - Значение JavaScript: в Node-API они представлены как
napi_value. Это может бытьnapi_value, представляющаяstring,number, илиsymbol.
Значения Node-API представлены типом napi_value. Любой вызов Node-API, требующий значения JavaScript, принимает napi_value. Однако, ответственность за проверку того, что napi_value принадлежит ожидаемому типу JavaScript API, лежит на вызывающей стороне.
API, документированные в этом разделе, предоставляют простой интерфейс для получения и установки свойств произвольных объектов JavaScript, представленных как napi_value.
Например, рассмотрим следующий фрагмент кода JavaScript:
const obj = {};
obj.myProp = 123; Эквивалент можно выполнить с использованием значений Node-API следующим фрагментом:
napi_status status = napi_generic_failure;
// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create a napi_value for 123
status = napi_create_int32(env, 123, &value);
if (status != napi_ok) return status;
// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status; Индексированные свойства могут быть установлены аналогичным образом. Рассмотрим следующий фрагмент JavaScript:
const arr = []; arr[123] = 'hello';
Эквивалент можно выполнить с использованием значений Node-API следующим фрагментом:
napi_status status = napi_generic_failure; // const arr = []; napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // Create a napi_value for 'hello' status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &value); if (status != napi_ok) return status; // arr[123] = 'hello'; status = napi_set_element(env, arr, 123, value); if (status != napi_ok) return status;
Свойства можно получить, используя API, описанные в этом разделе. Рассмотрим следующий фрагмент кода JavaScript:
const arr = []; const value = arr[123];
Следующее приблизительно соответствует Node-API аналогу:
napi_status status = napi_generic_failure; // const arr = [] napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // const value = arr[123] status = napi_get_element(env, arr, 123, &value); if (status != napi_ok) return status;
Наконец, для повышения производительности на объекте можно определить несколько свойств. Рассмотрим следующий JavaScript-код:
const obj = {};
Object.defineProperties(obj, {
'foo': { value: 123, writable: true, configurable: true, enumerable: true },
'bar': { value: 456, writable: true, configurable: true, enumerable: true }
}); Следующее приблизительно соответствует Node-API аналогу:
napi_status status = napi_status_generic_failure;
// const obj = {};
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_int32(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_int32(env, 456, &barValue);
if (status != napi_ok) return status;
// Set the properties
napi_property_descriptor descriptors[] = {
{ "foo", NULL, NULL, NULL, NULL, fooValue, napi_writable | napi_configurable, NULL },
{ "bar", NULL, NULL, NULL, NULL, barValue, napi_writable | napi_configurable, NULL }
}
status = napi_define_properties(env,
obj,
sizeof(descriptors) / sizeof(descriptors[0]),
descriptors);
if (status != napi_ok) return status; Структуры
napi_property_attributes
typedef enum {
napi_default = 0,
napi_writable = 1 << 0,
napi_enumerable = 1 << 1,
napi_configurable = 1 << 2,
// Used with napi_define_class to distinguish static properties
// from instance properties. Ignored by napi_define_properties.
napi_static = 1 << 10,
// Default for class methods.
napi_default_method = napi_writable | napi_configurable,
// Default for object properties, like in JS obj[prop].
napi_default_jsproperty = napi_writable |
napi_enumerable |
napi_configurable,
} napi_property_attributes; napi_property_attributes являются флагами, используемыми для управления поведением свойств, устанавливаемых на объект JavaScript. Помимо napi_static, они соответствуют атрибутам, перечисленным в разделе 6.1.7.1 Спецификации языка ECMAScript. Они могут быть одним или несколькими из следующих битовых флагов:
-
napi_default: Явно не установлены атрибуты свойства. По умолчанию свойство является только для чтения, не перечисляемым и не настраиваемым. -
napi_writable: Свойство изменяемо. -
napi_enumerable: Свойство перечисляется. -
napi_configurable: Свойство настраиваемо, как определено в разделе 6.1.7.1 Спецификации языка ECMAScript. -
napi_static: Свойство будет определено как статическое свойство класса, а не как свойство экземпляра (по умолчанию). Используется только функциейnapi_define_class. Игнорируется функциейnapi_define_properties. -
napi_default_method: Как метод в JS-классе, свойство настраиваемое и изменяемое, но не перечисляемое. -
napi_default_jsproperty: Как свойство, установленное присваиванием в JavaScript, свойство изменяемо, перечисляемо и настраиваемо.
napi_property_descriptor
typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;
napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;
napi_property_attributes attributes;
void* data;
} napi_property_descriptor; -
utf8name: Необязательная строка, описывающая ключ свойства, закодированная в UTF8. Для свойства должен быть предоставлен один изutf8nameилиname. -
name: Необязательныйnapi_value, указывающий на строку JavaScript или символ, который будет использоваться в качестве ключа свойства. Для свойства должен быть предоставлен один изutf8nameилиname. -
value: Значение, получаемое при доступе к свойству по методу «get», если свойство является свойством данных. Если это значение передаётся, установитеgetter,setter,methodиdataвNULL(поскольку эти члены не будут использоваться). -
getter: Функция, вызываемая при выполнении доступа по методу «get» к свойству. Если это значение передаётся, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Функция неявно вызывается во время выполнения при обращении к свойству из JavaScript-кода (или если доступ «get» к свойству выполняется с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
setter: Функция, вызываемая при выполнении доступа по методу «set» к свойству. Если это значение передаётся, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Функция неявно вызывается во время выполнения при изменении свойства из JavaScript-кода (или если доступ «set» к свойству выполняется с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
method: Установите это значение, чтобы сделать свойствоvalueобъекта-дескриптора свойства функцией JavaScript, представленнойmethod. Если это значение передаётся, установитеvalue,getterиsetterвNULL(поскольку эти члены не будут использоваться).napi_callbackсодержит дополнительные сведения. -
attributes: Атрибуты, связанные с конкретным свойством. См.napi_property_attributes. -
data: Данные обратного вызова, переданные вmethod,getterиsetterпри вызове этой функции.
Функции
napi_get_property_names
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойства. -
[out] result:napi_value, представляющий массив значений JavaScript, которые представляют имена свойств объекта. Для перебораresultможно использоватьnapi_get_array_lengthиnapi_get_element.
Возвращает napi_ok в случае успеха API.
Это API возвращает имена перечисляемых свойств объекта object в виде массива строк. Свойства объекта object, ключи которых являются символами, не будут включены.
napi_get_all_property_names
napi_get_all_property_names(napi_env env,
napi_value object,
napi_key_collection_mode key_mode,
napi_key_filter key_filter,
napi_key_conversion key_conversion,
napi_value* result); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойства. -
[in] key_mode: Нужно ли получать свойства прототипа также. -
[in] key_filter: Какие свойства нужно получить (перечисляемые/доступные для чтения/изменения). -
[in] key_conversion: Нужно ли преобразовывать числовые ключи свойств в строки. -
[out] result:napi_value, представляющий массив значений JavaScript, которые представляют имена свойств объекта. Для перебораresultможно использоватьnapi_get_array_lengthиnapi_get_element.
Возвращает napi_ok в случае успеха API.
Это API возвращает массив, содержащий имена доступных свойств этого объекта.
napi_set_property
napi_status napi_set_property(napi_env env,
napi_value object,
napi_value key,
napi_value value); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, на котором нужно установить свойство. -
[in] key: Имя свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok в случае успеха API.
Это API устанавливает свойство на переданный Object.
napi_get_property
napi_status napi_get_property(napi_env env,
napi_value object,
napi_value key,
napi_value* result); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойство. -
[in] key: Имя свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok в случае успеха API.
Это API получает запрашиваемое свойство из переданного Object.
napi_has_property
napi_status napi_has_property(napi_env env,
napi_value object,
napi_value key,
bool* result); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] key: Имя свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok в случае успеха API.
Это API проверяет, есть ли у переданного Object свойство с заданным именем.
napi_delete_property
napi_status napi_delete_property(napi_env env,
napi_value object,
napi_value key,
bool* result); -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] key: Имя свойства, которое нужно удалить. -
[out] result: Удалось ли удалить свойство.resultможно необязательно проигнорировать, передавNULL.
Возвращает napi_ok в случае успешного выполнения API.
Этот API пытается удалить собственную (own) собственность key от 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: Название собственной (own) свойства, существование которого нужно проверить. -
[out] result: Существует ли собственное (own) свойство в объекте или нет.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, обладает ли переданный Object указанным собственным (own) свойством. key должен быть string или symbol, в противном случае будет выброшено исключение. Node-API не будет выполнять никаких преобразований между типами данных.
napi_set_named_property
napi_status napi_set_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value value); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, для которого нужно установить свойство. -
[in] utf8Name: Название свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_set_property со строкой, преобразованной в napi_value в качестве 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] object: Объект, из которого нужно извлечь свойство. -
[in] utf8Name: Название свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_get_property со строкой, преобразованной в napi_value в качестве 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: Существует ли свойство в объекте или нет.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_has_property со строкой, преобразованной в napi_value в качестве 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] object: Объект, для которого нужно установить свойства. -
[in] index: Индекс свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот API устанавливает элемент в переданном Object.
napi_get_element
napi_status napi_get_element(napi_env env,
napi_value object,
uint32_t index,
napi_value* result); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого нужно извлечь свойство. -
[in] index: Индекс свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот API получает элемент по указанному индексу.
napi_has_element
napi_status napi_has_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] index: Индекс свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает, содержит ли переданный Object элемент по указанному индексу.
napi_delete_element
napi_status napi_delete_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для удаления элемента. -
[in] index: Индекс свойства, которое нужно удалить. -
[out] result: Удаление элемента успешно или нет.resultможно необязательно игнорировать, передавNULL.
Возвращает napi_ok в случае успешного выполнения API.
Этот API пытается удалить указанный index из 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] object: Объект, для которого нужно получить свойства. -
[in] property_count: Количество элементов в массивеproperties. -
[in] properties: Массив описателей свойств.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет эффективно определять несколько свойств для данного объекта. Свойства определяются с помощью описателей свойств (см. napi_property_descriptor). Используя массив таких описателей свойств, этот API будет устанавливать свойства в объекте по одному за раз, как определено DefineOwnProperty() (описано в Разделе 9.1.6 спецификации ECMA-262).
napi_object_freeze
napi_status napi_object_freeze(napi_env env,
napi_value object); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, который нужно заморозить.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод замораживает данный объект. Это предотвращает добавление новых свойств, удаление существующих свойств, изменение перечислимости, конфигурируемости или изменяемости существующих свойств, а также изменение значений существующих свойств. Также предотвращает изменение прототипа объекта. Описано в Разделе 19.1.2.6 спецификации ECMA-262.
napi_object_seal
napi_status napi_object_seal(napi_env env,
napi_value object); -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, который нужно запечатать.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод запечатывает данный объект. Это предотвращает добавление новых свойств, а также помечает все существующие свойства как неконфигурируемые. Описано в Разделе 19.1.2.20 спецификации ECMA-262.
Работа с функциями JavaScript
Node-API предоставляет набор API, которые позволяют коду JavaScript вызывать функции нативного кода. Node-API, поддерживающие обращение к нативному коду, принимают функции обратного вызова, представленные типом napi_callback. Когда JavaScript VM вызывает нативный код, вызывается функция napi_callback . API, описанные в этом разделе, позволяют функции обратного вызова выполнять следующие действия:
- Получить информацию о контексте, в котором был вызван обратный вызов.
- Получить аргументы, переданные в обратный вызов.
- Возвратить значение
napi_valueиз обратного вызова.
Кроме того, Node-API предоставляет набор функций, позволяющих вызывать функции JavaScript из нативного кода. Можно вызвать функцию как обычный вызов JavaScript-функции или как функцию-конструктор.
Любые данные, не являющиеся NULL, которые передаются в этот API через поле data элементов napi_property_descriptor, могут быть связаны с object и освобождаться всякий раз, когда object собирается сборщиком мусора, передав как object, так и данные в napi_add_finalizer.
Вызов функции
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:napi_value, представляющая вызываемую функцию JavaScript. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массивnapi_values, представляющих значения JavaScript, переданные в функцию в качестве аргументов. -
[out] result:napi_value, представляющее возвращаемый объект JavaScript.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать объект функции JavaScript из нативного плагина. Это основной механизм вызова из нативного кода плагина в JavaScript. Для специального случая вызова JavaScript после асинхронной операции см. napi_make_callback.
Пример использования может выглядеть следующим образом. Рассмотрим следующий фрагмент JavaScript:
function AddTwo(num) {
return num + 2;
} Затем, вышеуказанную функцию можно вызвать из нативного плагина с помощью следующего кода:
// 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_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в байтах илиNAPI_AUTO_LENGTH, если она имеет нулевую завершающую последовательность. -
[in] cb: Нативная функция, которая должна вызываться при вызове этого объекта функции.napi_callbackпредоставляет более подробную информацию. -
[in] data: Контекст данных, предоставленный пользователем. Он будет передан обратно в функцию при ее последующем вызове. -
[out] result:napi_value, представляющий объект JavaScript-функции для только что созданной функции.
Возвращает napi_ok в случае успешного выполнения API.
Этот API позволяет автору плагина создать объект функции в нативном коде. Это основной механизм для вызова в нативный код плагина из JavaScript.
Только что созданная функция не отображается автоматически в скрипте после этого вызова. Вместо этого свойство должно быть явно установлено на любом объекте, видимом для JavaScript, чтобы функция была доступна из скрипта.
Чтобы экспортировать функцию как часть экспорта модуля плагина, установите только что созданную функцию на объект экспорта. Пример модуля может выглядеть следующим образом:
napi_value SayHello(napi_env env, napi_callback_info info) {
printf("Hello\n");
return NULL;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return NULL;
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) Учитывая приведенный выше код, плагин можно использовать из JavaScript следующим образом:
const myaddon = require('./addon');
myaddon.sayHello(); Строка, переданная в require(), — это имя целевого объекта в binding.gyp, ответственного за создание файла .node.
Любые данные, не являющиеся NULL, передаваемые в этот API через параметр data, могут быть связаны с полученной функцией JavaScript (которая возвращается в параметре result) и освобождаться всякий раз, когда функция собирается сборщиком мусора, передав и функцию JavaScript, и данные в napi_add_finalizer.
Функции JavaScript описаны в разделе 19.2 спецификации языка ECMAScript.
Получение информации об обратном вызове
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и получает фактическое количество аргументов. -
[out] argv: Буфер, в который копируютсяnapi_value, представляющие аргументы. Если аргументов больше, чем указано, копируются только запрошенное количество. Если предоставлено меньше аргументов, чем заявлено, оставшаяся частьargvзаполняется значениямиnapi_value, представляющимиundefined. -
[out] this: Получает аргумент JavaScriptthisдля вызова. -
[out] data: Получает указатель данных для обратного вызова.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод используется внутри функции обратного вызова для извлечения подробностей о вызове, таких как аргументы и указатель this из предоставленной информации об обратном вызове.
Получение 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вызова конструктора.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает значение new.target вызова конструктора. Если текущий обратный вызов не является вызовом конструктора, результат равен NULL.
Создание экземпляра
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:napi_value, представляющая вызываемую функцию JavaScript как конструктор. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив значений JavaScript какnapi_value, представляющих аргументы конструктора. -
[out] result:napi_value, представляющий возвращаемый объект JavaScript, который в данном случае является созданным объектом.
Этот метод используется для создания нового значения JavaScript с помощью заданного napi_value, представляющего конструктор объекта. Например, рассмотрим следующий фрагмент:
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg); Следующее можно приблизить в Node-API с помощью следующего фрагмента:
// Get the constructor function MyObject napi_value global, constructor, arg, value; napi_status status = napi_get_global(env, &global); if (status != napi_ok) return; status = napi_get_named_property(env, global, "MyObject", &constructor); if (status != napi_ok) return; // const arg = "hello" status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &arg); if (status != napi_ok) return; napi_value* argv = &arg; size_t argc = 1; // const value = new MyObject(arg) status = napi_new_instance(env, constructor, argc, argv, &value);
Возвращает napi_ok в случае успешного выполнения API.
Обёртка объекта
Node-API предлагает способ "обёртки" классов и экземпляров C++ таким образом, чтобы конструктор класса и методы могли вызываться из JavaScript.
- API
napi_define_classопределяет класс JavaScript с конструктором, статическими свойствами и методами, а также свойствами и методами экземпляров, соответствующими классу C++. - Когда JavaScript-код вызывает конструктор, обратный вызов конструктора использует
napi_wrapдля обёртки нового экземпляра C++ в JavaScript-объект, а затем возвращает обёрнутый объект. - Когда JavaScript-код вызывает метод или обработчик доступа к свойству класса, вызывается соответствующая
napi_callbackфункция C++. Для обратного вызова экземпляраnapi_unwrapполучает экземпляр C++, который является целью вызова.
Для обёрнутых объектов может быть сложно отличить функцию, вызываемую на прототипе класса, от функции, вызываемой на экземпляре класса. Общим шаблоном для решения этой проблемы является сохранение постоянной ссылки на конструктор класса для последующих instanceof проверок.
napi_value MyClass_constructor = NULL;
status = napi_get_reference_value(env, MyClass::es_constructor, &MyClass_constructor);
assert(napi_ok == status);
bool is_instance = false;
status = napi_instanceof(env, es_this, MyClass_constructor, &is_instance);
assert(napi_ok == status);
if (is_instance) {
// napi_unwrap() ...
} else {
// otherwise...
} Ссылка должна быть освобождена, когда она больше не нужна.
Бывают случаи, когда napi_instanceof() недостаточно для обеспечения того, что JavaScript-объект является обёрткой для определённого нативного типа. Это особенно актуально, когда обёрнутые JavaScript-объекты передаются обратно в плагин через статические методы, а не как this значение методов прототипа. В таких случаях существует вероятность неправильного разворачивания.
const myAddon = require('./build/Release/my_addon.node');
// `openDatabase()` returns a JavaScript object that wraps a native database
// handle.
const dbHandle = myAddon.openDatabase();
// `query()` returns a JavaScript object that wraps a native query handle.
const queryHandle = myAddon.query(dbHandle, 'Gimme ALL the things!');
// There is an accidental error in the line below. The first parameter to
// `myAddon.queryHasRecords()` should be the database handle (`dbHandle`), not
// the query handle (`query`), so the correct condition for the while-loop
// should be
//
// myAddon.queryHasRecords(dbHandle, queryHandle)
//
while (myAddon.queryHasRecords(queryHandle, dbHandle)) {
// retrieve records
} В приведённом выше примере myAddon.queryHasRecords() — это метод, принимающий два аргумента. Первый — это дескриптор базы данных, второй — дескриптор запроса. Внутренне он разворачивает первый аргумент и преобразует полученный указатель в нативный дескриптор базы данных. Затем он разворачивает второй аргумент и преобразует полученный указатель в дескриптор запроса. Если аргументы переданы в неправильном порядке, преобразования будут работать, однако существует высокая вероятность того, что базовая операция базы данных завершится неудачей или даже приведёт к недопустимому доступу к памяти.
Для того чтобы убедиться, что указатель, полученный из первого аргумента, действительно является указателем на дескриптор базы данных, и аналогично, что указатель, полученный из второго аргумента, действительно является указателем на дескриптор запроса, реализация queryHasRecords() должна выполнить проверку типа. Сохранение конструктора JavaScript-класса, из которого был создан дескриптор базы данных, и конструктора, из которого был создан дескриптор запроса, в napi_ref может помочь, поскольку napi_instanceof() можно использовать для обеспечения того, что экземпляры, переданные в queryHashRecords() , действительно имеют правильный тип.
К сожалению, napi_instanceof() не защищает от манипуляций с прототипом. Например, прототип экземпляра дескриптора базы данных может быть установлен в прототип конструктора экземпляров дескрипторов запросов. В этом случае экземпляр дескриптора базы данных может быть принят за экземпляр дескриптора запроса, и он пройдёт napi_instanceof() проверку на экземпляр дескриптора запроса, при этом всё ещё содержа в себе указатель на дескриптор базы данных.
Для этого Node-API предоставляет возможности помечания типов.
Тег типа — 128-битовое целое число, уникальное для плагина. Node-API предоставляет структуру napi_type_tag для хранения тега типа. Когда такое значение передаётся вместе с JavaScript-объектом, хранящимся в napi_value к napi_type_tag_object(), JavaScript-объект будет помечен тегом типа. Пометка невидима со стороны JavaScript. Когда JavaScript-объект поступает в нативную привязку, napi_check_object_type_tag() можно использовать вместе с исходным тегом типа, чтобы определить, был ли JavaScript-объект ранее помечен тегом типа. Это создаёт возможность проверки типов более высокой точности, чем napi_instanceof() может обеспечить, поскольку такое помечание типов сохраняется при манипуляциях с прототипом и при загрузке/перезагрузке плагина.
Продолжая вышеприведённый пример, следующий скелет реализации плагина демонстрирует использование napi_type_tag_object() и napi_check_object_type_tag().
// This value is the type tag for a database handle. The command
//
// uuidgen | sed -r -e 's/-//g' -e 's/(.{16})(.*)/0x\1, 0x\2/'
//
// can be used to obtain the two values with which to initialize the structure.
static const napi_type_tag DatabaseHandleTypeTag = {
0x1edf75a38336451d, 0xa5ed9ce2e4c00c38
};
// This value is the type tag for a query handle.
static const napi_type_tag QueryHandleTypeTag = {
0x9c73317f9fad44a3, 0x93c3920bf3b0ad6a
};
static napi_value
openDatabase(napi_env env, napi_callback_info info) {
napi_status status;
napi_value result;
// Perform the underlying action which results in a database handle.
DatabaseHandle* dbHandle = open_database();
// Create a new, empty JS object.
status = napi_create_object(env, &result);
if (status != napi_ok) return NULL;
// Tag the object to indicate that it holds a pointer to a `DatabaseHandle`.
status = napi_type_tag_object(env, result, &DatabaseHandleTypeTag);
if (status != napi_ok) return NULL;
// Store the pointer to the `DatabaseHandle` structure inside the JS object.
status = napi_wrap(env, result, dbHandle, NULL, NULL, NULL);
if (status != napi_ok) return NULL;
return result;
}
// Later when we receive a JavaScript object purporting to be a database handle
// we can use `napi_check_object_type_tag()` to ensure that it is indeed such a
// handle.
static napi_value
query(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 2;
napi_value argv[2];
bool is_db_handle;
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (status != napi_ok) return NULL;
// Check that the object passed as the first parameter has the previously
// applied tag.
status = napi_check_object_type_tag(env,
argv[0],
&DatabaseHandleTypeTag,
&is_db_handle);
if (status != napi_ok) return NULL;
// Throw a `TypeError` if it doesn't.
if (!is_db_handle) {
// Throw a TypeError.
return NULL;
}
}
napi_define_class
napi_status napi_define_class(napi_env env,
const char* utf8name,
size_t length,
napi_callback constructor,
void* data,
size_t property_count,
const napi_property_descriptor* properties,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] utf8name: Имя JavaScript-функции-конструктора; При обёртке C++-класса рекомендуется, для ясности, чтобы это имя совпадало с именем C++-класса. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTHесли она имеет нуль-терминатор. -
[in] constructor: Функция обратного вызова, обрабатывающая создание экземпляров класса. При обёртке C++-класса этот метод должен быть статическим членом с сигнатуройnapi_callback. Конструктор C++-класса использовать нельзя.napi_callbackпредоставляет более подробную информацию. -
[in] data: Дополнительные данные, передаваемые в обратный вызов конструктора как свойствоdatacallback info. -
[in] property_count: Количество элементов в массиве аргументовproperties. -
[in] properties: Массив дескрипторов свойств, описывающих статические и экземпляры данных, свойства, аксессоры и методы класса. См.napi_property_descriptor. -
[out] result:napi_valueпредставляющий конструктор функции для класса.
Возвращает napi_ok в случае успешного выполнения API.
Определяет JavaScript-класс, включая:
- Функцию конструктора JavaScript, имеющую имя класса. При обёртке соответствующего C++-класса обратный вызов, переданный через
constructor, можно использовать для создания нового экземпляра C++-класса, который затем можно разместить внутри экземпляра JavaScript-объекта, который создаётся с помощьюnapi_wrap. - Свойства в функции-конструкторе, реализация которых может вызывать соответствующие статические свойства данных, аксессоры и методы C++-класса (определённые дескрипторами свойств с атрибутом
napi_static). - Свойства в объекте
prototypeконструктора функции. При обёртке C++-класса нестатические свойства данных, аксессоры и методы C++-класса можно вызывать из статических функций, заданных в дескрипторах свойств без атрибутаnapi_staticпосле получения экземпляра C++-класса, размещённого внутри экземпляра JavaScript-объекта, используяnapi_unwrap.
При обёртке C++-класса обратный вызов конструктора C++, переданный через constructor , должен быть статическим методом класса, который вызывает фактический конструктор класса, затем обёртывает новый экземпляр C++ в JavaScript-объект и возвращает обёрнутый объект. Для получения подробностей см. napi_wrap.
Функция конструктора JavaScript, возвращённая из napi_define_class, часто сохраняется и используется позже для создания новых экземпляров класса из нативного кода и/или для проверки того, являются ли предоставленные значения экземплярами класса. В этом случае, чтобы предотвратить сборку мусора для функции, можно создать сильную постоянную ссылку на неё с помощью napi_create_reference, гарантируя, что счётчик ссылок сохраняется >= 1.
Любые не-NULL данные, которые передаются в этот API через параметр data или через поле data элементов массива napi_property_descriptor, могут быть связаны с результатом JavaScript-конструктора (который возвращается в параметре result) и освобождаться всякий раз, когда класс собирается мусором, передав и JavaScript-функцию, и данные в napi_add_finalizer.
napi_wrap
napi_status napi_wrap(napi_env env,
napi_value js_object,
void* native_object,
napi_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); -
[in] env: Среда, в которой вызывается API. -
[in] js_object: JavaScript-объект, который будет обёрткой для нативного объекта. -
[in] native_object: Нативный экземпляр, который будет обёрнут в JavaScript-объект. -
[in] finalize_cb: Необязательный нативный обратный вызов, который может быть использован для освобождения нативного экземпляра, когда JavaScript-объект готов к сбору мусора.napi_finalizeпредоставляет более подробную информацию. -
[in] finalize_hint: Необязательный контекстный признак, который передаётся в обратный вызов finalize. -
[out] result: Необязательная ссылка на обёрнутый объект.
Возвращает napi_ok в случае успешного выполнения API.
Обёртывает нативный экземпляр в JavaScript-объект. Нативный экземпляр можно получить позже, используя napi_unwrap().
Когда JavaScript-код вызывает конструктор для класса, который был определён с помощью napi_define_class(), вызывается napi_callback для конструктора. После построения экземпляра нативного класса, обратный вызов должен вызвать napi_wrap() для обёртки вновь созданного экземпляра в уже созданный JavaScript-объект, являющийся this аргументом обратного вызова конструктора. (Этот this объект был создан из prototype, конструктора функции, поэтому у него уже есть определения всех свойств и методов экземпляра.)
Как правило, при обёртке экземпляра класса следует предоставить обратный вызов finalize, который просто удаляет нативный экземпляр, получаемый как data аргумент обратного вызова finalize.
Необязательная возвращаемая ссылка первоначально является слабой ссылкой, т.е. имеет счётчик ссылок 0. Как правило, этот счётчик ссылок временно увеличивается во время асинхронных операций, требующих, чтобы экземпляр оставался валидным.
Предупреждение: необязательная возвращаемая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова finalize. Если она будет удалена до этого, то обратный вызов finalize может никогда не быть вызван. Поэтому при получении ссылки также требуется обратный вызов finalize, чтобы обеспечить правильное удаление ссылки.
Вызов napi_wrap() второй раз для объекта вернёт ошибку. Чтобы связать другой нативный экземпляр с объектом, сначала используйте napi_remove_wrap().
napi_unwrap
napi_status napi_unwrap(napi_env env,
napi_value js_object,
void** result); -
[in] env: Среда, в которой вызывается API. -
[in] js_object: Объект, связанный с нативным экземпляром. -
[out] result: Указатель на обёрнутый нативный экземпляр.
Возвращает napi_ok в случае успешного выполнения API.
Извлекает исходный экземпляр, который ранее был обернут в JavaScript-объект с помощью napi_wrap().
Когда JavaScript-код вызывает метод или свойство класса, вызывается соответствующий napi_callback. Если обратный вызов предназначен для метода или доступа к свойству экземпляра, то аргумент this обратного вызова — это обернутый объект; обернутый экземпляр C++, являющийся объектом вызова, можно получить, вызвав napi_unwrap() в обернутом объекте.
napi_remove_wrap
napi_status napi_remove_wrap(napi_env env,
napi_value js_object,
void** result); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: Объект, связанный с исходным экземпляром. -
[out] result: Указатель на обернутый исходный экземпляр.
Возвращает napi_ok, если API выполнилось успешно.
Извлекает исходный экземпляр, который ранее был обернут в JavaScript-объект js_object с помощью napi_wrap() и удаляет оболочку. Если с оболочкой был связан обратный вызов finalize, он больше не будет вызываться, когда JavaScript-объект будет удалён сборщиком мусора.
napi_type_tag_object
napi_status napi_type_tag_object(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, который нужно пометить. -
[in] type_tag: Тег, которым нужно пометить объект.
Возвращает napi_ok, если API выполнилось успешно.
Связывает значение указателя type_tag с JavaScript-объектом. napi_check_object_type_tag() можно затем использовать для сравнения тега, который был прикреплён к объекту, с тегом, принадлежащим дополнению, чтобы убедиться, что объект имеет нужный тип.
Если у объекта уже есть связанный тег типа, этот API вернёт napi_invalid_arg.
napi_check_object_type_tag
napi_status napi_check_object_type_tag(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag,
bool* result); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, тег типа которого нужно проверить. -
[in] type_tag: Тег для сравнения с любым тегом, найденным в объекте. -
[out] result: Соответствует ли предоставленный тег типа тегу типа объекта.falseтакже возвращается, если тег типа не найден в объекте.
Возвращает napi_ok, если API выполнилось успешно.
Сравнивает указатель, предоставленный как type_tag с любым указателем, который может быть найден в js_object. Если в js_object не найден тег или если тег найден, но не соответствует type_tag, то result устанавливается в false. Если тег найден и соответствует type_tag, то result устанавливается в true.
napi_add_finalizer
napi_status napi_add_finalizer(napi_env env,
napi_value js_object,
void* 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: Необязательная ссылка на JavaScript-объект.
Возвращает napi_ok, если API выполнилось успешно.
Добавляет обратный вызов napi_finalize, который будет вызван, когда JavaScript-объект в js_object будет готов к сборке мусора. Этот API похож на napi_wrap(), за исключением того, что:
- исходные данные нельзя получить позже с помощью
napi_unwrap(), - их нельзя удалить позже с помощью
napi_remove_wrap(), и - API может вызываться несколько раз с разными данными, чтобы прикрепить их к JavaScript-объекту, и
- объект, обработанный API, может использоваться с
napi_wrap().
Предупреждение: Необязательная возвращённая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова finalize. Если она удалена до этого момента, обратный вызов finalize может никогда не быть вызван. Следовательно, при получении ссылки также требуется обратный вызов finalize, чтобы обеспечить правильное удаление ссылки.
Простые асинхронные операции
Модули дополнений часто нуждаются в использовании асинхронных помощников из libuv в рамках своей реализации. Это позволяет им планировать выполнение задач асинхронно, чтобы их методы могли возвращать значение до завершения работы. Это позволяет избежать блокировки общей работы приложения Node.js.
Node-API предоставляет стабильный интерфейс ABI для этих поддерживающих функций, охватывающий наиболее распространенные сценарии асинхронного использования.
Node-API определяет структуру napi_async_work, используемую для управления асинхронными рабочими процессами. Экземпляры создаются/удаляются с помощью napi_create_async_work и napi_delete_async_work.
Обратные вызовы execute и complete являются функциями, которые будут вызваны, когда исполнитель готов выполнить и завершить задачу соответственно.
Функция execute должна избегать выполнения каких-либо вызовов Node-API, которые могут привести к выполнению JavaScript или взаимодействию с объектами JavaScript. Чаще всего любой код, которому необходимо сделать вызовы Node-API, должен выполняться в обратном вызове complete вместо этого. Избегайте использования параметра napi_env в обратном вызове выполнения, так как он, вероятно, выполнит JavaScript.
Эти функции реализуют следующие интерфейсы:
typedef void (*napi_async_execute_callback)(napi_env env,
void* data);
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); При вызове этих методов параметр data будет содержать предоставленные дополнением данные void*, которые были переданы в вызов napi_create_async_work.
После создания асинхронный рабочий процесс может быть помещен в очередь для выполнения с помощью функции napi_queue_async_work:
napi_status napi_queue_async_work(napi_env env,
napi_async_work work); napi_cancel_async_work может использоваться, если необходимо отменить работу до её начала.
После вызова napi_cancel_async_work, обратный вызов complete будет вызван со значением статуса napi_cancelled. Работу не следует удалять до вызова обратного вызова complete, даже если она была отменена.
napi_create_async_work
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
napi_async_work* result); -
[in] env: Среда, в которой вызывается API. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан в возможныеasync_hooksinitобработчики. -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемого для диагностической информации, экспонируемой APIasync_hooks. -
[in] execute: Встроенная функция, которая должна вызываться для асинхронного выполнения логики. Данная функция вызывается из потока пула рабочих процессов и может выполняться параллельно с основным потоком обработки событий. -
[in] complete: Встроенная функция, которая будет вызвана при завершении асинхронной логики или ее отмене. Эта функция вызывается из основного потока обработки событий.napi_async_complete_callbackпредоставляет более подробную информацию. -
[in] data: Данные контекста, предоставленные пользователем. Они будут переданы обратно в функции выполнения и завершения. -
[out] result:napi_async_work*, который является дескриптором созданной асинхронной работы.
Возвращает napi_ok в случае успешного выполнения API.
Этот API выделяет объект работы, используемый для асинхронного выполнения логики. Он должен быть освобожден с помощью napi_delete_async_work, когда работа больше не требуется.
async_resource_name должен быть строкой UTF-8 с нулевым завершением.
Идентификатор async_resource_name предоставляется пользователем и должен отражать тип выполняемой асинхронной работы. Также рекомендуется использовать именование по пространствам имен, например, включив имя модуля. Дополнительную информацию см. в документации async_hooks.
napi_delete_async_work
napi_status napi_delete_async_work(napi_env env,
napi_async_work work); -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успешного выполнения API.
Этот API освобождает ранее выделенный объект работы.
Этот API можно вызывать даже при наличии ожидающей JavaScript-исключительной ситуации.
napi_queue_async_work
napi_status napi_queue_async_work(napi_env env,
napi_async_work work); -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успешного выполнения API.
Этот API запрашивает планирование ранее выделенной работы для выполнения. После успешного возврата этот API не должен вызываться повторно с тем же элементом napi_async_work, иначе результат будет неопределенным.
napi_cancel_async_work
napi_status napi_cancel_async_work(napi_env env,
napi_async_work work); -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успешного выполнения API.
Этот API отменяет запланированную работу, если она ещё не началась. Если она уже начала выполняться, её нельзя отменить, и будет возвращено napi_generic_failure. В случае успеха, обратный вызов complete будет вызван со значением статуса napi_cancelled. Работу не следует удалять до вызова обратного вызова complete, даже если она была успешно отменена.
Этот API можно вызывать даже при наличии ожидающей JavaScript-исключительной ситуации.
Настраиваемые асинхронные операции
Простые асинхронные API-интерфейсы, описанные выше, могут быть неподходящими для всех сценариев. При использовании других асинхронных механизмов необходимы следующие API-интерфейсы для правильного отслеживания асинхронной операции во время выполнения.
napi_async_init
napi_status napi_async_init(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_context* result)-
[in] env: Среда, в которой вызывается API. -
[in] async_resource: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам и доступен черезasync_hooks.executionAsyncResource(). -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемого для диагностики, доступный черезasync_hooksAPI. -
[out] result: Инициализированный асинхронный контекст.
Возвращает napi_ok в случае успешного выполнения API.
Объект async_resource необходимо удерживать до вызова napi_async_destroy, чтобы API, связанные с async_hooks, работали корректно. Для сохранения совместимости с предыдущими версиями, API-интерфейсы не поддерживают сильные ссылки на объекты async_resource, чтобы избежать утечек памяти. Однако, если объект async_resource будет собран сборщиком мусора JavaScript перед уничтожением napi_async_context функцией napi_async_destroy, вызов API, связанных с napi_async_context, таких как napi_open_callback_scope и napi_make_callback, может привести к проблемам, таким как потеря асинхронного контекста при использовании API AsyncLocalStorage.
Для сохранения совместимости с предыдущими версиями передача NULL в качестве async_resource не приводит к ошибке. Однако это не рекомендуется, так как это может привести к плохим результатам при использовании async_hooks init хуков и async_hooks.executionAsyncResource(), так как ресурс теперь необходим для реализации async_hooks для обеспечения связи между асинхронными обратными вызовами.
napi_async_destroy
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context);-
[in] env: Среда, в которой вызывается API. -
[in] async_context: Асинхронный контекст, который необходимо уничтожить.
Возвращает napi_ok в случае успешного выполнения API.
Этот API может быть вызван даже при наличии ожидающей JavaScript-исключения.
napi_make_callback
NAPI_EXTERN napi_status napi_make_callback(napi_env env,
napi_async_context async_context,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result);-
[in] env: Среда, в которой вызывается API. -
[in] async_context: Контекст асинхронной операции, вызывающей обратный вызов. Обычно это значение, полученное ранее изnapi_async_init. Для сохранения совместимости с предыдущими версиями, передачаNULLв качествеasync_contextне приводит к ошибке. Однако это приводит к неправильной работе асинхронных хуков. Возможные проблемы включают потерю асинхронного контекста при использовании APIAsyncLocalStorage. -
[in] recv: Значениеthis, переданное вызываемой функции. -
[in] func: Представлениеnapi_valueвызываемой JavaScript-функции. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив JavaScript-значений в видеnapi_value, представляющих аргументы функции. -
[out] result: Представлениеnapi_valueвозвращаемого JavaScript-объекта.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать JavaScript-функцию из нативного плагина. Этот API похож на napi_call_function. Однако он используется для вызова из нативного кода в JavaScript после возвращения из асинхронной операции (когда на стеке нет другого скрипта). Это довольно простой оболочкой над node::MakeCallback.
Важно отметить, что использование napi_make_callback не требуется внутри napi_async_complete_callback; в этом случае асинхронный контекст обратного вызова уже настроен, поэтому прямой вызов napi_call_function достаточен и уместен. Использование функции napi_make_callback может потребоваться при реализации пользовательского асинхронного поведения, которое не использует napi_create_async_work.
Любые process.nextTick или промисы, запланированные в очереди микрозадач JavaScript во время обратного вызова, выполняются до возвращения в 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хукам. Этот параметр устарел и игнорируется во время выполнения. Используйте параметрasync_resourceвnapi_async_initвместо него. -
[in] context: Контекст асинхронной операции, вызывающей обратный вызов. Это значение, полученное ранее изnapi_async_init. -
[out] result: Созданный контекст.
В некоторых случаях (например, при разрешении промисов) необходимо иметь эквивалент контекста, связанного с обратным вызовом, при выполнении определенных вызовов Node-API. Если на стеке нет другого скрипта, функции napi_open_callback_scope и napi_close_callback_scope могут использоваться для открытия/закрытия необходимого контекста.
napi_close_callback_scope
NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
napi_callback_scope scope)-
[in] env: Среда, в которой вызывается API. -
[in] scope: Контекст, который необходимо закрыть.
Этот API может быть вызван даже при наличии ожидающей JavaScript-исключения.
Управление версиями
napi_get_node_version
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
const char* release;
} napi_node_version;
napi_status napi_get_node_version(napi_env env,
const napi_node_version** version);-
[in] env: Среда, в которой вызывается API. -
[out] version: Указатель на информацию о версии Node.js.
Возвращает napi_ok в случае успешного выполнения API.
Эта функция заполняет структуру version значениями мажорной, минорной и патчевой версии Node.js, а также значением поля release из process.release.name.
Возвращаемый буфер статически выделен и не требует освобождения.
napi_get_version
napi_status napi_get_version(napi_env env,
uint32_t* result);-
[in] env: Среда, в которой вызывается API. -
[out] result: Самая высокая поддерживаемая версия Node-API.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает самую высокую версию Node-API, поддерживаемую средой выполнения Node.js. Node-API планируется как добавляемый, поэтому более новые версии Node.js могут поддерживать дополнительные API-функции. Для того, чтобы плагин мог использовать новую функцию при работе с версиями Node.js, которые её поддерживают, и обеспечивать альтернативное поведение при работе с версиями, которые её не поддерживают:
- Вызовите
napi_get_version()для определения доступности API. - Если доступна, динамически загрузите указатель на функцию, используя
uv_dlsym(). - Используйте динамически загруженный указатель для вызова функции.
- Если функция недоступна, предоставьте альтернативную реализацию без использования этой функции.
Управление памятью
napi_adjust_external_memory
NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env,
int64_t change_in_bytes,
int64_t* result);-
[in] env: Среда, в которой вызывается API. -
[in] change_in_bytes: Изменение внешней памяти, удерживаемой JavaScript-объектами. -
[out] result: Изменённое значение.
Возвращает napi_ok в случае успешного выполнения API.
Эта функция сообщает V8 о количестве внешней памяти, удерживаемой JavaScript-объектами (например, JavaScript-объект, указывающий на свою память, выделенную нативным модулем). Регистрация внешней памяти приведет к более частым глобальным сборкам мусора, чем в противном случае.
Обещания
Node-API предоставляет средства для создания Promise объектов, как описано в разделе 25.4 спецификации ECMA. Она реализует обещания как пару объектов. Когда обещание создается функцией napi_create_promise(), создается объект "отложенного выполнения" и возвращается вместе с объектом Promise. Объект отложенного выполнения привязан к созданному Promise и является единственным способом разрешить или отклонить Promise с помощью napi_resolve_deferred() или napi_reject_deferred(). Объект отложенного выполнения, созданный napi_create_promise(), освобождается функциями napi_resolve_deferred() или napi_reject_deferred(). Объект Promise может быть возвращен в JavaScript, где он может использоваться стандартным способом.
Например, чтобы создать обещание и передать его асинхронному рабочему потоку:
napi_deferred deferred; napi_value promise; napi_status status; // Create the promise. status = napi_create_promise(env, &deferred, &promise); if (status != napi_ok) return NULL; // Pass the deferred to a function that performs an asynchronous action. do_something_asynchronous(deferred); // Return the promise to JS return promise;
Функция do_something_asynchronous() бы выполнила свои асинхронные действия, а затем разрешила или отклонила отложенное выполнение, тем самым завершив обещание и освободив отложенное выполнение:
napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (asynchronous_action_succeeded) {
status = napi_resolve_deferred(env, deferred, undefined);
} else {
status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;
// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL;
napi_create_promise
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise); -
[in] env: Среда, в которой вызывается API. -
[out] deferred: Новый созданный объект отложенного выполнения, который позже может быть передан вnapi_resolve_deferred()илиnapi_reject_deferred()для разрешения или отклонения соответствующего обещания. -
[out] promise: Обещание JavaScript, связанное с объектом отложенного выполнения.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт объект отложенного выполнения и обещание JavaScript.
napi_resolve_deferred
napi_status napi_resolve_deferred(napi_env env,
napi_deferred deferred,
napi_value resolution); -
[in] env: Среда, в которой вызывается API. -
[in] deferred: Объект отложенного выполнения, связанное с обещанием, которое необходимо разрешить. -
[in] resolution: Значение, с помощью которого разрешить обещание.
Этот API разрешает обещание JavaScript с помощью объекта отложенного выполнения, с которым оно связано. Таким образом, его можно использовать только для разрешения JavaScript-обещаний, для которых доступен соответствующий объект отложенного выполнения. Это означает, что обещание должно быть создано с помощью napi_create_promise() и объект отложенного выполнения, возвращенный от этого вызова, должен быть сохранен, чтобы быть передан в этот API.
Объект отложенного выполнения освобождается при успешном выполнении.
napi_reject_deferred
napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection); -
[in] env: Среда, в которой вызывается API. -
[in] deferred: Объект отложенного выполнения, связанное с обещанием, которое необходимо отклонить. -
[in] rejection: Значение, с помощью которого отклонить обещание.
Этот API отклоняет обещание JavaScript с помощью объекта отложенного выполнения, с которым оно связано. Таким образом, его можно использовать только для отклонения JavaScript-обещаний, для которых доступен соответствующий объект отложенного выполнения. Это означает, что обещание должно быть создано с помощью napi_create_promise() и объект отложенного выполнения, возвращенный от этого вызова, должен быть сохранен, чтобы быть передан в этот API.
Объект отложенного выполнения освобождается при успешном выполнении.
napi_is_promise
napi_status napi_is_promise(napi_env env,
napi_value value,
bool* is_promise); -
[in] env: Среда, в которой вызывается API. -
[in] value: Значение для проверки -
[out] is_promise: Флаг, указывающий, является лиpromiseобъектом обещания, созданным ядром (т.е. объектом обещания, созданным подлежащим движком).
Выполнение скрипта
Node-API предоставляет API для выполнения строки JavaScript с использованием подлежащего движка JavaScript.
napi_run_script
NAPI_EXTERN napi_status napi_run_script(napi_env env,
napi_value script,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] script: Строка JavaScript, содержащая скрипт для выполнения. -
[out] result: Значение, полученное в результате выполнения скрипта.
Эта функция выполняет строку кода JavaScript и возвращает её результат с учетом следующих замечаний:
- В отличие от
eval, эта функция не позволяет скрипту получить доступ к текущей лексической области видимости, и, следовательно, также не позволяет получить доступ к области видимости модуля, что означает, что псевдо-глобальные переменные, такие какrequireнедоступны. - Скрипт может получить доступ к глобальной области видимости. Объявления функций и
varв скрипте будут добавлены в объектglobal. - Объявления переменных с использованием
letиconstбудут видны глобально, но не будут добавлены в объектglobal. - Значение
thisвнутри скрипта равноglobal.
Цикл событий libuv
Node-API предоставляет функцию для получения текущего цикла событий, связанного с определённым napi_env.
napi_get_uv_event_loop
NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env,
struct uv_loop_s** loop); -
[in] env: Среда, в которой вызывается API. -
[out] loop: Текущий экземпляр цикла libuv.
Асинхронные потокобезопасные вызовы функций
Функции JavaScript обычно могут вызываться только из основного потока нативного дополнения. Если дополнение создаёт дополнительные потоки, то функции Node-API, требующие napi_env, napi_value, или napi_ref, не должны вызываться из этих потоков.
Когда дополнение имеет дополнительные потоки, а функции JavaScript нужно вызвать на основе обработки, завершённой этими потоками, эти потоки должны взаимодействовать с основным потоком дополнения, чтобы основной поток мог вызвать функцию JavaScript от их имени. Потокобезопасные API предоставляют лёгкий способ сделать это.
Эти API предоставляют тип napi_threadsafe_function, а также API для создания, уничтожения и вызова объектов этого типа. napi_create_threadsafe_function() создаёт постоянную ссылку на napi_value, содержащий функцию JavaScript, которую можно вызывать из нескольких потоков. Вызовы происходят асинхронно. Это означает, что значения, с которыми должен вызываться обратный вызов JavaScript, будут помещены в очередь, и для каждого значения в очереди в конечном итоге будет выполнен вызов функции JavaScript.
При создании napi_threadsafe_function может быть предоставлен обратный вызов napi_finalize. Этот обратный вызов будет вызван в главном потоке, когда потокобезопасная функция будет уничтожена. Он получает контекст и данные завершения, предоставленные при создании, и предоставляет возможность очистки после потоков, например, вызывая uv_thread_join(). Помимо основного цикла, никакие потоки не должны использовать потокобезопасную функцию после завершения обратного вызова завершения.
context, заданный при вызове napi_create_threadsafe_function(), может быть получен из любого потока с помощью вызова napi_get_threadsafe_function_context().
Вызов потокобезопасной функции
napi_call_threadsafe_function() может быть использован для инициирования вызова в JavaScript. napi_call_threadsafe_function() принимает параметр, который контролирует, ведёт ли API себя блокирующим образом. Если он установлен в napi_tsfn_nonblocking, API ведёт себя неблокирующим образом, возвращая napi_queue_full, если очередь была заполнена, предотвращая добавление данных в очередь. Если он установлен в napi_tsfn_blocking, API блокируется до тех пор, пока не освободится место в очереди. napi_call_threadsafe_function() никогда не блокируется, если потокобезопасная функция была создана с максимальным размером очереди 0.
napi_call_threadsafe_function() не следует вызывать с napi_tsfn_blocking из потока JavaScript, потому что, если очередь заполнена, это может привести к тупику в потоке JavaScript.
Фактический вызов в JavaScript контролируется обратным вызовом, заданным через параметр call_js_cb. call_js_cb вызывается в главном потоке один раз для каждого значения, помещённого в очередь успешным вызовом napi_call_threadsafe_function(). Если такой обратный вызов не задан, будет использоваться стандартный обратный вызов, и результирующий вызов JavaScript не будет иметь аргументов. Обратный вызов call_js_cb получает функцию JavaScript для вызова как napi_value в своих параметрах, а также указатель контекста void*, использованный при создании napi_threadsafe_function, и указатель следующих данных, созданный одним из вторичных потоков. Затем обратный вызов может использовать API, такой как napi_call_function(), для вызова в JavaScript.
Обратный вызов также может быть вызван со значениями env и call_js_cb, установленными в NULL, чтобы указать, что вызовы в JavaScript больше невозможны, в то время как в очереди остаются элементы, которые могут потребоваться освободить. Это обычно происходит, когда процесс Node.js завершается, в то время как всё ещё активна потокобезопасная функция.
Необязательно вызывать JavaScript через napi_make_callback(), так как Node-API выполняет call_js_cb в контексте, подходящем для обратных вызовов.
Счётчик ссылок потокобезопасных функций
Потоки могут добавляться и удаляться из объекта napi_threadsafe_function в течение его существования. Таким образом, помимо задания начального числа потоков при создании, napi_acquire_threadsafe_function можно вызвать, чтобы указать, что новый поток начнёт использовать потокобезопасную функцию. Аналогично, napi_release_threadsafe_function можно вызвать, чтобы указать, что существующий поток перестанет использовать потокобезопасную функцию.
Объекты napi_threadsafe_function уничтожаются, когда каждый поток, использующий объект, вызвал napi_release_threadsafe_function() или получил статус возврата napi_closing в ответ на вызов napi_call_threadsafe_function. Очередь опустошается перед уничтожением napi_threadsafe_function. napi_release_threadsafe_function() должен быть последним вызовом API в сочетании с данным napi_threadsafe_function, потому что после завершения вызова нет гарантии, что napi_threadsafe_function всё ещё выделен. По той же причине не используйте потокобезопасную функцию после получения возвращаемого значения napi_closing в ответ на вызов napi_call_threadsafe_function. Данные, связанные с napi_threadsafe_function могут быть освобождены в его обратном вызове napi_finalize, который был передан napi_create_threadsafe_function(). Параметр initial_thread_count napi_create_threadsafe_function отмечает начальное количество приобретений потокобезопасных функций вместо вызова napi_acquire_threadsafe_function многократно при создании.
Когда количество потоков, использующих napi_threadsafe_function, достигает нуля, больше не могут начинаться новые потоки, использующие его, вызывая napi_acquire_threadsafe_function(). Фактически, все последующие API-вызовы, связанные с ним, кроме napi_release_threadsafe_function(), вернут ошибку napi_closing.
Потокобезопасная функция может быть «прервана», задав значение napi_tsfn_abort параметру napi_release_threadsafe_function(). Это заставит все последующие API, связанные с потокобезопасной функцией, за исключением napi_release_threadsafe_function(), вернуть napi_closing даже до того, как её счётчик ссылок достигнет нуля. В частности, napi_call_threadsafe_function() вернёт napi_closing, тем самым проинформировав потоки о том, что асинхронные вызовы потокобезопасной функции больше невозможны. Это можно использовать как критерий для завершения потока. При получении возвращаемого значения napi_closing от napi_call_threadsafe_function() поток больше не должен использовать потокобезопасную функцию, так как нет гарантии, что она выделена.
Решать, продолжать ли работу процесса
Аналогично обработчикам libuv, потокобезопасные функции могут быть «ссылочными» и «нессылочными». Ссылочная потокобезопасная функция сохранит цикл событий в потоке, в котором она создана, до уничтожения потокобезопасной функции. В противоположность этому, нессылочная потокобезопасная функция не помешает выходу цикла событий. Для этой цели существуют API napi_ref_threadsafe_function и napi_unref_threadsafe_function.
Ни napi_unref_threadsafe_function не отмечает потокобезопасные функции как подлежащие уничтожению, ни napi_ref_threadsafe_function не препятствует этому уничтожению.
napi_create_threadsafe_function
NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result); -
[in] env: Среда, в которой вызывается API. -
[in] func: Необязательная функция JavaScript для вызова из другого потока. Она должна быть предоставлена, еслиNULLпередаётся вcall_js_cb. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан в возможныеasync_hooksinitхуки. -
[in] async_resource_name: Строка JavaScript для предоставления идентификатора типа ресурса, предоставленного для диагностической информации, экспонируемой APIasync_hooks. -
[in] max_queue_size: Максимальный размер очереди.0для отсутствия лимита. -
[in] initial_thread_count: Начальное количество приобретений, т. е. начальное количество потоков, включая основной поток, которые будут использовать эту функцию. -
[in] thread_finalize_data: Необязательные данные, передаваемые вthread_finalize_cb. -
[in] thread_finalize_cb: Необязательная функция вызова при уничтоженииnapi_threadsafe_function. -
[in] context: Необязательные данные для прикрепления к результирующемуnapi_threadsafe_function. -
[in] call_js_cb: Необязательный обратный вызов, который вызывает функцию JavaScript в ответ на вызов в другом потоке. Этот обратный вызов будет вызван в главном потоке. Если не задан, функция JavaScript будет вызвана без параметров и сundefinedв качестве значенияthis.napi_threadsafe_function_call_jsсодержит более подробную информацию. -
[out] result: Асинхронная потокобезопасная функция JavaScript.
napi_get_threadsafe_function_context
NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
void** result); -
[in] func: Потокобезопасная функция, для которой нужно получить контекст. -
[out] result: Место для хранения контекста.
Этот API может быть вызван из любого потока, который использует func.
napi_call_threadsafe_function
NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking); -
[in] func: Асинхронная потокобезопасная функция JavaScript для вызова. -
[in] data: Данные для отправки в JavaScript через обратный вызовcall_js_cb, предоставленный во время создания потокобезопасной функции JavaScript. -
[in] is_blocking: Флаг, значение которого может бытьnapi_tsfn_blockingдля указания, что вызов должен блокироваться, если очередь заполнена, илиnapi_tsfn_nonblockingдля указания, что вызов должен возвращаться немедленно со статусомnapi_queue_fullвсякий раз, когда очередь заполнена.
Этот API не следует вызывать с napi_tsfn_blocking из потока JavaScript, поскольку в случае заполненной очереди это может привести к тупику в потоке JavaScript.
Этот API вернёт napi_closing если napi_release_threadsafe_function() был вызван с abort установленным в napi_tsfn_abort из любого потока. Значение добавляется в очередь только в том случае, если API возвращает napi_ok.
Этот API может вызываться из любого потока, который использует func.
napi_acquire_threadsafe_function
NAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func);
-
[in] func: Асинхронная потокобезопасная функция JavaScript для начала использования.
Поток должен вызвать этот API перед передачей func в любые другие потокобезопасные API-функции, чтобы указать, что он будет использовать func. Это предотвращает уничтожение func при остановке всех остальных потоков, использующих его.
Этот API может вызываться из любого потока, который начнёт использовать func.
napi_release_threadsafe_function
NAPI_EXTERN napi_status
napi_release_threadsafe_function(napi_threadsafe_function func,
napi_threadsafe_function_release_mode mode); -
[in] func: Асинхронная потокобезопасная функция JavaScript, счётчик ссылок которой нужно уменьшить. -
[in] mode: Флаг, значение которого может быть либоnapi_tsfn_releaseдля указания, что текущий поток больше не будет вызывать потокобезопасную функцию, илиnapi_tsfn_abortдля указания, что кроме текущего потока никакой другой поток не должен вызывать потокобезопасную функцию. Если он установлен вnapi_tsfn_abort, последующие вызовыnapi_call_threadsafe_function()вернутnapi_closing, и больше никаких значений не будут помещены в очередь.
Поток должен вызвать этот API, когда он перестанет использовать func. Передача func в любые потокобезопасные API после вызова этого API имеет неопределённые последствия, поскольку func может быть уничтожен.
Этот API может вызываться из любого потока, который перестанет использовать func.
napi_ref_threadsafe_function
NAPI_EXTERN napi_status napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
-
[in] env: Среда, в которой вызывается API. -
[in] func: Потокобезопасная функция для ссылки.
Этот API используется для указания, что циклу событий, выполняемому в основном потоке, не следует завершаться до тех пор, пока func не будет уничтожен. Подобно uv_ref, он также идемпотентен.
napi_unref_threadsafe_function не помечает потокобезопасные функции как подлежащие уничтожению, и napi_ref_threadsafe_function не предотвращает их уничтожение. Для этой цели доступны napi_acquire_threadsafe_function и napi_release_threadsafe_function.
Этот API может вызываться только из основного потока.
napi_unref_threadsafe_function
NAPI_EXTERN napi_status napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
-
[in] env: Среда, в которой вызывается API. -
[in] func: Потокобезопасная функция для отмены ссылки.
Этот API используется для указания, что циклу событий, выполняемому в основном потоке, разрешается завершиться до уничтожения func. Подобно uv_unref, он также идемпотентен.
Этот API может вызываться только из основного потока.
Дополнительные утилиты
node_api_get_module_file_name
NAPI_EXTERN napi_status node_api_get_module_file_name(napi_env env, const char** result);
-
[in] env: Среда, в которой вызывается API. -
[out] result: URL, содержащий абсолютный путь к месту загрузки плагина. Для файла на локальной файловой системе он начнется сfile://. Строка завершается нулём и принадлежитenv, поэтому её нельзя изменять или освобождать.
result может быть пустой строкой, если процесс загрузки плагина не смог установить имя файла плагина во время загрузки.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v16.x/docs/api/n-api.html