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, будут зависеть от символов функций C-Node-API, экспортированных Node.js. node-addon-api — более эффективный способ написания кода, вызывающего Node-API. Например, рассмотрите следующий node-addon-api код. Первая часть показывает node-addon-api код, а вторая часть показывает, что фактически используется в дополнении.
Object obj = Object::New(env); obj["foo"] = String::New(env, "bar"); copy
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;
} copy В результате дополнение использует только экспортированные C-API. Вследствие этого оно по-прежнему получает преимущества стабильности ABI, обеспечиваемой C-API.
При использовании node-addon-api вместо C-API начните с документации API docs для node-addon-api.
Ресурс Node-API предоставляет отличную ориентацию и советы для разработчиков, только начинающих работу с Node-API и node-addon-api. Дополнительные медиа-ресурсы можно найти на странице Node-API Media.
Последствия стабильности 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> copy
-
API libuv, которые также включены в Node.js и доступны через
#include <uv.h> copy
-
API V8, доступные через
#include <v8.h> copy
Таким образом, чтобы дополнение оставалось совместимым с ABI в основных версиях Node.js, оно должно использовать Node-API исключительно, ограничивая себя использованием
#include <node_api.h> copy
и проверяя для всех внешних библиотек, которые оно использует, что внешняя библиотека гарантирует стабильность 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 copy
Для разработчиков Windows Visual Studio предоставляет все необходимые инструменты компилятора. Однако нет необходимости устанавливать весь IDE Visual Studio. Следующая команда устанавливает необходимую инструментальную цепочку:
npm install --global windows-build-tools copy
Ниже приведены описания дополнительных инструментов, доступных для разработки и развертывания нативных дополнений 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. build_with_cmake — пример проекта нативного дополнения, основанного на CMake.
Загрузка предварительно скомпилированных бинарных файлов
Три перечисленных инструмента позволяют разработчикам и авторам нативных дополнений создавать и загружать бинарные файлы на публичные или частные серверы. Эти инструменты обычно интегрируются с системами сборки CI/CD, такими как Travis CI и AppVeyor, чтобы собирать и загружать бинарные файлы для различных платформ и архитектур. Эти бинарные файлы затем доступны для скачивания пользователям, которым не нужно устанавливать инструментальную цепочку C/C++.
node-pre-gyp
node-pre-gyp — это инструмент, основанный на node-gyp, который добавляет возможность загрузки бинарных файлов на сервер по выбору разработчика. node-pre-gyp имеет особенно хорошую поддержку загрузки бинарных файлов на Amazon S3.
prebuild
prebuild — это инструмент, который поддерживает сборку с помощью node-gyp или CMake.js. В отличие от node-pre-gyp, который поддерживает различные серверы, prebuild загружает бинарные файлы только на GitHub releases. prebuild — хороший выбор для проектов GitHub, использующих CMake.js.
prebuildify
prebuildify — это инструмент, основанный на node-gyp. Преимущество prebuildify заключается в том, что созданные бинарные файлы встроены в нативное дополнение при его загрузке в npm. Бинарные файлы загружаются из npm и становятся немедленно доступными для пользователя модуля при установке нативного дополнения.
Использование
Для использования функций Node-API включите файл node_api.h, который находится в каталоге src в дереве разработки node:
#include <node_api.h> copy
Это позволит использовать по умолчанию NAPI_VERSION для данной версии Node.js. Для обеспечения совместимости с определёнными версиями Node-API версия может быть указана явно при включении заголовка:
#define NAPI_VERSION 3 #include <node_api.h> copy
Это ограничит поверхность Node-API только функциональностью, доступной в указанных (и более ранних) версиях.
Часть поверхности Node-API является экспериментальной и требует явного включения:
#define NAPI_EXPERIMENTAL #include <node_api.h> copy
В этом случае вся поверхность API, включая экспериментальные API, будет доступна коду модуля.
Иногда вводятся экспериментальные функции, которые влияют на уже выпущенные и стабильные API. Эти функции можно отключить с помощью отключения:
#define NAPI_EXPERIMENTAL #define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT #include <node_api.h> copy
где <FEATURE_NAME> — имя экспериментальной функции, которая влияет как на экспериментальные, так и на стабильные API.
Матрица версий Node-API
До версии 9 версии Node-API были аддитивными и имели независимую нумерацию от Node.js. Это означало, что любая версия являлась расширением предыдущей, содержала все API предыдущей версии с некоторыми дополнениями. Каждая версия Node.js поддерживала только одну версию Node-API. Например, версия v18.15.0 поддерживает только Node-API версии 8. Стабильность ABI достигалась благодаря тому, что версия 8 являлась строгим супермножеством всех предыдущих версий.
Начиная с версии 9, хотя версии Node-API по-прежнему имеют независимую нумерацию, дополнение, работавшее с версией Node-API 9, может потребовать обновлений кода для работы с версией Node-API 10. Тем не менее, стабильность ABI сохраняется, поскольку версии Node.js, поддерживающие версии Node-API выше 8, будут поддерживать все версии между 8 и самой высокой поддерживаемой версией и по умолчанию будут предоставлять API версии 8, если дополнение не использует более высокую версию Node-API. Этот подход обеспечивает гибкость для лучшей оптимизации существующих функций Node-API при сохранении стабильности ABI. Существующие дополнения могут продолжать работать без перекомпиляции, используя более раннюю версию Node-API. Если дополнению необходима функциональность из более новой версии Node-API, для использования новых функций всё равно потребуются изменения в существующем коде и перекомпиляция.
В версиях Node.js, которые поддерживают Node-API версии 9 и выше, определение NAPI_VERSION=X и использование существующих макросов инициализации дополнений добавят запрошенную версию Node-API, которая будет использоваться во время выполнения, в дополнение. Если NAPI_VERSION не задано, по умолчанию используется версия 8.
Данная таблица может быть неактуальной в старых ветках, наиболее актуальная информация содержится в последней документации API по адресу: Матрица версий Node-API
| Версия Node-API | Поддерживается в |
|---|---|
| 9 | v18.17.0+, 20.3.0+, 21.0.0 и все более поздние версии |
| 8 | v12.22.0+, v14.17.0+, v15.12.0+, 16.0.0 и все более поздние версии |
| 7 | v10.23.0+, v12.19.0+, v14.12.0+, 15.0.0 и все более поздние версии |
| 6 | v10.20.0+, v12.17.0+, 14.0.0 и все более поздние версии |
| 5 | v10.17.0+, v12.11.0+, 13.0.0 и все более поздние версии |
| 4 | v10.16.0+, v11.8.0+, 12.0.0 и все более поздние версии |
| 3 | v6.14.2*, 8.11.2+, v9.11.0+*, 10.0.0 и все более поздние версии |
| 2 | v8.10.0+*, v9.3.0+*, 10.0.0 и все более поздние версии |
| 1 | v8.6.0+**, v9.0.0+*, 10.0.0 и все более поздние версии |
* Node-API был экспериментальным.
** Node.js 8.0.0 включал Node-API как экспериментальный. Он был выпущен как Node-API версии 1, но продолжал развиваться до Node.js 8.6.0. API отличается в версиях до Node.js 8.6.0. Рекомендуется использовать Node-API версии 3 или выше.
Каждая документация API Node-API будет иметь заголовок added in:, а стабильные API будут дополнительно иметь заголовок Node-API version:. API можно использовать напрямую при использовании версии Node.js, поддерживающей версию Node-API, указанную в Node-API version: или выше. При использовании версии Node.js, которая не поддерживает указанную в Node-API version: версию Node-API, или если нет указанной в 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_ copy
// addon.c
#include "addon.h"
#define NODE_API_CALL(env, call) \
do { \
napi_status status = (call); \
if (status != napi_ok) { \
const napi_extended_error_info* error_info = NULL; \
napi_get_last_error_info((env), &error_info); \
const char* err_message = error_info->error_message; \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
/* If an exception is already pending, don't rethrow it */ \
if (!is_pending) { \
const char* message = (err_message == NULL) \
? "empty error message" \
: err_message; \
napi_throw_error((env), NULL, message); \
} \
return NULL; \
} \
} while(0)
static napi_value
DoSomethingUseful(napi_env env, napi_callback_info info) {
// Do something useful.
return NULL;
}
napi_value create_addon(napi_env env) {
napi_value result;
NODE_API_CALL(env, napi_create_object(env, &result));
napi_value exported_function;
NODE_API_CALL(env, napi_create_function(env,
"doSomethingUseful",
NAPI_AUTO_LENGTH,
DoSomethingUseful,
NULL,
&exported_function));
NODE_API_CALL(env, napi_set_named_property(env,
result,
"doSomethingUseful",
exported_function));
return result;
} copy// addon_node.c
#include <node_api.h>
#include "addon.h"
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
// This function body is expected to return a `napi_value`.
// The variables `napi_env env` and `napi_value exports` may be used within
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
return create_addon(env);
} copyAPI жизненного цикла среды
Раздел 8.7 Спецификации языка ECMAScript определяет понятие "Agent" как автономную среду, в которой выполняется код JavaScript. Процесс может запускать и завершать несколько таких Agent, либо одновременно, либо последовательно.
Среда Node.js соответствует ECMAScript Agent. В основном процессе среда создается при запуске, и дополнительные среды могут быть созданы в отдельных потоках, чтобы служить потоками-рабочими нитями. Когда Node.js интегрирован в другое приложение, основной поток приложения может многократно создавать и уничтожать среду Node.js в течение жизненного цикла процесса приложения, так что каждая созданная приложением среда Node.js, в свою очередь, может создавать и уничтожать дополнительные среды, как потоки-рабочие нити, в течение своего жизненного цикла.
С точки зрения нативного дополнения это означает, что предоставляемые им связи могут вызываться многократно, из нескольких контекстов и даже одновременно из нескольких потоков.
Нативным дополнениям может потребоваться выделять глобальное состояние, которое они используют в течение своего жизненного цикла среды Node.js, чтобы состояние было уникальным для каждого экземпляра дополнения.
Для этого Node-API предоставляет способ связывать данные, так что его жизненный цикл связан с жизненным циклом среды Node.js.
napi_set_instance_data
napi_status napi_set_instance_data(node_api_nogc_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] data: Элемент данных, который нужно сделать доступным для связей этого экземпляра. -
[in] finalize_cb: Функция, которая вызывается при разборке среды. Функция получаетdata, чтобы она могла его освободить.napi_finalizeсодержит подробную информацию. -
[in] finalize_hint: Необязательное значение, передаваемое в обратный вызов finalize при сборе.
Возвращает napi_ok, если API выполнено успешно.
Этот API связывает data с текущей запущенной средой Node.js. data может быть позже получен с помощью napi_get_instance_data(). Любые существующие данные, связанные с текущей запущенной средой Node.js, которые были установлены с помощью предыдущего вызова napi_set_instance_data(), будут перезаписаны. Если предыдущим вызовом был предоставлен finalize_cb, он не будет вызван.
napi_get_instance_data
napi_status napi_get_instance_data(node_api_nogc_env env,
void** data); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[out] data: Элемент данных, который ранее был связан с текущей запущенной средой Node.js вызовомnapi_set_instance_data().
Возвращает napi_ok, если API выполнено успешно.
Этот API извлекает данные, которые ранее были связаны с текущей запущенной средой Node.js с помощью 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_no_external_buffers_allowed,
napi_cannot_run_js
} napi_status; copy Если требуется дополнительная информация при получении 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; copy -
error_message: Строка в кодировке UTF8, содержащая описание ошибки, нейтральное по отношению к виртуальной машине. -
engine_reserved: Зарезервировано для деталей ошибок, специфичных для виртуальной машины. В настоящее время не реализовано ни для одной виртуальной машины. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. В настоящее время не реализован ни для одной виртуальной машины. -
error_code: Код состояния Node-API, возникший в результате последней ошибки.
Дополнительную информацию см. в разделе Обработка ошибок.
napi_env
napi_env используется для представления контекста, который реализация Node-API на основе виртуальной машины может использовать для сохранения состояния, специфичного для виртуальной машины. Эта структура передаётся нативные функции при их вызове, и её необходимо передавать обратно при выполнении вызовов Node-API. В частности, тот же napi_env, который был передан при первоначальном вызове нативной функции, должен передаваться в любых последующих вложенных вызовах Node-API. Кэширование napi_env в целях общего повторного использования и передача napi_env между экземплярами одного и того же плагина, выполняющегося на разных потоках Worker, запрещено. napi_env становится недоступным, когда экземпляр нативного плагина загружается. Уведомление об этом событии передаётся через обратные вызовы, предоставленные napi_add_env_cleanup_hook и napi_set_instance_data.
node_api_nogc_env
Этот вариант napi_env передаётся синхронным финализаторам (node_api_nogc_finalize). Подмножество Node-API принимает параметр типа node_api_nogc_env в качестве первого аргумента. Эти API не обращаются к состоянию движка JavaScript и, следовательно, безопасны для вызова из синхронных финализаторов. Передача параметра типа napi_env в эти API разрешена, однако передача параметра типа node_api_nogc_env в API, которые обращаются к состоянию движка JavaScript, запрещена. Попытка сделать это без преобразования приведёт к предупреждению компилятора или ошибке при компиляции плагинов с флагами, которые заставляют их генерировать предупреждения и/или ошибки, когда в функцию передаются неверные типы указателей. Вызов таких API из синхронного финализатора в конечном итоге приведёт к завершению приложения.
napi_value
Это непрозрачный указатель, используемый для представления значения JavaScript.
napi_threadsafe_function
Это непрозрачный указатель, представляющий функцию JavaScript, которая может вызываться асинхронно из нескольких потоков через napi_call_threadsafe_function().
napi_threadsafe_function_release_mode
Значение, которое должно быть передано napi_release_threadsafe_function(), чтобы указать, следует ли закрыть функцию с безопасным доступом из нескольких потоков немедленно (napi_tsfn_abort) или просто освободить (napi_tsfn_release), сделав её доступной для последующего использования через napi_acquire_threadsafe_function() и napi_call_threadsafe_function().
typedef enum {
napi_tsfn_release,
napi_tsfn_abort
} napi_threadsafe_function_release_mode; copy
napi_threadsafe_function_call_mode
Значение, которое должно быть передано napi_call_threadsafe_function(), чтобы указать, нужно ли блокировать вызов, когда очередь, связанная с функцией с безопасным доступом из нескольких потоков, заполнена.
typedef enum {
napi_tsfn_nonblocking,
napi_tsfn_blocking
} napi_threadsafe_function_call_mode; copy Типы управления памятью Node-API
napi_handle_scope
Это абстракция, используемая для управления и изменения срока жизни объектов, созданных в определённом контексте. В целом, значения Node-API создаются в контексте области обработки объектов. При вызове нативной функции из JavaScript существует стандартная область обработки объектов. Если пользователь явно не создаёт новую область обработки объектов, значения Node-API будут создаваться в стандартной области обработки объектов. При любом вызове кода за пределами выполнения нативной функции (например, при вызове обратного вызова libuv) модуль должен создать область обработки перед вызовом функций, которые могут привести к созданию значений JavaScript.
Области обработки объектов создаются с помощью napi_open_handle_scope и уничтожаются с помощью napi_close_handle_scope. Закрытие области может указывать сборщику мусора, что все napi_value, созданные в течение срока действия области обработки объектов, больше не ссылаются из текущей области стека.
Для получения дополнительной информации см. раздел Управление сроком жизни объектов.
napi_escapable_handle_scope
Области обработки объектов с возможностью освобождения — это специальный тип области обработки объектов для возврата значений, созданных в определённой области обработки объектов, в родительскую область.
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; copy
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); copy
За исключением случаев, описанных в разделе Управление сроком жизни объектов, создание области обработки объектов и/или области обратных вызовов внутри napi_callback не требуется.
node_api_nogc_finalize
Тип указателя на функцию, предоставляемую плагином, которая позволяет пользователю получать уведомления о том, когда внешние данные готовы к очистке, потому что связанный с ними объект был собран сборщиком мусора. Пользователь должен предоставить функцию, удовлетворяющую следующей сигнатуре, которая будет вызвана при сборе объекта. В настоящее время node_api_nogc_finalize можно использовать для определения момента сбора объектов, имеющих внешние данные.
typedef void (*node_api_nogc_finalize)(node_api_nogc_env env,
void* finalize_data,
void* finalize_hint); copy За исключением случаев, описанных в разделе Управление сроком жизни объектов, создание области обработки объектов и/или области обратных вызовов внутри тела функции не требуется.
Поскольку эти функции могут вызываться, когда движок JavaScript находится в состоянии, при котором он не может выполнять код JavaScript, вызывать могут только Node-API, принимающие node_api_nogc_env в качестве первого параметра. node_api_post_finalizer можно использовать для планирования вызовов Node-API, требующих доступа к состоянию движка JavaScript, после завершения текущего цикла сбора мусора.
В случае node_api_create_external_string_latin1 и node_api_create_external_string_utf16 параметр env может быть null, потому что внешние строки могут быть собраны на позднем этапе завершения работы окружения.
История изменений:
-
экспериментально (
NAPI_EXPERIMENTAL):Могут быть вызваны только вызовы Node-API, принимающие
node_api_nogc_envв качестве первого параметра, в противном случае приложение будет завершено с соответствующим сообщением об ошибке. Эта функция может быть отключена, если определитьNODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT.
napi_finalize
Тип указателя на функцию, предоставляемую плагином, позволяющая пользователю запланировать группу вызовов Node-API в ответ на событие сбора мусора после завершения цикла сбора мусора. Эти указатели на функции могут использоваться с node_api_post_finalizer.
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint); copy История изменений:
-
экспериментальный (
NAPI_EXPERIMENTALопределён):Функцию этого типа больше нельзя использовать в качестве финализатора, за исключением случаев использования
node_api_post_finalizer. Вместо этого следует использоватьnode_api_nogc_finalize. Эту функцию можно отключить, определивNODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT.
napi_async_execute_callback
Указатель на функцию, используемый с функциями, поддерживающими асинхронные операции. Функции обратного вызова должны соответствовать следующей сигнатуре:
typedef void (*napi_async_execute_callback)(napi_env env, void* data); copy
Реализации этой функции должны избегать выполнения вызовов 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); copy Если только по причинам, обсуждаемым в Управлении жизненным циклом объектов, создание обработчика и/или области обратного вызова внутри тела функции не является необходимым.
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); copy -
[in] env: Среда для использования для вызовов API илиNULL, если потокобезопасная функция разрывается, иdataможет потребоваться освободить. -
[in] js_callback: Функция JavaScript для вызова илиNULL, если потокобезопасная функция разрывается, иdataможет потребоваться освободить. Она также может бытьNULL, если потокобезопасная функция была создана безjs_callback. -
[in] context: Необязательные данные, с которыми была создана потокобезопасная функция. -
[in] data: Данные, созданные вторичным потоком. Ответственность обратного вызова — преобразовать эти данные в значения JavaScript (с помощью функций Node-API), которые можно передать в качестве параметров при вызовеjs_callback. Этот указатель полностью управляется потоками и этим обратным вызовом. Таким образом, этот обратный вызов должен освободить данные.
Если только по причинам, обсуждаемым в Управлении жизненным циклом объектов, создание обработчика и/или области обратного вызова внутри тела функции не является необходимым.
napi_cleanup_hook
Указатель на функцию, используемый с napi_add_env_cleanup_hook. Он будет вызван при разрыве среды.
Функции обратного вызова должны соответствовать следующей сигнатуре:
typedef void (*napi_cleanup_hook)(void* data); copy
-
[in] data: Данные, переданные вnapi_add_env_cleanup_hook.
napi_async_cleanup_hook
Указатель на функцию, используемый с napi_add_async_cleanup_hook. Он будет вызван при разрыве среды.
Функции обратного вызова должны соответствовать следующей сигнатуре:
typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
void* data); copy -
[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;
}; copy -
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(node_api_nogc_env env,
const napi_extended_error_info** result); copy -
[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 для получения и очистки исключения. При успехе результат будет содержать дескриптор последнего брошенного JavaScript-исключения Object. Если после получения исключения выяснится, что исключение всё-таки не может быть обработано, его можно повторно бросить с помощью napi_throw, где ошибка — это значение JavaScript, которое нужно бросить.
Также доступны следующие вспомогательные функции, если нативному коду нужно бросить исключение или определить, является ли napi_value экземпляром JavaScript-объекта Error: napi_throw_error, napi_throw_type_error, napi_throw_range_error, node_api_throw_syntax_error и napi_is_error.
Также доступны следующие вспомогательные функции, если нативному коду нужно создать объект Error: napi_create_error, napi_create_type_error, napi_create_range_error и node_api_create_syntax_error, где результат — napi_value, который ссылается на только что созданный JavaScript-объект Error.
Проект Node.js добавляет коды ошибок ко всем ошибкам, генерируемым внутри. Цель состоит в том, чтобы приложения использовали эти коды ошибок для всех проверок ошибок. Соответствующие сообщения об ошибках останутся, но будут использоваться только для ведения журнала и отображения, с ожиданием, что сообщение может измениться без применения SemVer. Для поддержки этой модели в Node-API, как во внутренней функциональности, так и для функциональности конкретных модулей (поскольку это хорошая практика), функции throw_ и create_ принимают необязательный параметр code, который представляет собой строку кода, добавляемого к объекту ошибки. Если необязательный параметр NULL, то код к ошибке не будет привязан. Если код предоставлен, имя, связанное с ошибкой, также обновляется следующим образом:
originalName [code] copy
где originalName — исходное имя, связанное с ошибкой, а code — предоставленный код. Например, если код — 'ERR_ERROR_1', и создаётся TypeError, имя будет:
TypeError [ERR_ERROR_1] copy
napi_throw
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error); copy
-
[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); copy -
[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); copy -
[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); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибке. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok, если API успешно выполнился.
Этот API бросает JavaScript-исключение RangeError с предоставленным текстом.
node_api_throw_syntax_error
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
const char* code,
const char* msg); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибке. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok, если API успешно выполнился.
Этот API бросает JavaScript-исключение SyntaxError с предоставленным текстом.
napi_is_error
NAPI_EXTERN napi_status napi_is_error(napi_env env,
napi_value value,
bool* result); copy -
[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); copy -
[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); copy -
[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); copy -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который будет связан с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok, если API успешно выполнился.
Этот API возвращает JavaScript RangeError со предоставленным текстом.
node_api_create_syntax_error
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который будет связан с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok, если API успешно выполнился.
Этот API возвращает JavaScript SyntaxError со предоставленным текстом.
napi_get_and_clear_last_exception
napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result); copy -
[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); copy
-
[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); copy
-
[in] env: Окружение, в котором вызывается API. -
[in] err: Ошибка, передаваемая в'uncaughtException'.
Вызывает 'uncaughtException' в JavaScript. Полезно, если асинхронный обработчик выбрасывает исключение без возможности восстановления.
Критические ошибки
В случае невосстановимой ошибки в нативном дополнении может быть выброшена критическая ошибка, чтобы немедленно завершить процесс.
napi_fatal_error
NAPI_NO_RETURN void napi_fatal_error(const char* location,
size_t location_len,
const char* message,
size_t message_len); copy -
[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
} copy Это приведет к созданию большого количества ссылок, что приведет к существенному расходу ресурсов. Кроме того, даже если нативный код может использовать только самую последнюю ссылку, все связанные объекты также будут удерживаться в памяти, так как они все принадлежат одной и той же области видимости.
Для решения этой проблемы 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;
}
} copy При вложенности областей видимости возникают случаи, когда ссылке из внутренней области видимости необходимо жить дольше, чем срок существования этой области. 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); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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 предоставляет методы для создания постоянных ссылок на значения. В настоящее время Node-API позволяет создавать ссылки только для ограниченного набора типов значений, включая object, external, function и symbol.
Каждая ссылка имеет связанный счетчик со значением 0 или больше, который определяет, будет ли ссылка удерживать соответствующее значение в памяти. Ссылки со значением счетчика 0 не препятствуют сбору мусора соответствующих значений. Значения типов object (object, function, external) и symbol становятся «слабыми» ссылками и могут по-прежнему быть доступными, даже если они не собраны. Любой счетчик, больший 0, предотвратит сбор мусора значений.
Значения symbol имеют разные типы. Истинное поведение слабой ссылки поддерживается только локальными символами, созданными с помощью функции napi_create_symbol или вызовами конструктора JavaScript Symbol(). Глобально зарегистрированные символы, созданные с помощью функции node_api_symbol_for или вызовами функций JavaScript Symbol.for(), остаются всегда сильными ссылками, потому что сборщик мусора их не собирает. То же самое относится к общеизвестным символам, таким как Symbol.iterator. Они также никогда не собираются сборщиком мусора.
Ссылки могут быть созданы с начальным счетчиком ссылок. Затем счетчик можно изменить с помощью napi_reference_ref и napi_reference_unref. Если объект будет собран, а счетчик ссылки равен 0, все последующие вызовы для получения объекта, связанного со ссылкой napi_get_reference_value, вернут NULL для возвращаемого napi_value. Попытка вызвать napi_reference_ref для ссылки, объект которой был собран, приведет к ошибке.
Ссылки должны быть удалены, когда они больше не нужны дополнению. При удалении ссылки она больше не будет препятствовать сбору мусора соответствующего объекта. Отсутствие удаления постоянной ссылки приведет к утечке памяти, при которой как нативный память для постоянной ссылки, так и соответствующий объект в куче будут удерживаться навсегда.
Можно создать несколько постоянных ссылок, которые ссылаются на один и тот же объект, каждая из которых будет удерживать объект в памяти или нет, в зависимости от ее индивидуального счетчика. Несколько постоянных ссылок на один и тот же объект могут привести к непредвиденному удержанию нативной памяти. Нативные структуры для постоянной ссылки должны быть сохранены до тех пор, пока не будут выполнены финализаторы для ссылающегося объекта. Если для одного и того же объекта создается новая постоянная ссылка, финализаторы этого объекта не будут выполнены, и нативная память, на которую указывает предыдущая постоянная ссылка, не будет освобождена. Этому можно избежать, вызвав napi_delete_reference в дополнение к napi_reference_unref, когда это возможно.
История изменений:
-
Экспериментальная (
NAPI_EXPERIMENTALопределено):Ссылки могут быть созданы для всех типов значений. Новые поддерживаемые типы значений не поддерживают семантику слабой ссылки, и значения этих типов освобождаются, когда счетчик ссылок становится 0, и больше не могут быть доступны по ссылке.
napi_create_reference
NAPI_EXTERN napi_status napi_create_reference(napi_env env,
napi_value value,
uint32_t initial_refcount,
napi_ref* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, для которого создается ссылка. -
[in] initial_refcount: Начальное значение счетчика ссылок для новой ссылки. -
[out] result:napi_ref, указывающий на новую ссылку.
Возвращает napi_ok, если API выполнена успешно.
Этот API создает новую ссылку со значением счетчика ссылок для переданного значения.
napi_delete_reference
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref); copy
-
[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); copy -
[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); copy -
[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); copy -
[in] env: Окружение, в котором вызывается API. -
[in] ref:napi_ref, для которого запрашивается соответствующее значение. -
[out] result:napi_value, на который ссылаетсяnapi_ref.
Возвращает napi_ok, если API успешно выполнилась.
Если ссылка всё ещё действительна, этот API возвращает napi_value, представляющий значение JavaScript, связанное с 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(node_api_nogc_env env,
napi_cleanup_hook fun,
void* arg); copy Регистрирует 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(node_api_nogc_env env,
void (*fun)(void* arg),
void* arg); copy Отменяет регистрацию fun как функции, которая будет выполнена с параметром arg после выхода из текущей среды Node.js. Как аргумент, так и значение функции должны быть точными совпадениями.
Функция должна была быть первоначально зарегистрирована с помощью napi_add_env_cleanup_hook, иначе процесс прервётся.
napi_add_async_cleanup_hook
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
node_api_nogc_env env,
napi_async_cleanup_hook hook,
void* arg,
napi_async_cleanup_hook_handle* remove_handle); copy -
[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); copy -
[in] remove_handle: Ручка асинхронного обработчика очистки, созданного с помощьюnapi_add_async_cleanup_hook.
Отменяет регистрацию обработчика очистки, соответствующего remove_handle. Это предотвратит выполнение обработчика, если он ещё не начал выполняться. Это необходимо вызвать с любым значением napi_async_cleanup_hook_handle, полученным из napi_add_async_cleanup_hook.
Финализация при выходе из среды Node.js
Среда Node.js может быть разрушена в любой момент, как только возможно, при запрещённом выполнении JavaScript, например, по запросу worker.terminate(). Когда среда разрушается, зарегистрированные napi_finalize обратные вызовы объектов JavaScript, потокобезопасных функций и данных экземпляров среды вызываются немедленно и независимо.
Вызов napi_finalize обратных вызовов запланирован после вручную зарегистрированных обработчиков очистки. Чтобы обеспечить правильный порядок финализации дополнений во время завершения среды и избежать использования после освобождения в napi_finalize обратном вызове, дополнения должны зарегистрировать обработчик очистки с помощью napi_add_env_cleanup_hook и napi_add_async_cleanup_hook, чтобы вручную освободить выделенный ресурс в правильном порядке.
Регистрация модуля
Модули Node-API регистрируются аналогично другим модулям, за исключением того, что вместо использования макроса NODE_MODULE используется следующее:
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) copy
Следующее различие заключается в сигнатуре метода Init. Для модуля Node-API она следующая:
napi_value Init(napi_env env, napi_value exports); copy
Возвращаемое значение от 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;
} copy Для задания функции, которая должна возвращаться 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;
} copy Для определения класса, чтобы можно было создавать новые экземпляры (часто используется с обёртыванием объекта):
// 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;
} copy Вы также можете использовать макрос NAPI_MODULE_INIT, который является сокращением для NAPI_MODULE и определения функции Init:
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
napi_value answer;
napi_status result;
status = napi_create_int64(env, 42, &answer);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "answer", answer);
if (status != napi_ok) return NULL;
return exports;
} copy Параметры env и exports предоставляются в теле макроса NAPI_MODULE_INIT.
Все дополнения Node-API обладают контекстно-зависимым характером, то есть их можно загружать несколько раз. При объявлении такого модуля существуют определённые соображения по проектированию. Дополнительные сведения содержатся в документации по модулям с контекстно-зависимым характером.
Переменные env и exports будут доступны внутри тела функции после вызова макроса.
Дополнительные сведения о настройке свойств объектов см. в разделе Работа со свойствами JavaScript.
Дополнительные сведения о создании модулей дополнений в целом см. в существующем API.
Работа с JavaScript-значениями
Node-API предоставляет набор API для создания всех типов JavaScript-значений. Некоторые из этих типов описаны в разделе 6 Спецификации языка ECMAScript.
В основном, эти API используются для одного из следующих:
- Создание нового JavaScript-объекта
- Преобразование примитивного типа C в значение Node-API
- Преобразование значения Node-API в примитивный тип C
- Получение глобальных экземпляров, включая
undefinedиnull
Значения Node-API представлены типом napi_value. Любой вызов 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; copy Описывает перечисления фильтров 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; copy Биты фильтра свойств. Их можно объединять с помощью операции OR для создания составного фильтра.
napi_key_conversion
typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion; copy 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; copy Описывает тип 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; copy Представляет собой базовый бинарный скалярный тип данных TypedArray. Элементы этого перечисления соответствуют разделу 22.2 Спецификации языка ECMAScript.
Функции создания объектов
napi_create_array
napi_status napi_create_array(napi_env env, napi_value* result) copy
-
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Начальная длинаArray. -
[out] result:napi_value, представляющий JavaScript-Array.
Возвращает napi_ok, если API успешно выполнился.
Этот API возвращает значение Node-API, соответствующее JavaScript-типу Array. Свойство length Array установлено в переданное значение параметра length. Однако гарантируется ли предварительная выделение буфера под VМ при создании массива, зависит от реализации подлежащей VМ. Если буфер должен быть непрерывным блоком памяти, к которому можно напрямую читать и записывать через 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) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Длина в байтах создаваемого буфера массива. -
[out] data: Указатель на базовый байтовый буферArrayBuffer.dataможно необязательно пропустить, передавNULL. -
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] size: Размер базового буфера в байтах. -
[out] data: Необработанный указатель на базовый буфер.dataможно необязательно пропустить, передавNULL. -
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] size: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Необработанный указатель на буфер для копирования. -
[out] result_data: Указатель на базовый буфер данных новогоBuffer.result_dataможно необязательно пропустить, передавNULL. -
[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); copy -
[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) copy -
[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_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) copy -
[in] env: Среда, в которой вызывается API. -
[in] external_data: Указатель на внутренний байтовый буферArrayBuffer. -
[in] byte_length: Длина внутреннего буфера в байтах. -
[in] finalize_cb: Необязательный обратный вызов, вызываемый при сбореArrayBuffer.napi_finalizeсодержит подробную информацию. -
[in] finalize_hint: Необязательный параметр, передаваемый в обратный вызов finalize во время сбора. -
[out] result:napi_value, представляющий JavaScript-объектArrayBuffer.
Возвращает napi_ok, если API успешно выполнилась.
Некоторые среды выполнения, отличные от Node.js, отказались от поддержки внешних буферов. В средах, отличных от Node.js, этот метод может возвращать napi_no_external_buffers_allowed, чтобы указать, что внешние буферы не поддерживаются. Одним из таких сред выполнения является Electron, как описано в этом вопросе electron/issues/35801.
Для поддержания совместимости со всеми средами выполнения вы можете определить NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED в своем дополнении перед включением заголовков node-api. Это скроет 2 функции, создающие внешние буферы. Это гарантирует ошибку компиляции, если вы случайно используете один из этих методов.
Этот API возвращает значение Node-API, соответствующее JavaScript-объекту ArrayBuffer. Внутренний байтовый буфер ArrayBuffer выделен и управляется внешне. Вызывающая сторона должна гарантировать, что байтовый буфер остается валидным до тех пор, пока не будет вызван обратный вызов finalize.
API добавляет обратный вызов napi_finalize, который будет вызван при сборе только что созданного JavaScript-объекта.
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) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Необработанный указатель на внутренний буфер для экспонирования JavaScript. -
[in] finalize_cb: Необязательный обратный вызов, вызываемый при сбореArrayBuffer.napi_finalizeсодержит подробную информацию. -
[in] finalize_hint: Необязательный параметр, передаваемый в обратный вызов finalize во время сбора. -
[out] result:napi_value, представляющий JavaScript-объектnode::Buffer.
Возвращает napi_ok, если API успешно выполнилась.
Некоторые среды выполнения, отличные от Node.js, отказались от поддержки внешних буферов. В средах, отличных от Node.js, этот метод может возвращать napi_no_external_buffers_allowed, чтобы указать, что внешние буферы не поддерживаются. Одним из таких сред выполнения является Electron, как описано в этом вопросе electron/issues/35801.
Для поддержания совместимости со всеми средами выполнения вы можете определить NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED в своем дополнении перед включением заголовков node-api. Это скроет 2 функции, создающие внешние буферы. Это гарантирует ошибку компиляции, если вы случайно используете один из этих методов.
Этот API выделяет объект node::Buffer и инициализирует его данными, поддерживаемыми переданным буфером. Хотя это по-прежнему полностью поддерживаемая структура данных, в большинстве случаев будет достаточно использования TypedArray.
API добавляет обратный вызов napi_finalize, который будет вызван при сборе только что созданного JavaScript-объекта.
Для Node.js >=4 Buffers являются Uint8Array.
napi_create_object
napi_status napi_create_object(napi_env env, napi_value* result) copy
-
[in] env: Среда, в которой вызывается API. -
[out] result: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) copy -
[in] env: Среда, в которой вызывается API. -
[in] description: Необязательноеnapi_value, которое ссылается на JavaScript-объектstring, который будет установлен в качестве описания для символа. -
[out] result:napi_value, представляющий JavaScript-символsymbol.
Возвращает napi_ok, если API успешно выполнилась.
Этот API создает значение JavaScript-символа из UTF8-строки C.
Тип JavaScript-символа symbol описан в Разделе 19.4 спецификации языка ECMAScript.
node_api_symbol_for
napi_status node_api_symbol_for(napi_env env,
const char* utf8description,
size_t length,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] utf8description: Строка C в кодировке UTF-8, представляющая текст, который будет использоваться в качестве описания для символа. -
[in] length: Длина строки описания в байтах илиNAPI_AUTO_LENGTH, если она имеет нуль-терминатор. -
[out] result:napi_value, представляющий JavaScript-символsymbol.
Возвращает napi_ok, если API успешно выполнилась.
Этот API ищет в глобальном реестре существующий символ с заданным описанием. Если символ уже существует, он будет возвращен, в противном случае в реестре будет создан новый символ.
Тип 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) copy -
[in] env: Среда, в которой вызывается API. -
[in] type: Скалярный тип данных элементов внутриTypedArray. -
[in] length: Количество элементов вTypedArray. -
[in] arraybuffer:ArrayBuffer, лежащий в основе массива. -
[in] byte_offset: Смещение в байтах внутриArrayBuffer, с которого начинать проекциюTypedArray. -
[out] result: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) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Количество элементов вDataView. -
[in] arraybuffer:ArrayBuffer, лежащий в основеDataView. -
[in] byte_offset: Смещение в байтах внутриArrayBuffer, с которого начинать проекциюDataView. -
[out] result: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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result: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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Беззнаковое целое значение, которое должно быть представлено в JavaScript. -
[out] result: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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result: Объект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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Значение с двойной точностью, которое должно быть представлено в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScript-значение типаnumber.
Возвращает 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); copy -
[in] env: Среда, в которой вызывается API. -
[in] value: Целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScript-значение типаBigInt.
Возвращает 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); copy -
[in] env: Среда, в которой вызывается API. -
[in] value: Беззнаковое целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScript-значение типаBigInt.
Возвращает 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); copy -
[in] env: Среда, в которой вызывается API. -
[in] sign_bit: Определяет, будет ли полученноеBigIntположительным или отрицательным. -
[in] word_count: Длина массиваwords. -
[in] words: Массивuint64_t32-разрядных слов в формате little-endian. -
[out] result: Объектnapi_value, представляющий JavaScript-значение типаBigInt.
Возвращает 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); copy -
[in] env: Среда, в которой вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке ISO-8859-1. -
[in] length: Длина строки в байтах, илиNAPI_AUTO_LENGTH, если строка завершается нулем. -
[out] result: Объектnapi_value, представляющий JavaScript-строку.
Возвращает napi_ok, если API выполнилось успешно.
Этот API создает значение JavaScript-строки из C-строки в кодировке ISO-8859-1. Строка из исходного кода копируется.
Тип JavaScript-строки описан в Разделе 6.1.4 спецификации языка ECMAScript.
node_api_create_external_string_latin1
napi_status
node_api_create_external_string_latin1(napi_env env,
char* str,
size_t length,
napi_finalize finalize_callback,
void* finalize_hint,
napi_value* result,
bool* copied); copy -
[in] env: Среда, в которой вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке ISO-8859-1. -
[in] length: Длина строки в байтах, илиNAPI_AUTO_LENGTH, если строка завершается нулем. -
[in] finalize_callback: Функция, которая вызывается при сборе строки. Функция будет вызываться со следующими параметрами:-
[in] env: Среда, в которой работает плагин. Это значение может быть null, если строка собирается в процессе завершения работы рабочего процесса или основного экземпляра Node.js. -
[in] data: Это значениеstrкак указатель наvoid*. -
[in] finalize_hint: Это значениеfinalize_hint, которое было передано в API.napi_finalizeсодержит более подробную информацию. Этот параметр необязателен. Передача значения null означает, что плагин не должен быть уведомлен при сборе соответствующей JavaScript-строки.
-
-
[in] finalize_hint: Необязательный параметр для передачи в обратный вызов finalize во время сбора. -
[out] result: Объектnapi_value, представляющий JavaScript-строку. -
[out] copied: Была ли скопирована строка. Если да, то finalizer уже был вызван для уничтоженияstr.
Возвращает napi_ok, если API выполнилось успешно.
Этот API создает значение JavaScript-строки из C-строки в кодировке ISO-8859-1. Исходная строка может не копироваться и должна существовать на протяжении всего жизненного цикла JavaScript-значения.
Тип JavaScript-строки описан в Разделе 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) copy -
[in] env: Среда, в которой вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах, илиNAPI_AUTO_LENGTH, если строка завершается нулем. -
[out] result: Объектnapi_value, представляющий JavaScript-строку.
Возвращает napi_ok, если API выполнилось успешно.
Этот API создает значение JavaScript-строки из C-строки в кодировке UTF16-LE. Строка из исходного кода копируется.
Тип JavaScript-строки описан в Разделе 6.1.4 спецификации языка ECMAScript.
node_api_create_external_string_utf16
napi_status
node_api_create_external_string_utf16(napi_env env,
char16_t* str,
size_t length,
napi_finalize finalize_callback,
void* finalize_hint,
napi_value* result,
bool* copied); copy -
[in] env: Среда, в которой вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах, илиNAPI_AUTO_LENGTH, если строка завершается нулем. -
[in] finalize_callback: Функция, которая вызывается при сборе строки. Функция будет вызываться со следующими параметрами:-
[in] env: Среда, в которой работает плагин. Это значение может быть null, если строка собирается в процессе завершения работы рабочего процесса или основного экземпляра Node.js. -
[in] data: Это значениеstrкак указатель наvoid*. -
[in] finalize_hint: Это значениеfinalize_hint, которое было передано в API.napi_finalizeсодержит более подробную информацию. Этот параметр необязателен. Передача значения null означает, что плагин не должен быть уведомлен при сборе соответствующей JavaScript-строки.
-
-
[in] finalize_hint: Необязательный параметр для передачи в обратный вызов finalize во время сбора. -
[out] result: Объектnapi_value, представляющий JavaScript-строку. -
[out] copied: Была ли скопирована строка. Если да, то finalizer уже был вызван для уничтоженияstr.
Возвращает napi_ok, если API выполнилось успешно.
Этот API создает значение JavaScript-строки из C-строки в кодировке UTF16-LE. Исходная строка может не копироваться и должна существовать на протяжении всего жизненного цикла JavaScript-значения.
Тип JavaScript-строки описан в Разделе 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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке UTF8. -
[in] length: Длина строки в байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объект, представляющий JavaScript-строкуstring.
Возвращает napi_ok, если API выполнилась успешно.
Этот API создаёт значение JavaScript-строки string из UTF8-строки C. Исходная строка копируется.
Тип JavaScript-строки string описан в разделе 6.1.4 спецификации ECMAScript Language Specification.
node_api_create_property_key_utf16
napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env,
const char16_t* str,
size_t length,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объект, представляющий оптимизированную JavaScript-строкуstring, предназначенную для использования в качестве ключа свойства объектов.
Возвращает napi_ok, если API выполнилась успешно.
Этот API создаёт оптимизированное значение JavaScript-строки string из UTF16-LE-строки C для использования в качестве ключа свойства объектов. Исходная строка копируется.
Многие JavaScript-движки, включая V8, используют интернализованные строки в качестве ключей для установки и получения значений свойств. Обычно они используют хеш-таблицу для создания и поиска таких строк. Хотя это добавляет некоторую стоимость при создании каждого ключа, это улучшает производительность после этого, позволяя сравнивать указатели строк, а не целые строки.
Если новая JavaScript-строка предназначена для использования в качестве ключа свойства, то для некоторых JavaScript-движков более эффективным будет использование функции node_api_create_property_key_utf16. В противном случае используйте функции napi_create_string_utf16 или node_api_create_external_string_utf16, так как при использовании этого метода может быть дополнительная нагрузка на создание/хранение строк.
Тип JavaScript-строки string описан в разделе 6.1.4 спецификации ECMAScript Language Specification.
Функции для преобразования из Node-API в типы C
napi_get_array_length
napi_status napi_get_array_length(napi_env env,
napi_value value,
uint32_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Объект, представляющий JavaScript-массивArray, длина которого запрашивается. -
[out] result: Объект, представляющий длину массива.
Возвращает napi_ok, если API выполнилась успешно.
Этот API возвращает длину массива.
Свойство Array длины описано в разделе 22.1.4.1 спецификации ECMAScript Language Specification.
napi_get_arraybuffer_info
napi_status napi_get_arraybuffer_info(napi_env env,
napi_value arraybuffer,
void** data,
size_t* byte_length) copy -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: Объект, представляющий запрашиваемыйArrayBuffer. -
[out] data: Необходимый буфер данных (underlying data buffer) дляArrayBuffer. Если byte_length равен0, то это может бытьNULLили любое другое значение указателя. -
[out] byte_length: Длина буфера данных в байтах.
Возвращает napi_ok, если API выполнилась успешно.
Этот API используется для получения базового буфера данных (underlying data buffer) объекта ArrayBuffer и его длины.
ПРЕДУПРЕЖДЕНИЕ: Используйте с осторожностью. Жизненный цикл базового буфера данных управляется ArrayBuffer даже после его возврата. Один из безопасных способов использования этого API — в сочетании с napi_create_reference, который можно использовать для гарантии управления жизненным циклом ArrayBuffer. Также безопасно использовать возвращённый буфер данных в том же обработчике событий, пока не будут вызваны другие API, которые могут вызвать GC.
napi_get_buffer_info
napi_status napi_get_buffer_info(napi_env env,
napi_value value,
void** data,
size_t* length) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Объект, представляющий запрашиваемыйnode::BufferилиUint8Array. -
[out] data: Необходимый буфер данных (underlying data buffer) дляnode::BufferилиUint8Array. Если length равен0, то это может бытьNULLили любое другое значение указателя. -
[out] length: Длина буфера данных в байтах.
Возвращает napi_ok, если API выполнилась успешно.
Этот метод возвращает идентичные data и byte_length, как napi_get_typedarray_info. А napi_get_typedarray_info также принимает node::Buffer (Uint8Array) в качестве значения.
Этот API используется для получения базового буфера данных (underlying data buffer) объекта node::Buffer и его длины.
Предупреждение: Используйте с осторожностью, так как жизненный цикл базового буфера данных не гарантируется, если он управляется виртуальной машиной.
napi_get_prototype
napi_status napi_get_prototype(napi_env env,
napi_value object,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] object: Объект, представляющий JavaScript-объектObject, прототип которого необходимо вернуть. Это возвращает эквивалентObject.getPrototypeOf(что не то же самое, что свойствоprototypeфункции). -
[out] result: Объект, представляющий прототип данного объекта.
Возвращает 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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] typedarray: Объект, представляющий запрашиваемыйTypedArray. -
[out] type: Скалярный тип данных элементов вTypedArray. -
[out] length: Количество элементов вTypedArray. -
[out] data: Буфер данных, лежащий в основеTypedArray, скорректированный значениемbyte_offset, так что он указывает на первый элемент вTypedArray. Если длина массива равна0, то это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer: Базовый буфер данных (underlying buffer) дляTypedArray. -
[out] byte_offset: Смещение в байтах в базовом массиве (underlying native array), с которого начинается проекция первого элемента массивов. Значение для параметра data уже скорректировано, так что data указывает на первый элемент в массиве. Таким образом, первый байт базового массива будет вdata - byte_offset.
Возвращает napi_ok, если API выполнилась успешно.
Этот API возвращает различные свойства типизированного массива.
Любой из параметров вывода может быть NULL, если это свойство не требуется.
Предупреждение: Используйте с осторожностью, так как жизненный цикл базового буфера данных управляется виртуальной машиной.
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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] dataview: Объект, представляющий запрашиваемыйDataView. -
[out] byte_length: Количество байтов вDataView. -
[out] data: Буфер данных, лежащий в основеDataView. Если byte_length равен0, то это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer: Базовый буфер данных (underlying buffer) для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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Объект, представляющий JavaScript-объектDate. -
[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) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Объект, представляющий JavaScript-объектBoolean. -
[out] result: Примитивное C-булево значение, эквивалентное данному JavaScript-объектуBoolean.
Возвращает napi_ok, если API выполнилось успешно. Если в качестве аргумента передано значение, которое не является булевым napi_value, то возвращается napi_boolean_expected.
Этот API возвращает примитивное булевое значение C, эквивалентное переданному JavaScript Boolean.
napi_get_value_double
napi_status napi_get_value_double(napi_env env,
napi_value value,
double* result) copy -
[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); copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, представляющее JavaScriptBigInt. -
[out] result: Примитивное значение C типаint64_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); copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, представляющее JavaScriptBigInt. -
[out] result: Примитивное значение C типаuint64_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); copy -
[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) copy -
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, представляющее JavaScriptnumber. -
[out] result: Примитивное значение C типаint32, эквивалентное переданному 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) copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, представляющее JavaScriptnumber. -
[out] result: Примитивное значение C типаint64, эквивалентное переданному 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) copy -
[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) copy -
[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) copy -
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, представляющее JavaScriptnumber. -
[out] result: Примитивное значение C, эквивалентное переданному JavaScriptnapi_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) copy
-
[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) copy
-
[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) copy
-
[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) copy
-
[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) copy -
[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) copy -
[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) copy -
[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) copy -
[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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение, тип которого нужно определить. -
[out] result: Тип JavaScript-значения.
Возвращает napi_ok, если API выполнено успешно.
-
napi_invalid_arg, если типvalueне является известным типом ECMAScript, иvalueне является внешним значением.
Этот API отображает поведение, аналогичное вызову оператора typeof над объектом, как определено в разделе 12.5.5 Спецификации языка ECMAScript. Однако есть некоторые отличия:
- Поддерживает обнаружение внешнего значения.
- Обнаруживает
nullкак отдельный тип, в то время как ECMAScripttypeofобнаруживал быobject.
Если у value некорректный тип, возвращается ошибка.
napi_instanceof
napi_status napi_instanceof(napi_env env,
napi_value object,
napi_value constructor,
bool* result) copy -
[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) copy
-
[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) copy
-
[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) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли данноеnapi_valueобъектnode::BufferилиUint8Array.
Возвращает napi_ok, если API выполнено успешно.
Этот API проверяет, является ли переданный Object буфером или объектом Uint8Array. Для проверки, является ли значение Uint8Array, следует использовать napi_is_typedarray.
napi_is_date
napi_status napi_is_date(napi_env env, napi_value value, bool* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Представляет ли данный объект JavaScript-объектDate.
Возвращает napi_ok, если API выполнено успешно.
Этот API проверяет, является ли переданный Object датой.
napi_is_error
napi_status napi_is_error(napi_env env, napi_value value, bool* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Является ли данный объект объектомError.
Возвращает napi_ok, если API выполнено успешно.
Этот API проверяет, является ли переданный Object ошибкой Error.
napi_is_typedarray
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Является ли данный объект типом массиваTypedArray.
Возвращает napi_ok, если API выполнено успешно.
Этот API проверяет, является ли переданный Object типом массива.
napi_is_dataview
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: JavaScript-значение для проверки. -
[out] result: Является ли данный объект объектом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) copy -
[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) copy -
[in] env: Среда, в которой вызывается API. -
[in] arraybuffer: JavaScriptArrayBuffer, который нужно отсоединить.
Возвращает 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) copy -
[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, описанные в этом разделе, обеспечивают простой интерфейс для получения и установки свойств произвольных объектов JavaScript, представленных napi_value.
Например, рассмотрим следующий фрагмент JavaScript-кода:
const obj = {};
obj.myProp = 123; copy Аналогичный результат можно получить с помощью значений 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; copy Индексированные свойства можно установить аналогичным образом. Рассмотрим следующий фрагмент JavaScript:
const arr = []; arr[123] = 'hello'; copy
Аналогичный результат можно получить с помощью значений 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; copy
Свойства можно получить, используя API, описанные в этом разделе. Рассмотрим следующий фрагмент JavaScript:
const arr = []; const value = arr[123]; copy
Следующий пример приблизительно эквивалентен 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; copy
Наконец, для повышения производительности можно определить несколько свойств на объекте. Рассмотрим следующий фрагмент JavaScript:
const obj = {};
Object.defineProperties(obj, {
'foo': { value: 123, writable: true, configurable: true, enumerable: true },
'bar': { value: 456, writable: true, configurable: true, enumerable: true },
}); copy Следующий пример приблизительно эквивалентен 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; copy Структуры
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; copy 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; copy -
utf8name: Необязательная строка, описывающая ключ свойства, закодированная в UTF8. Для свойства должен быть задан один изutf8nameилиname. -
name: Необязательноеnapi_value, указывающее на JavaScript-строку или символ, используемые в качестве ключа свойства. Для свойства должен быть задан один изutf8nameилиname. -
value: Значение, возвращаемое при чтении свойства, если свойство является свойством данных. Если передано, установитеgetter,setter,methodиdataвNULL(поскольку эти члены не будут использоваться). -
getter: Функция, вызываемая при чтении свойства. Если передана, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Функция вызывается неявно во время выполнения при доступе к свойству из JavaScript-кода (или при чтении свойства с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
setter: Функция, вызываемая при записи в свойство. Если передана, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Функция вызывается неявно во время выполнения при записи в свойство из JavaScript-кода (или при записи в свойство с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
method: Установите это значение, чтобы свойствоvalueобъекта-описателя стало 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); copy -
[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); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойства. -
[in] key_mode: Нужно ли получать свойства прототипа? -
[in] key_filter: Какие свойства получать (перечисляемые/доступные для чтения/изменения). -
[in] key_conversion: Преобразовывать ли числовые ключи свойств в строки. -
[out] result:napi_value, представляющий массив JavaScript-значений, представляющих имена свойств объекта.napi_get_array_lengthиnapi_get_elementмогут быть использованы для итерации поresult.
Возвращает napi_ok, если API выполнено успешно.
Это API возвращает массив, содержащий имена доступных свойств этого объекта.
napi_set_property
napi_status napi_set_property(napi_env env,
napi_value object,
napi_value key,
napi_value value); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, который нужно проверить. -
[in] key: Название собственного свойства, существование которого необходимо проверить. -
[out] result: Существует ли собственное свойство в объекте или нет.
Возвращает napi_ok, если API выполнилась успешно.
Этот API проверяет, есть ли у переданного Object указанное собственное свойство. key должен быть string или symbol, в противном случае будет выброшено исключение. Node-API не будет выполнять преобразование между типами данных.
napi_set_named_property
napi_status napi_set_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value value); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, которому нужно установить свойство. -
[in] utf8Name: Имя свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok, если API выполнилась успешно.
Этот метод эквивалентен вызову napi_set_property со строкой, созданной из переданной строки как utf8Name.
napi_get_named_property
napi_status napi_get_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект, из которого необходимо извлечь свойство. -
[in] utf8Name: Имя свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok, если API выполнилась успешно.
Этот метод эквивалентен вызову napi_get_property со строкой, созданной из переданной строки как utf8Name.
napi_has_named_property
napi_status napi_has_named_property(napi_env env,
napi_value object,
const char* utf8Name,
bool* result); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] object: Объект для проверки. -
[in] utf8Name: Имя свойства, существование которого необходимо проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok, если API выполнилась успешно.
Этот метод эквивалентен вызову napi_has_property со строкой, созданной из переданной строки как utf8Name.
napi_set_element
napi_status napi_set_element(napi_env env,
napi_value object,
uint32_t index,
napi_value value); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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_call_function
NAPI_EXTERN napi_status napi_call_function(napi_env env,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result); copy -
[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;
}
global.AddTwo = AddTwo; copy Затем, вышеупомянутую функцию можно вызвать из родного плагина с помощью следующего кода:
// 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; copy
napi_create_function
napi_status napi_create_function(napi_env env,
const char* utf8name,
size_t length,
napi_callback cb,
void* data,
napi_value* result); copy -
[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) copy Учитывая вышеприведенный код, плагин можно использовать из JavaScript следующим образом:
const myaddon = require('./addon');
myaddon.sayHello(); copy Строка, переданная в require(), — это имя целевого объекта в binding.gyp, ответственного за создание файла .node.
Любые данные, не являющиеся NULL, которые передаются в этот API через параметр data, могут быть связаны с получившейся JavaScript-функцией (которая возвращается в параметре result) и освобождены при сборе мусора функции, передав и JavaScript-функцию, и данные в napi_add_finalizer.
JavaScript-функции описаны в разделе 19.2 спецификации языка ECMAScript.
napi_get_cb_info
napi_status napi_get_cb_info(napi_env env,
napi_callback_info cbinfo,
size_t* argc,
napi_value* argv,
napi_value* thisArg,
void** data) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация об обратном вызове, переданная функции обратного вызова. -
[in-out] argc: Указывает длину массиваargvи получает фактическое количество аргументов.argcможно необязательно игнорировать, передавNULL. -
[out] argv: Массив C изnapi_value, в который будут скопированы аргументы. Если аргументов больше, чем указано, копируются только запрошенное количество аргументов. Если предоставлено меньше аргументов, чем заявлено, оставшаяся частьargvзаполняется значениямиnapi_value, представляющимиundefined.argvможно необязательно игнорировать, передавNULL. -
[out] thisArg: Получает JavaScript-аргументthisдля вызова.thisArgможно необязательно игнорировать, передавNULL. -
[out] data: Получает указатель на данные для обратного вызова.dataможно необязательно игнорировать, передавNULL.
Возвращает napi_ok, если API выполнилась успешно.
Этот метод используется внутри функции обратного вызова для получения деталей о вызове, таких как аргументы и указатель this из заданной информации об обратном вызове.
napi_get_new_target
napi_status napi_get_new_target(napi_env env,
napi_callback_info cbinfo,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация об обратном вызове, переданная функции обратного вызова. -
[out] result:new.targetвызова конструктора.
Возвращает napi_ok, если API выполнилась успешно.
Этот API возвращает new.target вызова конструктора. Если текущий обратный вызов не является вызовом конструктора, результат — NULL.
napi_new_instance
napi_status napi_new_instance(napi_env env,
napi_value cons,
size_t argc,
napi_value* argv,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cons:napi_value, представляющий функцию JavaScript, которая должна быть вызвана в качестве конструктора. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив JavaScript-значений, какnapi_value, представляющих аргументы конструктора. Еслиargcравно нулю, этот параметр можно опустить, передавNULL. -
[out] result:napi_value, представляющий возвращаемый JavaScript-объект, который в данном случае является созданным объектом.
Этот метод используется для создания нового значения JavaScript с помощью заданного napi_value, представляющего конструктор объекта. Например, рассмотрим следующий фрагмент:
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg); copy Следующее можно приблизить в 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); copy
Возвращает napi_ok, если API выполнилась успешно.
Обёртка объекта
Node-API предоставляет способ «обёртки» классов и экземпляров C++ таким образом, чтобы конструктор и методы класса можно было вызывать из JavaScript.
- API
napi_define_classопределяет JavaScript-класс с конструктором, статическими свойствами и методами, а также свойствами и методами экземпляров, соответствующими C++-классу. - Когда JavaScript-код вызывает конструктор, обратный вызов конструктора использует
napi_wrapдля обёртки нового C++-экземпляра в JavaScript-объект, затем возвращает обёртку объекта. - Когда JavaScript-код вызывает метод или обработчик доступа к свойству в классе, вызывается соответствующая
napi_callbackC++-функция. Для обратного вызова экземпляра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...
} copyСсылка должна быть освобождена, как только она больше не требуется.
В некоторых случаях 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
} copyВ приведённом выше примере 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;
}
} copy
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); copy-
[in] env: Окружение, в котором вызывается API. -
[in] utf8name: Имя функции-конструктора JavaScript. Для ясности рекомендуется использовать имя C++-класса при обёртке C++-класса. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[in] constructor: Функция обратного вызова, которая обрабатывает создание экземпляров класса. При обёртке C++-класса этот метод должен быть статическим членом с сигнатуройnapi_callback. Конструктор C++-класса использовать нельзя.napi_callbackпредоставляет более подробную информацию. -
[in] data: Дополнительные данные, которые передаются в обратный вызов конструктора как свойствоdataинформации об обратном вызове. -
[in] property_count: Количество элементов в аргументе массиваproperties. -
[in] properties: Массив описателей свойств, описывающих статические и экземпляры данных свойства, аксессоры и методы класса. См.napi_property_descriptor. -
[out] result:napi_value, представляющий функцию-конструктор класса.
Возвращает 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); copy-
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, который будет обёрткой родного объекта. -
[in] native_object: Родной экземпляр, который будет обёрнут в JavaScript-объект. -
[in] finalize_cb: Необязательный родной обратный вызов, который можно использовать для освобождения родного экземпляра, когда JavaScript-объект был собран мусором.napi_finalizeпредоставляет более подробную информацию. -
[in] finalize_hint: Необязательный контекстный подсказка, который передаётся в обратный вызов завершения. -
[out] result: Необязательная ссылка на обёрнутый объект.
Возвращает napi_ok, если API выполнился успешно.
Обёртка родного экземпляра в JavaScript-объект. Родной экземпляр можно получить позже с помощью napi_unwrap().
Когда JavaScript-код вызывает конструктор класса, который был определён с помощью napi_define_class(), вызывается napi_callback для конструктора. После создания экземпляра родного класса обратный вызов должен вызвать napi_wrap(), чтобы обёрнуть только что созданный экземпляр в уже созданный JavaScript-объект, который является аргументом this обратного вызова конструктора. (Этот this объект был создан из prototype функции-конструктора, поэтому у него уже есть определения всех свойств и методов экземпляра.)
Обычно при обёртке экземпляра класса должен быть предоставлен обратный вызов завершения, который просто удаляет родной экземпляр, который получен как аргумент data обратного вызова завершения.
Необязательная возвращаемая ссылка изначально является слабой ссылкой, означающей, что её счётчик ссылок равен 0. Обычно этот счётчик ссылок временно увеличивается во время асинхронных операций, которые требуют, чтобы экземпляр оставался действительным.
Внимание: необязательная возвращаемая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова завершения. Если она удаляется до этого, то обратный вызов завершения может никогда не быть вызван. Следовательно, при получении ссылки также требуется обратный вызов завершения, чтобы обеспечить правильную утилизацию ссылки.
Обратные вызовы завершения могут быть отложены, создавая окно, в котором объект был собран мусором (и слабая ссылка недействительна), но обратный вызов завершения ещё не был вызван. При использовании napi_get_reference_value() на слабых ссылках, возвращаемых napi_wrap(), вы всё равно должны обрабатывать пустой результат.
Вызов napi_wrap() второй раз для объекта вернёт ошибку. Чтобы связать другой родной экземпляр с объектом, сначала используйте napi_remove_wrap().
napi_unwrap
napi_status napi_unwrap(napi_env env,
napi_value js_object,
void** result); copy- Окружение, в котором вызывается API.
- Объект, связанный с родным экземпляром.
- Указатель на обернутый родной экземпляр.
Возвращает 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); copy - Окружение, в котором вызывается API.
- Объект, связанный с родным экземпляром.
- Указатель на обернутый родной экземпляр.
Возвращает napi_ok, если API выполнилось успешно.
Извлекает родной экземпляр, который ранее был обернут в JavaScript-объект js_object с помощью napi_wrap() и удаляет обёртку. Если был связан обратный вызов finalization, он больше не будет вызываться при сборе мусора JavaScript-объекта.
napi_type_tag_object
napi_status napi_type_tag_object(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag); copy - Окружение, в котором вызывается API.
- JavaScript-объект или external, который необходимо пометить.
- Тег, с помощью которого следует пометить объект.
Возвращает napi_ok, если API выполнилось успешно.
Связывает значение указателя type_tag с JavaScript-объектом или external. 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); copy - Окружение, в котором вызывается API.
- JavaScript-объект или external, тег типа которого нужно проверить.
- Тег для сравнения с любым найденным тегом объекта.
- Соответствие тега типа, предоставленного, тегу типа объекта.
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* finalize_data,
node_api_nogc_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); copy - Окружение, в котором вызывается API.
- JavaScript-объект, к которому будет прикреплены данные.
- Дополнительные данные, которые будут переданы в
finalize_cb. - Родной обратный вызов, который будет использоваться для освобождения родных данных при сборе мусора JavaScript-объекта.
napi_finalizeсодержит более подробную информацию. - Дополнительный контекстный признак, который передается в обратный вызов finalization.
- Дополнительная ссылка на JavaScript-объект.
Возвращает napi_ok, если API выполнилось успешно.
Добавляет обратный вызов napi_finalize, который будет вызываться при сборе мусора JavaScript-объекта в js_object.
Эта API может вызываться несколько раз для одного JavaScript-объекта.
Внимание: Дополнительная возвращенная ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова finalization. Если она удалена до этого, обратный вызов finalization может никогда не быть вызван. Поэтому при получении ссылки также требуется обратный вызов finalization для правильного удаления ссылки.
node_api_post_finalizer
napi_status node_api_post_finalizer(node_api_nogc_env env,
napi_finalize finalize_cb,
void* finalize_data,
void* finalize_hint); copy - Окружение, в котором вызывается API.
- Родной обратный вызов, который будет использоваться для освобождения родных данных при сборе мусора JavaScript-объекта.
napi_finalizeсодержит более подробную информацию. - Дополнительные данные, которые будут переданы в
finalize_cb. - Дополнительный контекстный признак, который передается в обратный вызов finalization.
Возвращает napi_ok, если API выполнилось успешно.
Планирует обратный вызов napi_finalize для асинхронного вызова в цикле событий.
Обычно finalizers вызываются во время сбора мусора (GC). В этот момент вызов любой Node-API, который может привести к изменениям в состоянии GC, будет запрещен и приведет к ошибке Node.js.
node_api_post_finalizer помогает обойти это ограничение, позволяя дополнению отложить вызовы таких Node-API до момента вне GC finalization.
Простые асинхронные операции
Модули дополнений часто нуждаются в использовании асинхронных помощников из 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); copy При вызове этих методов переданный параметр data будет содержать данные, предоставленные дополнением void*, которые были переданы в вызов napi_create_async_work.
После создания асинхронный рабочий процесс можно поместить в очередь на выполнение с помощью функции napi_queue_async_work:
napi_status napi_queue_async_work(node_api_nogc_env env,
napi_async_work work); copy 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); copy -
[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); copy -
[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(node_api_nogc_env env,
napi_async_work work); copy -
[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(node_api_nogc_env env,
napi_async_work work); copy -
[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) copy[in] env: Среда, в которой вызывается API.[in] async_resource: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам и к которому можно получить доступ с помощьюasync_hooks.executionAsyncResource().[in] async_resource_name: Идентификатор типа ресурса, предоставляемого для диагностической информации, доступной через APIasync_hooks.[out] result: Инициализированный асинхронный контекст.
Возвращает napi_ok, если API успешно выполнен.
Объект async_resource необходимо сохранить до вызова napi_async_destroy для корректной работы связанных с ним API. Для сохранения совместимости с предыдущими версиями, napi_async_context не поддерживают сильную ссылку на объекты async_resource, чтобы избежать утечки памяти. Однако, если объект async_resource будет собран сборщиком мусора JavaScript до того, как napi_async_context был уничтожен napi_async_destroy, вызов связанных с napi_async_context API, таких как napi_open_callback_scope и napi_make_callback, может привести к проблемам, таким как потеря асинхронного контекста при использовании API AsyncLocalStorage.
Для сохранения совместимости с предыдущими версиями, передача NULL для async_resource не приводит к ошибке. Однако это не рекомендуется, так как это приведёт к нежелательному поведению с async_hooks init хуками и async_hooks.executionAsyncResource(), так как ресурс теперь необходим реализации базового async_hooks API для обеспечения связи между асинхронными обратными вызовами.
napi_async_destroy
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context); copy[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); copy[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, представляющих аргументы функции. Еслиargcравно нулю, этот параметр можно опустить, передавNULL.[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 или Promises, запланированные в очереди микрозадач 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) copy[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) copy[in] env: Среда, в которой вызывается API.[in] scope: Контекст для закрытия.
Этот API можно вызывать, даже если в JavaScript есть ожидающая обработка исключения.
Управление версиями
napi_get_node_version
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
const char* release;
} napi_node_version;
napi_status napi_get_node_version(node_api_nogc_env env,
const napi_node_version** version); copy[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(node_api_nogc_env env,
uint32_t* result); copy[in] env: Среда, в которой вызывается API.[out] result: Наивысшая поддерживаемая версия Node-API.
Возвращает napi_ok, если API успешно выполнен.
Этот API возвращает наивысшую поддерживаемую версию Node-API, поддерживаемую средой выполнения Node.js. Node-API планируется как добавочный, так что более новые релизы Node.js могут поддерживать дополнительные API-функции. Чтобы позволить дополнению использовать новую функцию при запуске с версиями Node.js, которые её поддерживают, при этом обеспечивая поведение по умолчанию при запуске с версиями Node.js, которые её не поддерживают:
- Вызовите
napi_get_version(), чтобы определить, доступен ли API. - Если доступен, динамически загрузите указатель на функцию, используя
uv_dlsym(). - Используйте динамически загруженный указатель для вызова функции.
- Если функция недоступна, предоставьте альтернативную реализацию, не использующую эту функцию.
Управление памятью
napi_adjust_external_memory
NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_nogc_env env,
int64_t change_in_bytes,
int64_t* result); copy[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(), создается объект "отложенного выполнения" (deferred), возвращаемый вместе с 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; copy
Функция 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; copy
napi_create_promise
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise); copy -
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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(node_api_nogc_env env,
struct uv_loop_s** loop); copy -
[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); copy -
[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_EXPERIMENTALопределён):Обработка исключений, брошенных в
call_js_cb, выполняется с помощью события'uncaughtException', а не игнорируется.
napi_get_threadsafe_function_context
NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
void** result); copy -
[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); copy -
[in] func: Асинхронная потокобезопасная функция JavaScript для вызова. -
[in] data: Данные, отправляемые в JavaScript через обратный вызовcall_js_cb, предоставленный при создании потокобезопасной функции JavaScript. -
[in] is_blocking: Флаг, значение которого может быть либоnapi_tsfn_blocking, чтобы указать, что вызов должен блокироваться, если очередь заполнена, либоnapi_tsfn_nonblocking, чтобы указать, что вызов должен возвращаться немедленно со статусомnapi_queue_full, когда очередь заполнена.
Этот API не следует вызывать из потока JavaScript с napi_tsfn_blocking, потому что, если очередь заполнена, это может привести к тупику в потоке JavaScript.
Этот 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); copy
-
[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); copy -
[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(node_api_nogc_env env, napi_threadsafe_function func); copy
-
[in] env: Окружение, в котором вызывается API. -
[in] func: Потокобезопасная функция, которую нужно проинициализировать.
Этот API используется для указания того, что цикл событий, работающий в главном потоке, не должен завершаться до тех пор, пока func не будет уничтожен. Подобно uv_ref, он также идемпотентен.
Также napi_unref_threadsafe_function не помечает потокобезопасные функции как уничтожаемые и не препятствует их уничтожению. napi_acquire_threadsafe_function и napi_release_threadsafe_function доступны для этой цели.
Этот API может быть вызван только из главного потока.
napi_unref_threadsafe_function
NAPI_EXTERN napi_status napi_unref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func); copy
-
[in] env: Окружение, в котором вызывается API. -
[in] func: Потокобезопасная функция, которую нужно разорвать.
Этот API используется для указания того, что цикл событий, работающий в главном потоке, может завершиться до уничтожения func. Подобно uv_unref, он также идемпотентен.
Этот API может быть вызван только из главного потока.
Служебные утилиты
node_api_get_module_file_name
NAPI_EXTERN napi_status node_api_get_module_file_name(node_api_nogc_env env, const char** result); copy
-
[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-v20.x/docs/api/n-api.html