N-API
N-API (произносится как N, затем API) — это API для создания нативных дополнений. Оно независимо от базовой среды выполнения JavaScript (например, V8) и поддерживается как часть самого Node.js. Это API будет обладать стабильностью бинарного интерфейса (ABI) в разных версиях Node.js. Оно предназначено для изоляции дополнений от изменений в базовом движке JavaScript и позволяет модулям, скомпилированным для одной основной версии, работать в последующих основных версиях Node.js без перекомпиляции. В руководстве ABI Stability приведено более подробное объяснение.
Дополнения создаются/упаковываются с тем же подходом/инструментами, что и в разделе C++ Addons. Единственное различие заключается в наборе API, используемых нативным кодом. Вместо использования API V8 или Native Abstractions for Node.js, используются функции, доступные в N-API.
API, экспортируемые N-API, обычно используются для создания и обработки значений JavaScript. Концепции и операции, как правило, соответствуют идеям, описанным в спецификации языка ECMA-262. API обладают следующими свойствами:
- Все вызовы N-API возвращают код состояния типа
napi_status. Этот код указывает, был ли успешен или неудачен вызов API. - Значение возврата API передаётся через параметр-результат.
- Все значения JavaScript абстрагированы за неким типом с непрозрачным именем
napi_value. - В случае кода состояния ошибки дополнительная информация может быть получена с помощью
napi_get_last_error_info. Более подробную информацию можно найти в разделе обработки ошибок Обработка ошибок.
N-API — это C API, гарантирующий стабильность ABI в разных версиях Node.js и уровнях компиляторов. C++ API может быть проще в использовании. Для поддержки использования C++, проект содержит модуль обертки на C++ под названием node-addon-api. Этот обертка предоставляет инлайновый C++ API. Бинарные файлы, созданные с node-addon-api, будут зависеть от символов для функций N-API, основанных на C, экспортированных Node.js. node-addon-api — более эффективный способ написания кода, вызывающего N-API. Например, рассмотрите следующий node-addon-api код. Первая секция показывает node-addon-api код, а вторая секция показывает то, что фактически используется в дополнении.
Object obj = Object::New(env); obj["foo"] = String::New(env, "bar");
napi_status status;
napi_value object, string;
status = napi_create_object(env, &object);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, &string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_set_named_property(env, object, "foo", string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
} В итоге дополнение использует только экспортированные API на C. В результате оно всё ещё получает преимущества стабильности ABI, предоставляемые API на C.
При использовании node-addon-api вместо API на C, начните с документации API docs для node-addon-api.
Ресурс N-API Resource предоставляет отличное руководство и советы для разработчиков, только начинающих работать с N-API и node-addon-api.
Последствия стабильности ABI
Хотя N-API гарантирует стабильность ABI, другие части Node.js этого не делают, и любые внешние библиотеки, используемые из дополнения, также могут не обеспечивать это. В частности, ни один из следующих API не гарантирует стабильность ABI в основных версиях:
-
API Node.js на C++, доступные через любой из
#include <node.h> #include <node_buffer.h> #include <node_version.h> #include <node_object_wrap.h>
-
API libuv, также включенные в Node.js и доступные через
#include <uv.h>
-
API V8, доступные через
#include <v8.h>
Таким образом, для сохранения ABI-совместимости дополнения с основными версиями Node.js оно должно использовать исключительно N-API, ограничивая себя использованием
#include <node_api.h>
и проверяя для всех внешних библиотек, которые оно использует, что внешняя библиотека обеспечивает гарантии стабильности ABI, аналогичные N-API.
Компиляция
В отличие от модулей, написанных на JavaScript, разработка и развертывание нативных дополнений Node.js с использованием N-API требует дополнительного набора инструментов. Помимо основных инструментов, необходимых для разработки для Node.js, разработчик нативного дополнения нуждается в инструменте, который может компилировать код C и C++ в бинарный файл. Кроме того, в зависимости от того, как развертывается нативное дополнение, пользователю этого дополнения также потребуется установленный инструмент для компиляции C/C++.
Для разработчиков Linux необходимые пакеты инструментария C/C++ легко доступны. В сообществе Node.js широко используется GCC для построения и тестирования на различных платформах. Для многих разработчиков инфраструктура компилятора LLVM также является хорошим выбором.
Для разработчиков macOS Xcode предоставляет все необходимые инструменты компилятора. Однако нет необходимости устанавливать весь IDE Xcode. Следующая команда устанавливает необходимый инструмент:
xcode-select --install
Для разработчиков Windows Visual Studio предоставляет все необходимые инструменты компилятора. Однако нет необходимости устанавливать весь IDE Visual Studio. Следующая команда устанавливает необходимый инструмент:
npm install --global windows-build-tools
Разделы ниже описывают дополнительные инструменты, доступные для разработки и развертывания нативных дополнений Node.js.
Инструменты для компиляции
Оба перечисленных здесь инструмента требуют, чтобы пользователи нативного дополнения имели установленный инструмент для компиляции C/C++ для успешной установки нативного дополнения.
node-gyp
node-gyp — это система сборки, основанная на инструменте Google GYP и поставляется в комплекте с npm. Для GYP, а следовательно и для node-gyp, требуется установка Python.
Исторически node-gyp был инструментом выбора для создания нативных дополнений. Он пользуется широкой поддержкой и документацией. Однако некоторые разработчики столкнулись с ограничениями в node-gyp.
CMake.js
CMake.js — это альтернативная система сборки, основанная на CMake.
CMake.js — хороший выбор для проектов, которые уже используют CMake, или для разработчиков, сталкивающихся с ограничениями node-gyp.
Загрузка предварительно скомпилированных библиотек
Три перечисленных инструмента позволяют разработчикам и поддерживающим нативные дополнения создавать и загружать бинарные файлы на публичные или частные серверы. Эти инструменты обычно интегрируются с системами CI/CD, такими как Travis CI и AppVeyor, для сборки и загрузки бинарных файлов для различных платформ и архитектур. Эти бинарные файлы затем доступны для скачивания пользователям, которым не требуется устанавливать инструмент C/C++.
node-pre-gyp
node-pre-gyp — это инструмент, основанный на node-gyp, который добавляет возможность загружать бинарные файлы на сервер по выбору разработчика. node-pre-gyp имеет особенно хорошую поддержку загрузки бинарных файлов в Amazon S3.
prebuild
prebuild — это инструмент, поддерживающий сборку с использованием node-gyp или CMake.js. В отличие от node-pre-gyp, который поддерживает различные серверы, prebuild загружает бинарные файлы только в выпуски GitHub. prebuild — хороший выбор для проектов GitHub, использующих CMake.js.
prebuildify
prebuildify — это инструмент, основанный на node-gyp. Преимущество prebuildify заключается в том, что скомпилированные бинарные файлы упаковываются с нативным модулем при его загрузке в npm. Бинарные файлы скачиваются из npm и немедленно доступны пользователю модуля при установке нативного модуля.
Использование
Для использования функций N-API включите файл node_api.h, который находится в каталоге src в дереве разработки Node.js:
#include <node_api.h>
Это включит по умолчанию NAPI_VERSION для данного релиза Node.js. Для обеспечения совместимости со специфическими версиями N-API, версию можно указать явно при включении заголовка:
#define NAPI_VERSION 3 #include <node_api.h>
Это ограничит поверхность N-API только функционалом, доступным в указанных (и более ранних) версиях.
Некоторая часть поверхности N-API экспериментальная и требует явного включения:
#define NAPI_EXPERIMENTAL #include <node_api.h>
В этом случае вся поверхность API, включая экспериментальные API, будет доступна коду модуля.
Матрица версий N-API
Версии N-API являются аддитивными и имеют отдельную версионирование от Node.js. Версия 4 является расширением версии 3, содержа в себе все API версии 3 с некоторыми дополнениями. Это означает, что нет необходимости перекомпилировать для новых версий Node.js, которые поддерживают более позднюю версию.
| 1 | 2 | 3 | 4 | 5 | 6 | |
|---|---|---|---|---|---|---|
| v6.x | v6.14.2* | |||||
| v8.x | v8.0.0* | v8.10.0* | v8.11.2 | v8.16.0 | ||
| v9.x | v9.0.0* | v9.3.0* | v9.11.0* | |||
| v10.x | v10.0.0 | v10.0.0 | v10.0.0 | v10.16.0 | v10.17.0 | v10.20.0 |
| v11.x | v11.0.0 | v11.0.0 | v11.0.0 | v11.8.0 | ||
| v12.x | v12.0.0 | v12.0.0 | v12.0.0 | v12.0.0 | v12.11.0 | v12.17.0 |
| v13.x | v13.0.0 | v13.0.0 | v13.0.0 | v13.0.0 | v13.0.0 | |
| v14.x | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 | v14.0.0 |
* Указывает, что версия N-API была выпущена как экспериментальная
Каждый документированный API для N-API будет иметь заголовок added in:, а стабильные API будут иметь дополнительный заголовок N-API version:. API напрямую доступны при использовании версии Node.js, которая поддерживает версию N-API, показанную в N-API version: или выше. При использовании версии Node.js, которая не поддерживает указанную N-API version:, или если нет N-API version:, то API будет доступно только если #define NAPI_EXPERIMENTAL предшествует включению node_api.h или js_native_api.h. Если API кажется недоступным в версии Node.js, которая позже, чем та, что показана в added in:, то это, скорее всего, причина кажущегося отсутствия.
API N-API, связанные строго с доступом к функциям ECMAScript из нативного кода, можно найти отдельно в js_native_api.h и js_native_api_types.h. API, определённые в этих заголовках, включены в node_api.h и node_api_types.h. Заголовки структурированы таким образом, чтобы позволить реализацию N-API вне Node.js. Для этих реализаций API, специфичные для Node.js, могут быть неприменимы.
Части плагина, специфичные для Node.js, могут быть отделены от кода, который раскрывает фактическую функциональность для JavaScript-среды, чтобы последний мог использоваться с несколькими реализациями N-API. В примере ниже, addon.c и addon.h относятся только к js_native_api.h. Это гарантирует, что addon.c может быть повторно использовано для компиляции как с реализацией N-API от Node.js, так и с любой реализацией N-API вне Node.js.
addon_node.c — это отдельный файл, содержащий специфичную для Node.js точку входа в плагин и инициализирующий плагин вызовом addon.c при загрузке плагина в среду Node.js.
// addon.h #ifndef _ADDON_H_ #define _ADDON_H_ #include <js_native_api.h> napi_value create_addon(napi_env env); #endif // _ADDON_H_
// addon.c
#include "addon.h"
#define NAPI_CALL(env, call) \
do { \
napi_status status = (call); \
if (status != napi_ok) { \
const napi_extended_error_info* error_info = NULL; \
napi_get_last_error_info((env), &error_info); \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
if (!is_pending) { \
const char* message = (error_info->error_message == NULL) \
? "empty error message" \
: error_info->error_message; \
napi_throw_error((env), NULL, message); \
return NULL; \
} \
} \
} while(0)
static napi_value
DoSomethingUseful(napi_env env, napi_callback_info info) {
// Do something useful.
return NULL;
}
napi_value create_addon(napi_env env) {
napi_value result;
NAPI_CALL(env, napi_create_object(env, &result));
napi_value exported_function;
NAPI_CALL(env, napi_create_function(env,
"doSomethingUseful",
NAPI_AUTO_LENGTH,
DoSomethingUseful,
NULL,
&exported_function));
NAPI_CALL(env, napi_set_named_property(env,
result,
"doSomethingUseful",
exported_function));
return result;
} // addon_node.c
#include <node_api.h>
#include "addon.h"
NAPI_MODULE_INIT() {
// This function body is expected to return a `napi_value`.
// The variables `napi_env env` and `napi_value exports` may be used within
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
return create_addon(env);
} API жизненного цикла среды
Раздел 8.7 Спецификации языка ECMAScript определяет понятие «Агент» как самодостаточную среду, в которой выполняется код JavaScript. Процесс может запускать и завершать несколько таких Агентов одновременно или последовательно.
Среда Node.js соответствует агенту ECMAScript. В главном процессе среда создается при запуске, а дополнительные среды могут быть созданы на отдельных потоках, чтобы служить потоками-работниками. Когда Node.js встроен в другое приложение, главный поток приложения также может многократно создавать и уничтожать среду Node.js в течение жизненного цикла процесса приложения, так что каждая созданная приложением среда Node.js, в свою очередь, в течение своего жизненного цикла может создавать и уничтожать дополнительные среды как потоки-работники.
С точки зрения родного плагина это означает, что предоставляемые им привязки могут вызываться многократно, из нескольких контекстов и даже одновременно из нескольких потоков.
Родным плагинам может потребоваться выделять глобальное состояние, которое они используют в течение всего своего жизненного цикла, так что состояние должно быть уникальным для каждого экземпляра плагина.
Для этого N-API предоставляет способ выделения данных таким образом, что его жизненный цикл привязан к жизненному циклу Агента.
napi_set_instance_data
napi_status napi_set_instance_data(napi_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint); -
[in] env: Среда, в которой вызывается вызов N-API. -
[in] data: Элемент данных, который нужно сделать доступным для привязок этого экземпляра. -
[in] finalize_cb: Функция, которую нужно вызвать при разборке среды. Функция получаетdata, чтобы она могла его освободить.napi_finalizeсодержит больше деталей. -
[in] finalize_hint: Необязательный подсказка, передаваемая в обратный вызов finalize во время сбора мусора.
Возвращает napi_ok в случае успеха API.
Этот API связывает data с текущим работающим Агентом. data позже можно получить с помощью napi_get_instance_data(). Любые существующие данные, связанные с текущим работающим агентом, которые были установлены посредством предыдущего вызова napi_set_instance_data(), будут перезаписаны. Если finalize_cb был предоставлен предыдущим вызовом, он не будет вызван.
napi_get_instance_data
napi_status napi_get_instance_data(napi_env env,
void** data); -
[in] env: Среда, в которой вызывается вызов N-API. -
[out] data: Элемент данных, который ранее был связан с текущим работающим Агентом вызовомnapi_set_instance_data().
Возвращает napi_ok в случае успеха API.
Этот API извлекает данные, которые были ранее связаны с текущим работающим Агентом через napi_set_instance_data(). Если данные не установлены, вызов будет успешным и data будет установлено в NULL.
Основные типы данных N-API
N-API предоставляет следующие фундаментальные типы данных как абстракции, которые используются различными API. Эти API следует рассматривать как непрозрачные, инспектируемые только с помощью других вызовов N-API.
napi_status
Целочисленное значение состояния, указывающее на успех или неудачу вызова N-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_status; Если требуется дополнительная информация при возвращении API неудачного состояния, ее можно получить, вызвав napi_get_last_error_info.
napi_extended_error_info
typedef struct {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
} napi_extended_error_info; -
error_message: Строка UTF8, содержащая описание ошибки, нейтральное по отношению к виртуальной машине. -
engine_reserved: Зарезервировано для деталей ошибки, специфичных для виртуальной машины. В настоящее время для какой-либо виртуальной машины не реализовано. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. В настоящее время для какой-либо виртуальной машины не реализовано. -
error_code: Код состояния N-API, который возник с последней ошибкой.
Дополнительная информация содержится в разделе Обработка ошибок.
napi_env
napi_env используется для представления контекста, который реализация N-API может использовать для сохранения состояния, специфичного для виртуальной машины. Эта структура передаётся в родные функции при их вызове и должна быть возвращена при выполнении вызовов N-API. В частности, тот же самый napi_env, что был передан при первоначальном вызове родной функции, должен быть передан при всех последующих вложенных вызовах N-API. Кэширование napi_env в целях общего повторного использования и передача napi_env между экземплярами одного и того же плагина, работающего в разных потоках Worker, запрещено. napi_env становится недействительным при разгрузке экземпляра родного плагина. Уведомление об этом событии передаётся через обратные вызовы, предоставленные napi_add_env_cleanup_hook и napi_set_instance_data.
napi_value
Это неявный указатель, используемый для представления значения JavaScript.
napi_threadsafe_function
Это неявный указатель, представляющий функцию JavaScript, которую можно вызывать асинхронно из нескольких потоков с помощью napi_call_threadsafe_function().
napi_threadsafe_function_release_mode
Значение, которое нужно передать napi_release_threadsafe_function() для указания, должно ли быть закрыта функция с безопасным доступом из разных потоков немедленно (napi_tsfn_abort) или просто освобождена (napi_tsfn_release) и, следовательно, доступна для последующего использования через napi_acquire_threadsafe_function() и napi_call_threadsafe_function().
typedef enum {
napi_tsfn_release,
napi_tsfn_abort
} napi_threadsafe_function_release_mode; napi_threadsafe_function_call_mode
Значение, которое нужно передать napi_call_threadsafe_function() для указания, должна ли операция блокироваться всякий раз, когда очередь, связанная с функцией с безопасным доступом из разных потоков, полна.
typedef enum {
napi_tsfn_nonblocking,
napi_tsfn_blocking
} napi_threadsafe_function_call_mode; Типы управления памятью N-API
napi_handle_scope
Это абстракция, используемая для управления и изменения срока жизни объектов, созданных в определённом контексте. В общем случае значения N-API создаются в контексте области видимости обработчика. Когда родной метод вызывается из JavaScript, существует стандартная область видимости обработчика. Если пользователь не создаёт явно новую область видимости обработчика, значения N-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; napi_async_cleanup_hook_handle
Неявное значение, возвращаемое napi_add_async_cleanup_hook. Оно должно быть передано napi_remove_async_cleanup_hook по завершении цепочки асинхронных событий очистки.
Типы обратных вызовов N-API
napi_callback_info
Неявной тип данных, передаваемый в функцию обратного вызова. Он может использоваться для получения дополнительной информации о контексте, в котором был вызван обратный вызов.
napi_callback
Тип указателя на функцию для пользовательских функций нативных функций, которые должны быть экспонированы для JavaScript через N-API. Функции обратного вызова должны соответствовать следующей сигнатуре:
typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
За исключением случаев, описанных в Управлении жизненным циклом объектов, создание дескриптора и/или области обратного вызова внутри napi_callback не требуется.
napi_finalize
Тип указателя на функцию для функций плагинов, которые позволяют пользователю получать уведомления, когда данные, принадлежащие внешнему источнику, готовы к очистке, поскольку объект, с которым они были связаны, был собран сборщиком мусора. Пользователь должен предоставить функцию, удовлетворяющую следующей сигнатуре, которая будет вызвана при сборе объекта. В настоящее время napi_finalize можно использовать для определения того, когда собираются объекты, имеющие внешние данные.
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint); За исключением случаев, описанных в Управлении жизненным циклом объектов, создание дескриптора и/или области обратного вызова внутри тела функции не требуется.
napi_async_execute_callback
Указатель на функцию, используемый с функциями, которые поддерживают асинхронные операции. Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef void (*napi_async_execute_callback)(napi_env env, void* data);
Реализации этой функции должны избегать выполнения вызовов N-API, которые выполняют JavaScript или взаимодействуют с объектами JavaScript. Вызовы N-API должны быть в napi_async_complete_callback вместо этого. Не используйте параметр napi_env, так как это, вероятно, приведет к выполнению JavaScript.
napi_async_complete_callback
Указатель на функцию, используемый с функциями, которые поддерживают асинхронные операции. Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); За исключением случаев, описанных в Управлении жизненным циклом объектов, создание дескриптора и/или области обратного вызова внутри тела функции не требуется.
napi_threadsafe_function_call_js
Указатель на функцию, используемый с асинхронными безопасными для потоков вызовами функций. Обратный вызов будет вызван в основном потоке. Его назначение заключается в использовании элемента данных, поступающего через очередь из одного из вторичных потоков, для построения параметров, необходимых для вызова JavaScript, обычно через napi_call_function, и затем выполнить вызов в JavaScript.
Данные, поступающие из вторичного потока через очередь, передаются в параметре data, а функция JavaScript для вызова — в параметре js_callback.
N-API настраивает среду перед вызовом этого обратного вызова, поэтому достаточно вызвать функцию JavaScript через napi_call_function, а не через napi_make_callback.
Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef void (*napi_threadsafe_function_call_js)(napi_env env,
napi_value js_callback,
void* context,
void* data); -
[in] env: Среда для использования в API-вызовах илиNULL, если функция безопасная для потоков разрывается иdataможет потребоваться освободить. -
[in] js_callback: Функция JavaScript для вызова илиNULL, если функция безопасная для потоков разрывается иdataможет потребоваться освободить. Также может бытьNULL, если функция безопасная для потоков была создана безjs_callback. -
[in] context: Необязательные данные, с которыми была создана функция безопасная для потоков. -
[in] data: Данные, созданные вторичным потоком. Ответственность обратного вызова заключается в преобразовании этих данных в значения JavaScript (с помощью функций N-API), которые могут быть переданы в качестве параметров при вызовеjs_callback. Этот указатель полностью управляется потоками и этим обратным вызовом. Следовательно, этот обратный вызов должен освободить данные.
За исключением случаев, описанных в Управлении жизненным циклом объектов, создание дескриптора и/или области обратного вызова внутри тела функции не требуется.
napi_async_cleanup_hook
Указатель на функцию, используемый с napi_add_async_cleanup_hook. Она будет вызвана при разрыве среды.
Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
void* data); -
[in] handle: Дескриптор, который необходимо передать вnapi_remove_async_cleanup_hookпосле завершения асинхронной очистки. -
[in] data: Данные, переданные вnapi_add_async_cleanup_hook.
Тело функции должно инициировать асинхронные действия очистки, по завершении которых handle необходимо передать в вызов napi_remove_async_cleanup_hook.
Обработка ошибок
N-API использует как возвращаемые значения, так и исключения JavaScript для обработки ошибок. В следующих разделах объясняется подход для каждого случая.
Возвращаемые значения
Все функции N-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.
typedef struct napi_extended_error_info {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
}; -
error_message: Текстовое представление произошедшей ошибки. -
engine_reserved: Непрозрачная ручка, предназначенная только для использования движком. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. -
error_code: Код состояния n-api для последней ошибки.
napi_get_last_error_info возвращает информацию о последнем вызове функции N-API.
Не полагайтесь на содержимое или формат любой расширенной информации, так как она не подчиняется SemVer и может изменяться в любое время. Она предназначена только для целей ведения журнала.
napi_get_last_error_info
napi_status
napi_get_last_error_info(napi_env env,
const napi_extended_error_info** result); -
[in] env: Среда, в которой вызывается API. -
[out] result: Структураnapi_extended_error_info, содержащая дополнительную информацию об ошибке.
Возвращает napi_ok если API выполнено успешно.
Этот API извлекает структуру napi_extended_error_info с информацией о последней произошедшей ошибке.
Содержимое возвращаемой структуры napi_extended_error_info действительно до тех пор, пока функция n-api не будет вызвана на той же env.
Не полагайтесь на содержимое или формат любой расширенной информации, так как она не подчиняется SemVer и может изменяться в любое время. Она предназначена только для целей ведения журнала.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
Исключения
Любой вызов функции N-API может привести к возникновению ожидающего исключения JavaScript. Это относится ко всем функциям API, даже к тем, которые могут не вызвать выполнение JavaScript.
Если значение napi_status , возвращаемое функцией, равно napi_ok, то исключение не ожидается и дополнительные действия не требуются. Если возвращаемое значение napi_status отличается от napi_ok или napi_pending_exception, для восстановления и продолжения вместо простого немедленного возврата необходимо вызвать napi_is_exception_pending, чтобы определить, ожидается ли исключение.
Во многих случаях, когда функция N-API вызывается, и исключение уже ожидается, функция вернётся немедленно со значением napi_status napi_pending_exception. Однако это не относится ко всем функциям. N-API позволяет вызывать подмножество функций для обеспечения минимальной очистки перед возвратом в JavaScript. В этом случае napi_status будет отражать статус функции. Она не будет отражать предыдущие ожидающие исключения. Для избежания путаницы, проверяйте статус ошибки после каждого вызова функции.
Когда ожидается исключение, можно использовать один из двух подходов.
Первый подход заключается в выполнении необходимой очистки, а затем возврате, чтобы управление вернулось в JavaScript. В рамках перехода обратно в JavaScript исключение будет выброшено в той части кода JavaScript, где была вызвана нативная функция. Поведение большинства вызовов N-API не определено, когда ожидается исключение, и многие просто вернут napi_pending_exception, поэтому делайте как можно меньше и возвращайтесь в JavaScript, где исключение может быть обработано.
Второй подход заключается в попытке обработать исключение. В некоторых случаях нативный код может перехватить исключение, принять соответствующие меры и продолжить работу. Это рекомендуется только в определённых случаях, когда известно, что исключение можно безопасно обработать. В этих случаях можно использовать napi_get_and_clear_last_exception для получения и очистки исключения. При успехе результат будет содержать дескриптор последнего выброшенного JavaScript Object исключения. Если после получения исключения выяснится, что его нельзя обработать, его можно повторно выбросить с помощью napi_throw, где error — объект JavaScript Error для выброса.
Также доступны следующие вспомогательные функции, если нативному коду необходимо выбросить исключение или определить, является ли napi_value экземпляром объекта JavaScript Error: napi_throw_error, napi_throw_type_error, napi_throw_range_error и napi_is_error.
Следующие служебные функции также доступны в случае необходимости создания объекта Error с помощью кода нативных языков: napi_create_error, napi_create_type_error и napi_create_range_error, где result — napi_value , который ссылается на вновь созданный JavaScript-объект Error.
В проекте Node.js добавляются коды ошибок ко всем ошибкам, генерируемым внутри. Цель состоит в том, чтобы приложения использовали эти коды ошибок для проверки всех ошибок. Соответствующие сообщения об ошибках останутся, но будут использоваться только для ведения журнала и отображения, предполагается, что сообщение может быть изменено без применения SemVer. Для поддержки этой модели с N-API, как в внутренней функциональности, так и для функциональности, специфичной для модуля (поскольку это хорошая практика), функции throw_ и create_ принимают необязательный параметр code, который представляет собой строку для добавления кода в объект ошибки. Если необязательный параметр NULL, то код к ошибке не будет добавлен. Если код предоставлен, имя, связанное с ошибкой, также обновляется следующим образом:
originalName [code]
где originalName — оригинальное имя, связанное с ошибкой, а code — предоставленный код. Например, если код — 'ERR_ERROR_1', и создается TypeError, имя будет:
TypeError [ERR_ERROR_1]
napi_throw
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error);
-
[in] env: Окружение, в котором вызывается API. -
[in] error: Значение JavaScript, которое должно быть выброшено.
Возвращает napi_ok, если API выполнена успешно.
Этот API выбрасывает предоставленное значение JavaScript.
napi_throw_error
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok, если API выполнена успешно.
Этот API выбрасывает JavaScript-объект Error с предоставленным текстом.
napi_throw_type_error
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok, если API выполнена успешно.
Этот API выбрасывает JavaScript-объект TypeError с предоставленным текстом.
napi_throw_range_error
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
const char* code,
const char* msg); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok, если API выполнена успешно.
Этот API выбрасывает JavaScript-объект RangeError с предоставленным текстом.
napi_is_error
NAPI_EXTERN napi_status napi_is_error(napi_env env,
napi_value value,
bool* result); -
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемоеnapi_value. -
[out] result: Булево значение, устанавливаемое в true, еслиnapi_valueпредставляет собой ошибку, и в false в противном случае.
Возвращает napi_ok, если API выполнена успешно.
Этот API запрашивает napi_value для проверки, представляет ли он собой объект ошибки.
napi_create_error
NAPI_EXTERN napi_status napi_create_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой кода ошибки, которая будет связана с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScript-объектString, который будет использоваться в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok, если API выполнена успешно.
Этот API возвращает JavaScript-объект Error с предоставленным текстом.
napi_create_type_error
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой кода ошибки, которая будет связана с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScript-объектString, который будет использоваться в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok, если API выполнена успешно.
Этот API возвращает JavaScript-объект TypeError с предоставленным текстом.
napi_create_range_error
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, которая должна быть связана с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptString, который будет использоваться в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает JavaScript RangeError со предоставленным текстом.
napi_get_and_clear_last_exception
napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[out] result: Исключение, если оно ожидается,NULLв противном случае.
Возвращает napi_ok в случае успешного выполнения API.
Этот API может быть вызван даже при наличии ожидающего JavaScript-исключения.
napi_is_exception_pending
napi_status napi_is_exception_pending(napi_env env, bool* result);
-
[in] env: Окружение, в котором вызывается API. -
[out] result: Булево значение, которое устанавливается в true, если ожидается исключение.
Возвращает napi_ok в случае успешного выполнения API.
Этот API может быть вызван даже при наличии ожидающего JavaScript-исключения.
napi_fatal_exception
napi_status napi_is_exception_pending(napi_env env, bool* result);
-
[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); -
[in] location: Необязательное место, в котором произошла ошибка. -
[in] location_len: Длина места в байтах, илиNAPI_AUTO_LENGTHесли оно имеет нуль-терминатор. -
[in] message: Сообщение, связанное с ошибкой. -
[in] message_len: Длина сообщения в байтах, илиNAPI_AUTO_LENGTHесли оно имеет нуль-терминатор.
Вызов функции не возвращает значение, процесс будет завершен.
Этот API может быть вызван даже при наличии ожидающего JavaScript-исключения.
Управление жизненным циклом объектов
При выполнении вызовов N-API, в качестве napi_values могут быть возвращены дескрипторы объектов в куче подчинённой виртуальной машины. Эти дескрипторы должны удерживать объекты «живыми» до тех пор, пока они больше не требуются кодом нативного языка, иначе объекты могут быть собраны в мусор, до того, как код нативного языка закончит с ними.
Когда возвращаются дескрипторы объектов, они связываются с «областью видимости». Срок действия области видимости по умолчанию привязан к сроку действия вызова метода нативного кода. В результате дескрипторы по умолчанию остаются валидными, и объекты, связанные с этими дескрипторами, будут удерживаться живыми на протяжении всего вызова метода нативного кода.
Однако во многих случаях необходимо, чтобы дескрипторы оставались валидными либо на более короткий, либо на более длительный срок, чем срок действия метода нативного кода. В следующих разделах описаны функции N-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
} Это приведет к созданию большого количества дескрипторов, что потребует значительных ресурсов. Кроме того, даже если код нативного языка может использовать только последний дескриптор, все связанные объекты также будут храниться в памяти, так как они используют одну и ту же область видимости.
Для решения этой задачи N-API предоставляет возможность создания новой «области видимости», к которой будут привязаны вновь созданные дескрипторы. После того, как эти дескрипторы больше не требуются, область видимости может быть «закрыта», и все дескрипторы, связанные с областью видимости, будут считаться недействительными. Методы открытия/закрытия областей видимости — napi_open_handle_scope и napi_close_handle_scope.
N-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;
}
} При вложенности областей видимости существуют случаи, когда дескриптор из внутренней области видимости должен существовать дольше, чем срок действия этой области. N-API поддерживает «область видимости с возможностью выхода» для поддержки этого случая. Область видимости с возможностью выхода позволяет одному дескриптору «продвигаться» так, чтобы он «выходил» за пределы текущей области видимости, и срок действия дескриптора изменяется с текущей области видимости на внешнюю область видимости.
Доступные методы для открытия/закрытия областей видимости с возможностью выхода — napi_open_escapable_handle_scope и napi_close_escapable_handle_scope.
Запрос на продвижение дескриптора выполняется с помощью napi_escape_handle, который может быть вызван только один раз.
napi_open_handle_scope
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
napi_handle_scope* result); -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющий новую область видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API открывает новую область видимости.
napi_close_handle_scope
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
napi_handle_scope scope); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий область видимости для закрытия.
Возвращает napi_ok в случае успешного выполнения API.
Этот API закрывает переданную область видимости. Области видимости должны закрываться в обратном порядке их создания.
Этот API может быть вызван даже при наличии ожидающей JavaScript-исключения.
napi_open_escapable_handle_scope
NAPI_EXTERN napi_status
napi_open_escapable_handle_scope(napi_env env,
napi_handle_scope* result); -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющий новую область видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API открывает новую область видимости, из которой один объект может быть продвинут во внешнюю область видимости.
napi_close_escapable_handle_scope
NAPI_EXTERN napi_status
napi_close_escapable_handle_scope(napi_env env,
napi_handle_scope scope); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий область видимости для закрытия.
Возвращает napi_ok в случае успешного выполнения API.
Этот API закрывает переданную область видимости. Области видимости должны закрываться в обратном порядке их создания.
Этот API может быть вызван даже при наличии ожидающей JavaScript-исключения.
napi_escape_handle
napi_status napi_escape_handle(napi_env env,
napi_escapable_handle_scope scope,
napi_value escapee,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющий текущую область видимости. -
[in] escapee:napi_valueпредставляющий JavaScript-Objectдля выхода за пределы области видимости. -
[out] result:napi_valueпредставляющий дескриптор выходящегоObjectво внешней области видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API продвигает дескриптор объекта JavaScript, так что он остается допустимым на протяжении всего срока действия внешней области видимости. Он может быть вызван только один раз на область видимости. Если он вызывается более одного раза, будет возвращено сообщение об ошибке.
Этот API может быть вызван даже при наличии ожидающей JavaScript-исключения.
Ссылки на объекты с сроком жизни, превышающим срок действия метода нативного кода
В некоторых случаях дополнение должно иметь возможность создавать и ссылаться на объекты с сроком жизни, превышающим срок действия одного вызова нативного метода. Например, для создания конструктора и последующего использования этого конструктора в запросе для создания экземпляров необходимо иметь возможность ссылаться на объект конструктора в разных запросах создания экземпляров. Это невозможно с обычным дескриптором, возвращаемым как napi_value, как описано в предыдущем разделе. Срок жизни обычного дескриптора управляется областями видимости, и все области видимости должны быть закрыты до конца нативного метода.
N-API предоставляет методы для создания постоянных ссылок на объект. Каждая постоянная ссылка имеет связанный счётчик со значением 0 или больше. Счётчик определяет, будет ли ссылка поддерживать соответствующий объект живым. Ссылки со значением счётчика 0 не препятствуют сборке мусора объекта и часто называются «слабыми» ссылками. Любое значение счётчика больше 0 предотвратит сборку мусора объекта.
Ссылки могут быть созданы с начальным значением счётчика ссылок. Затем значение счётчика можно изменить с помощью napi_reference_ref и napi_reference_unref. Если объект был собран мусором, в то время как счётчик ссылки равен 0, все последующие вызовы для получения объекта, связанного со ссылкой napi_get_reference_value, вернут NULL для возвращаемого napi_value. Попытка вызвать napi_reference_ref для ссылки, объект которой был собран мусором, приведёт к ошибке.
Ссылки должны быть удалены, когда они больше не требуются дополнением. Когда ссылка удаляется, она больше не будет препятствовать сборке соответствующего объекта. Отсутствие удаления постоянной ссылки приведёт к «утечке памяти», при которой как собственная память для постоянной ссылки, так и соответствующий объект в куче будут навсегда сохранены.
Можно создать несколько постоянных ссылок, которые ссылаются на один и тот же объект, каждая из которых будет либо поддерживать объект активным, либо нет, в зависимости от собственного счётчика.
napi_create_reference
NAPI_EXTERN napi_status napi_create_reference(napi_env env,
napi_value value,
uint32_t initial_refcount,
napi_ref* result); -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueпредставляющийObject, для которого требуется ссылка. -
[in] initial_refcount: Начальное значение счётчика ссылок для новой ссылки. -
[out] result:napi_ref, указывающий на новую ссылку.
Возвращает napi_ok, если API успешно выполнено.
Этот API создаёт новую ссылку со значением счётчика ссылок, указанным для Object переданного объекта.
napi_delete_reference
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref);
-
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_ref, который необходимо удалить.
Возвращает napi_ok, если API успешно выполнено.
Этот API удаляет переданную ссылку.
Этот API можно вызвать даже если есть ожидающее исключение JavaScript.
napi_reference_ref
NAPI_EXTERN napi_status napi_reference_ref(napi_env env,
napi_ref ref,
uint32_t* result); -
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_refдля которого необходимо увеличить счётчик ссылок. -
[out] result: Новое значение счётчика ссылок.
Возвращает napi_ok, если API успешно выполнено.
Этот API увеличивает счётчик ссылок для переданной ссылки и возвращает полученное значение счётчика.
napi_reference_unref
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
napi_ref ref,
uint32_t* result); -
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_refдля которого необходимо уменьшить счётчик ссылок. -
[out] result: Новое значение счётчика ссылок.
Возвращает napi_ok, если API успешно выполнено.
Этот API уменьшает счётчик ссылок для переданной ссылки и возвращает полученное значение счётчика.
napi_get_reference_value
NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,
napi_ref ref,
napi_value* result); переменная napi_value passed в этих методах — это указатель на объект, к которому относится ссылка.
-
[in] env: Среда, в которой вызывается API. -
[in] ref:napi_ref, для которого запрашивается соответствующийObject. -
[out] result:napi_valueдляObjectссылки, на который ссылаетсяnapi_ref.
Возвращает napi_ok, если API успешно выполнено.
Если ссылка всё ещё действительна, этот API возвращает napi_value представляющий JavaScript Object связанный с napi_ref. В противном случае, результат будет NULL.
Очистка при выходе текущего экземпляра Node.js
Хотя процесс Node.js обычно освобождает все свои ресурсы при выходе, встраивающие Node.js или будущая поддержка Worker могут потребовать от дополнений зарегистрировать обработчики очистки, которые будут выполнены после выхода текущего экземпляра Node.js.
N-API предоставляет функции для регистрации и отмены регистрации таких обратных вызовов. При выполнении этих обратных вызовов все ресурсы, удерживаемые дополнением, должны быть освобождены.
napi_add_env_cleanup_hook
NODE_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env,
void (*fun)(void* arg),
void* arg); Регистрирует fun в качестве функции, которая будет выполнена с параметром arg, когда текущая среда Node.js выйдет.
Функцию можно безопасно указать несколько раз с различными значениями arg. В этом случае она также будет вызвана несколько раз. Предоставление одинаковых значений fun и arg несколько раз запрещено и приведёт к аварийному завершению процесса.
Обработчики будут вызваны в обратном порядке, т. е. последний добавленный будет вызван первым.
Удаление этого обработчика можно выполнить с помощью napi_remove_env_cleanup_hook. Как правило, это происходит, когда ресурс, для которого был добавлен этот обработчик, всё равно разрушается.
Для асинхронной очистки доступен napi_add_async_cleanup_hook.
napi_remove_env_cleanup_hook
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env,
void (*fun)(void* arg),
void* arg); Отменяет регистрацию fun в качестве функции, которая будет выполнена с параметром arg при выходе текущей среды Node.js. И аргумент, и значение функции должны быть точно такими же.
Функция должна была быть первоначально зарегистрирована с помощью napi_add_env_cleanup_hook, в противном случае процесс прервётся.
napi_add_async_cleanup_hook
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
napi_env env,
napi_async_cleanup_hook hook,
void* arg,
napi_async_cleanup_hook_handle* remove_handle); -
[in] env: Среда, в которой вызывается API. -
[in] hook: Указатель на функцию, которая должна быть вызвана при завершении среды. -
[in] arg: Указатель, который передаётся вhook, когда она вызывается. -
[out] remove_handle: Необязательная обработка, которая ссылается на асинхронную обработку очистки.
Регистрирует hook, которая является функцией типа napi_async_cleanup_hook, как функцию, которая будет выполнена с параметрами remove_handle и arg после выхода текущей среды Node.js.
В отличие от napi_add_env_cleanup_hook, обработчик может быть асинхронным.
В остальном поведение в целом соответствует napi_add_env_cleanup_hook.
Если remove_handle не NULL, в нём будет храниться неявное значение, которое необходимо передать в napi_remove_async_cleanup_hook позже, независимо от того, была ли уже вызвана обработка. Как правило, это происходит, когда ресурс, для которого была добавлена эта обработка, разрушается.
napi_remove_async_cleanup_hook
NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(
napi_async_cleanup_hook_handle remove_handle); -
[in] remove_handle: Обработка асинхронной очистки, которая была создана с помощьюnapi_add_async_cleanup_hook.
Отменяет обработчик очистки, соответствующий remove_handle. Это предотвратит выполнение обработчика, если он ещё не начал выполняться. Это обязательно для любого значения napi_async_cleanup_hook_handle, полученного из napi_add_async_cleanup_hook.
Регистрация модулей
Модули N-API регистрируются аналогично другим модулям, но вместо использования макроса NODE_MODULE используется следующее:
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
Следующее отличие – сигнатура метода Init. Для модуля N-API она выглядит так:
napi_value Init(napi_env env, napi_value exports);
Значение, возвращаемое Init, рассматривается как объект exports для модуля. Метод Init получает пустой объект через параметр exports для удобства. Если Init возвращает NULL, параметр, переданный как exports, экспортируется модулем. Модули N-API не могут изменять объект module, но могут указать что-либо в качестве свойства exports модуля.
Для добавления метода hello как функции, чтобы её можно было вызывать как метод плагина:
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor desc = {
"hello",
NULL,
Method,
NULL,
NULL,
NULL,
napi_writable | napi_enumerable | napi_configurable,
NULL
};
status = napi_define_properties(env, exports, 1, &desc);
if (status != napi_ok) return NULL;
return exports;
} Для установки функции, которая должна возвращаться require() для плагина:
napi_value Init(napi_env env, napi_value exports) {
napi_value method;
napi_status status;
status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method);
if (status != napi_ok) return NULL;
return method;
} Для определения класса, чтобы можно было создавать новые экземпляры (часто используется с обёртыванием объектов):
// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor properties[] = {
{ "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
};
napi_value cons;
status =
napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
if (status != napi_ok) return NULL;
status = napi_create_reference(env, cons, 1, &constructor);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "MyObject", cons);
if (status != napi_ok) return NULL;
return exports;
} Если модуль будет загружен несколько раз в течение жизненного цикла процесса Node.js, используйте макрос NAPI_MODULE_INIT для инициализации модуля:
NAPI_MODULE_INIT() {
napi_value answer;
napi_status result;
status = napi_create_int64(env, 42, &answer);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "answer", answer);
if (status != napi_ok) return NULL;
return exports;
} Этот макрос включает NAPI_MODULE, и объявляет функцию Init со специальным именем и видимостью за пределами плагина. Это позволит Node.js инициализировать модуль, даже если он загружен несколько раз.
При объявлении модуля, который может загружаться несколько раз, следует учесть несколько аспектов проектирования. Дополнительные сведения см. в документации по модулям с контекстной зависимостью.
Переменные env и exports будут доступны внутри тела функции после вызова макроса.
Дополнительные сведения о настройке свойств объектов см. в разделе Работа со свойствами JavaScript.
Дополнительные сведения о создании модулей плагинов в целом см. в существующем API.
Работа со значениями JavaScript
N-API предоставляет набор API для создания всех типов значений JavaScript. Некоторые из этих типов описаны в разделе 6 спецификации языка ECMAScript.
В основе этих API лежит одно из следующих действий:
- Создание нового объекта JavaScript
- Преобразование примитивного типа C в значение N-API
- Преобразование значения N-API в примитивный тип C
- Получение глобальных экземпляров, включая
undefinedиnull
Значения N-API представлены типом napi_value. Любой вызов N-API, требующий значения JavaScript, принимает napi_value. В некоторых случаях API предварительно проверяет тип napi_value. Однако для повышения производительности лучше, чтобы вызывающий код убедился, что napi_value имеет ожидаемый JavaScript-тип, требуемый API.
Типы перечислений
napi_key_collection_mode
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode; Описывает перечисления фильтров Keys/Properties:
napi_key_collection_mode ограничивает диапазон собираемых свойств.
napi_key_own_only ограничивает собираемые свойства только указанным объектом. napi_key_include_prototypes также включит все ключи цепочки прототипов объекта.
napi_key_filter
typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter; Биты фильтра свойств. Они могут быть объединены с помощью оператора OR для создания составного фильтра.
napi_key_conversion
typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion; napi_key_numbers_to_strings преобразует целочисленные индексы в строки. napi_key_keep_numbers вернёт числа для целочисленных индексов.
napi_valuetype
typedef enum {
// ES6 types (corresponds to typeof)
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
napi_bigint,
} napi_valuetype; Описывает тип napi_value. Как правило, это соответствует типам, описанным в Разделе 6.1 спецификации ECMAScript Language Specification. В дополнение к типам из этого раздела, napi_valuetype также может представлять Function и Object с внешними данными.
Значение JavaScript типа napi_external отображается в JavaScript как обычный объект, на котором нельзя установить свойства и у которого нет прототипа.
napi_typedarray_type
typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
napi_bigint64_array,
napi_biguint64_array,
} napi_typedarray_type; Представляет собой базовый бинарный скалярный тип данных TypedArray. Элементы этого перечисления соответствуют Разделу 22.2 спецификации ECMAScript Language Specification.
Функции создания объектов
napi_create_array
napi_status napi_create_array(napi_env env, napi_value* result)
-
[in] env: Среда, в которой вызывается вызов N-API. -
[out] result:napi_value, представляющий JavaScriptArray.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает значение N-API, соответствующее типу JavaScript Array. Массивы JavaScript описаны в Разделе 22.1 спецификации ECMAScript Language Specification.
napi_create_array_with_length
napi_status napi_create_array_with_length(napi_env env,
size_t length,
napi_value* result) -
[in] env: Среда, в которой вызывается API. -
[in] length: Начальная длинаArray. -
[out] result:napi_value, представляющий JavaScriptArray.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает значение N-API, соответствующее типу JavaScript Array . Свойство length Array устанавливается в переданное значение длины. Однако гарантируется ли предварительная выделение буфера подлежащим VМ при создании массива, не гарантируется. Это поведение зависит от реализации подлежащей VМ. Если буфер должен быть непрерывным блоком памяти, который может быть непосредственно прочитан и/или записан через C, используйте napi_create_external_arraybuffer.
Массивы JavaScript описаны в Разделе 22.1 спецификации ECMAScript Language Specification.
napi_create_arraybuffer
napi_status napi_create_arraybuffer(napi_env env,
size_t byte_length,
void** data,
napi_value* result) -
[in] env: Среда, в которой вызывается API. -
[in] length: Длина в байтах создаваемого буфера массива. -
[out] data: Указатель на подлежащий байтовый буферArrayBuffer. -
[out] result:napi_value, представляющий JavaScriptArrayBuffer.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает значение N-API, соответствующее типу JavaScript ArrayBuffer. ArrayBuffer используются для представления буферов данных фиксированной длины. Обычно они используются как буфер для TypedArray объектов. Выделенный ArrayBuffer будет иметь базовый байтовый буфер, размер которого определяется параметром length, переданным в функцию. Подлежащий буфер необязательно возвращается вызывающему коду в случае, если вызывающий код хочет напрямую манипулировать им. К этому буферу можно обращаться только для записи из кода нативных языках. Для записи в этот буфер из JavaScript необходимо создать массив с типом данных или объект DataView.
Объекты JavaScript ArrayBuffer описаны в Разделе 24.1 спецификации ECMAScript Language Specification.
napi_create_buffer
napi_status napi_create_buffer(napi_env env,
size_t size,
void** data,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] size: Размер базового буфера в байтах. -
[out] data: Сырой указатель на базовый буфер. -
[out] result: Anapi_value, представляющийnode::Buffer.
Возвращает napi_ok, если API выполнилось успешно.
Этот API выделяет объект node::Buffer. Хотя эта структура данных полностью поддерживается, в большинстве случаев достаточно использовать TypedArray.
napi_create_buffer_copy
napi_status napi_create_buffer_copy(napi_env env,
size_t length,
const void* data,
void** result_data,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] size: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Сырой указатель на базовый буфер для копирования. -
[out] result_data: Указатель на базовый буфер данных новогоBuffer. -
[out] result: Anapi_value, представляющийnode::Buffer.
Возвращает napi_ok, если API выполнилось успешно.
Этот API выделяет объект node::Buffer и инициализирует его данными, скопированными из переданного буфера. Хотя эта структура данных полностью поддерживается, в большинстве случаев достаточно использовать TypedArray.
napi_create_date
napi_status napi_create_date(napi_env env,
double time,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] time: Значение времени ECMAScript в миллисекундах с 01 января 1970 года по UTC. -
[out] result: Anapi_value, представляющий JavaScriptDate.
Возвращает napi_ok, если API выполнилось успешно.
Этот API не учитывает високосные секунды; они игнорируются, так как ECMAScript соответствует спецификации времени POSIX.
Этот API выделяет объект JavaScript Date.
Объекты JavaScript Date описаны в разделе 20.3 спецификации языка ECMAScript.
napi_create_external
napi_status napi_create_external(napi_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] data: Сырой указатель на внешние данные. -
[in] finalize_cb: Необязательный обратный вызов, вызываемый при сборе внешнего значения.napi_finalizeсодержит больше подробностей. -
[in] finalize_hint: Необязательный подсказка для передачи в обратный вызов finalize во время сбора. -
[out] result: Anapi_value, представляющий внешнее значение.
Возвращает napi_ok, если API выполнилось успешно.
Этот API выделяет значение JavaScript с прикреплёнными к нему внешними данными. Это используется для передачи внешних данных через JavaScript-код, чтобы они могли быть получены позже кодом нативных языков с помощью napi_get_value_external.
API добавляет обратный вызов napi_finalize, который будет вызван, когда созданный JavaScript-объект готов к сборке мусора. Он похож на napi_wrap(), за исключением:
- внешние данные не могут быть получены позже с помощью
napi_unwrap(), - они также не могут быть удалены позже с помощью
napi_remove_wrap(), и - созданный API объект может быть использован с
napi_wrap().
Созданное значение не является объектом и, следовательно, не поддерживает дополнительные свойства. Это считается отдельным типом значения: вызов napi_typeof() с внешним значением возвращает napi_external.
napi_create_external_arraybuffer
napi_status
napi_create_external_arraybuffer(napi_env env,
void* external_data,
size_t byte_length,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] external_data: Указатель на базовый байтовый буферArrayBuffer. -
[in] byte_length: Длина базового буфера в байтах. -
[in] finalize_cb: Необязательный обратный вызов, который вызывается при сбореArrayBuffer.napi_finalizeсодержит больше подробностей. -
[in] finalize_hint: Необязательный подсказка для передачи в обратный вызов finalize во время сбора. -
[out] result: Anapi_value, представляющий JavaScriptArrayBuffer.
Возвращает napi_ok, если API выполнилось успешно.
Этот API возвращает значение N-API, соответствующее JavaScript ArrayBuffer. Базовый байтовый буфер ArrayBuffer выделяется и управляется внешним образом. Вызывающая сторона должна гарантировать, что байтовый буфер остаётся валидным до тех пор, пока не будет вызван обратный вызов finalize.
API добавляет обратный вызов napi_finalize, который будет вызван, когда созданный JavaScript-объект готов к сборке мусора. Он похож на napi_wrap(), за исключением:
- внешние данные не могут быть получены позже с помощью
napi_unwrap(), - они также не могут быть удалены позже с помощью
napi_remove_wrap(), и - созданный API объект может быть использован с
napi_wrap().
Объекты JavaScript ArrayBuffer описаны в разделе 24.1 спецификации языка ECMAScript.
napi_create_external_buffer
napi_status napi_create_external_buffer(napi_env env,
size_t length,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] length: Размер буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Сырой указатель на базовый буфер, который необходимо экспонировать для JavaScript. -
[in] finalize_cb: Необязательный обратный вызов, который вызывается, когда происходит сборка мусораArrayBuffer.napi_finalizeсодержит дополнительные сведения. -
[in] finalize_hint: Необязательное значение, передаваемое в обратный вызов finalize во время сбора мусора. -
[out] result: Объектnapi_value, представляющийnode::Buffer.
Возвращает napi_ok при успешном выполнении API.
Этот API выделяет объект node::Buffer и инициализирует его данными, опирающимися на переданный буфер. Хотя это все ещё полностью поддерживаемая структура данных, в большинстве случаев использования объекта TypedArray будет достаточно.
API добавляет обратный вызов napi_finalize, который вызывается, когда созданный JavaScript-объект готов для сбора мусора. Он похож на napi_wrap(), за исключением того, что:
- данные с родного уровня не могут быть получены позже с помощью
napi_unwrap(), - они также не могут быть удалены позже с помощью
napi_remove_wrap(), и - объект, созданный API, может быть использован с
napi_wrap().
Для Node.js >=4 Buffers являются Uint8Array.
napi_create_object
napi_status napi_create_object(napi_env env, napi_value* result)
-
[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) -
[in] env: Окружение, в котором вызывается API. -
[in] description: Необязательныйnapi_value, который ссылается на JavaScript-символString, который будет задан как описание для символа. -
[out] result: Объектnapi_value, представляющий JavaScript-символSymbol.
Возвращает napi_ok при успешном выполнении API.
Этот API создает JavaScript-объект Symbol из UTF8-кодированной C-строки.
Тип JavaScript-символа Symbol описан в Разделе 19.4 спецификации языка ECMAScript.
napi_create_typedarray
napi_status napi_create_typedarray(napi_env env,
napi_typedarray_type type,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result) -
[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) -
[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 в N-API
napi_create_int32
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Целочисленное значение, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptNumber.
Возвращает 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)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Беззнаковое целочисленное значение, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptNumber.
Возвращает 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)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Целочисленное значение, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptNumber.
Возвращает napi_ok, если API успешно выполнился.
Этот API используется для преобразования типа C int64_t в тип JavaScript Number.
Тип JavaScript Number описан в разделе 6.1.6 спецификации языка ECMAScript. Обратите внимание, что полный диапазон int64_t не может быть представлен в JavaScript с полной точностью. Целочисленные значения за пределами диапазона Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) потеряют точность.
napi_create_double
napi_status napi_create_double(napi_env env, double value, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение двойной точности, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptNumber.
Возвращает napi_ok, если API успешно выполнился.
Этот API используется для преобразования типа C double в тип JavaScript Number.
Тип JavaScript Number описан в разделе 6.1.6 спецификации языка ECMAScript.
napi_create_bigint_int64
napi_status napi_create_bigint_int64(napi_env env,
int64_t value,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] value: Целочисленное значение, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok, если API успешно выполнился.
Этот API преобразует тип C int64_t в тип JavaScript BigInt.
napi_create_bigint_uint64
napi_status napi_create_bigint_uint64(napi_env env,
uint64_t value,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] value: Беззнаковое целочисленное значение, подлежащее представлению в JavaScript. -
[out] result: Объектnapi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok, если API успешно выполнился.
Этот API преобразует тип C uint64_t в тип JavaScript BigInt.
napi_create_bigint_words
napi_status napi_create_bigint_words(napi_env env,
int sign_bit,
size_t word_count,
const uint64_t* words,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] sign_bit: Определяет, будет ли полученноеBigIntположительным или отрицательным. -
[in] word_count: Длина массиваwords. -
[in] words: Массивuint64_tмалоэндианных 64-битных слов. -
[out] result: Объектnapi_value, представляющий JavaScriptBigInt.
Возвращает napi_ok, если API успешно выполнился.
Этот API преобразует массив беззнаковых 64-битных слов в одно BigInt значение.
Полученное BigInt вычисляется как: (–1)sign_bit (words[0] × (264)0 + words[1] × (264)1 + …)
napi_create_string_latin1
napi_status napi_create_string_latin1(napi_env env,
const char* str,
size_t length,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку, закодированную в ISO-8859-1. -
[in] length: Длина строки в байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объектnapi_value, представляющий строковыйStringJavaScript.
Возвращает napi_ok, если API выполнился успешно.
Этот API создаёт объект JavaScript String из C-строки, закодированной в ISO-8859-1. Исходная строка копируется.
Тип JavaScript String описан в Разделе 6.1.4 спецификации языка ECMAScript.
napi_create_string_utf16
napi_status napi_create_string_utf16(napi_env env,
const char16_t* str,
size_t length,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку, закодированную в UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объектnapi_value, представляющий строковыйStringJavaScript.
Возвращает napi_ok, если API выполнился успешно.
Этот API создаёт объект JavaScript String из C-строки, закодированной в UTF16-LE. Исходная строка копируется.
Тип JavaScript String описан в Разделе 6.1.4 спецификации языка ECMAScript.
napi_create_string_utf8
napi_status napi_create_string_utf8(napi_env env,
const char* str,
size_t length,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку, закодированную в UTF8. -
[in] length: Длина строки в байтах, илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объектnapi_value, представляющий строковыйStringJavaScript.
Возвращает napi_ok, если API выполнился успешно.
Этот API создаёт объект JavaScript String из C-строки, закодированной в UTF8. Исходная строка копируется.
Тип JavaScript String описан в Разделе 6.1.4 спецификации языка ECMAScript.
Функции для преобразования из N-API в типы C
napi_get_array_length
napi_status napi_get_array_length(napi_env env,
napi_value value,
uint32_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptArray, длина которого запрашивается. -
[out] result:uint32представляющий длину массива.
Возвращает napi_ok, если API выполнился успешно.
Этот API возвращает длину массива.
Свойство Array длины описано в Разделе 22.1.4.1 спецификации языка ECMAScript.
napi_get_arraybuffer_info
napi_status napi_get_arraybuffer_info(napi_env env,
napi_value arraybuffer,
void** data,
size_t* byte_length) -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer:napi_valueпредставляющий запрашиваемыйArrayBuffer. -
[out] data: Базовый буфер данныхArrayBuffer. Если byte_length -0, он может бытьNULLили любым другим значением указателя. -
[out] byte_length: Длина базового буфера данных в байтах.
Возвращает napi_ok, если API выполнился успешно.
Этот API используется для извлечения базового буфера данных объекта ArrayBuffer и его длины.
ВНИМАНИЕ: Будьте внимательны при использовании этого API. Жизненный цикл базового буфера данных управляется объектом 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) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющийnode::Buffer, который запрашивается. -
[out] data: Базовый буфер данныхnode::Buffer. Если длина равна0, это может бытьNULLили любое другое значение указателя. -
[out] length: Длина базового буфера данных в байтах.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для получения базового буфера данных и его длины для node::Buffer.
Предупреждение: Будьте осторожны при использовании этого API, так как срок жизни базового буфера данных не гарантируется, если он управляется виртуальной машиной.
napi_get_prototype
napi_status napi_get_prototype(napi_env env,
napi_value object,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] object:napi_value, представляющий JavaScriptObject, прототип которого нужно вернуть. Возвращает эквивалентObject.getPrototypeOf(что не то же самое, что свойствоprototypeфункции). -
[out] result:napi_value, представляющий прототип заданного объекта.
Возвращает napi_ok в случае успешного выполнения API.
napi_get_typedarray_info
napi_status napi_get_typedarray_info(napi_env env,
napi_value typedarray,
napi_typedarray_type* type,
size_t* length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset) -
[in] env: Окружение, в котором вызывается API. -
[in] typedarray:napi_value, представляющийTypedArray, свойства которого необходимо запросить. -
[out] type: Тип данных элементов вTypedArray. -
[out] length: Количество элементов вTypedArray. -
[out] data: Буфер данных, лежащий в основеTypedArray, скорректированный значениемbyte_offset, так что он указывает на первый элемент вTypedArray. Если длина массива равна0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer: Данные, лежащие в основеTypedArray. -
[out] byte_offset: Смещение в байтах в базовом нативном массиве, от которого начинается проекция первого элемента массивов. Значение параметра data уже было скорректировано, поэтому data указывает на первый элемент в массиве. Таким образом, первый байт нативного массива находится по адресуdata - byte_offset.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает различные свойства массива с типом данных.
Предупреждение: Будьте осторожны при использовании этого API, так как базовый буфер данных управляется виртуальной машиной.
napi_get_dataview_info
napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* byte_length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset) -
[in] env: Окружение, в котором вызывается API. -
[in] dataview:napi_value, представляющийDataView, свойства которого необходимо запросить. -
[out] byte_length: Количество байтов вDataView. -
[out] data: Буфер данных, лежащий в основеDataView. Если byte_length равно0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer: Данные, лежащие в основеDataView. -
[out] byte_offset: Смещение в байтах в буфере данных, с которого начинается проекцияDataView.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает различные свойства DataView.
napi_get_date_value
napi_status napi_get_date_value(napi_env env,
napi_value value,
double* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий JavaScriptDate. -
[out] result: Значение времени какdouble, представленное в миллисекундах с полуночи 01 января 1970 года по UTC.
Этот API не учитывает високосные секунды; они игнорируются, так как ECMAScript соответствует спецификации времени POSIX.
Возвращает napi_ok в случае успешного выполнения API. Если передан napi_value , не являющийся датой, возвращает napi_date_expected.
Этот API возвращает значение времени C double для заданного JavaScript Date.
napi_get_value_bool
napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий JavaScriptBoolean. -
[out] result: C-булево значение, эквивалентное заданному JavaScriptBoolean.
Возвращает 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) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptNumber. -
[out] result: Эквивалент C double примитива заданного JavaScriptNumber.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не числовое значение napi_value, возвращает napi_number_expected.
Этот API возвращает эквивалент C double примитива заданного JavaScript Number.
napi_get_value_bigint_int64
napi_status napi_get_value_bigint_int64(napi_env env,
napi_value value,
int64_t* result,
bool* lossless); -
[in] env: Окружение, в котором вызывается API -
[in] value:napi_valueпредставляющий JavaScriptBigInt. -
[out] result: Cint64_tпримитив, эквивалентный заданному JavaScriptBigInt. -
[out] lossless: Указывает, было ли значениеBigIntпреобразовано без потерь.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не числовое значение BigInt, возвращает napi_bigint_expected.
Этот API возвращает C int64_t примитив, эквивалентный заданному JavaScript BigInt. При необходимости значение будет усечено, при этом lossless будет установлено в false.
napi_get_value_bigint_uint64
napi_status napi_get_value_bigint_uint64(napi_env env,
napi_value value,
uint64_t* result,
bool* lossless); -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptBigInt. -
[out] result: Cuint64_tпримитив, эквивалентный заданному JavaScriptBigInt. -
[out] lossless: Указывает, было ли значениеBigIntпреобразовано без потерь.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не числовое значение BigInt, возвращает napi_bigint_expected.
Этот API возвращает C uint64_t примитив, эквивалентный заданному JavaScript BigInt. При необходимости значение будет усечено, при этом lossless будет установлено в false.
napi_get_value_bigint_words
napi_status napi_get_value_bigint_words(napi_env env,
napi_value value,
int* sign_bit,
size_t* word_count,
uint64_t* words); -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptBigInt. -
[out] sign_bit: Целое число, представляющее, является ли JavaScriptBigIntположительным или отрицательным. -
[in/out] word_count: Должен быть инициализирован длиной массиваwords. При возврате он будет установлен в фактическое количество слов, необходимое для хранения этогоBigInt. -
[out] words: Указатель на предварительно выделенный массив 64-битовых слов.
Возвращает napi_ok в случае успеха API.
Этот API преобразует единственное значение BigInt в знаковый бит, массив 64-битовых слов в формате little-endian и количество элементов в массиве. sign_bit и words могут быть оба установлены в NULL, для получения только word_count.
napi_get_value_external
napi_status napi_get_value_external(napi_env env,
napi_value value,
void** result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий внешнее значение JavaScript. -
[out] result: Указатель на данные, обернутые внешним значением JavaScript.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не внешнее napi_value значение, возвращает napi_invalid_arg.
Этот API извлекает указатель на внешние данные, которые были ранее переданы в napi_create_external().
napi_get_value_int32
napi_status napi_get_value_int32(napi_env env,
napi_value value,
int32_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptNumber. -
[out] result: Cint32примитив, эквивалентный заданному JavaScriptNumber.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не числовое значение napi_value, то napi_number_expected.
Этот API возвращает C int32 примитив, эквивалентный заданному JavaScript Number.
Если число выходит за пределы диапазона 32-битного целого числа, результат усекается до эквивалента нижних 32 битов. Это может привести к тому, что большое положительное число станет отрицательным, если значение больше, чем 231 - 1.
Неконечные числовые значения (NaN, +Infinity, или -Infinity ) устанавливают результат в ноль.
napi_get_value_int64
napi_status napi_get_value_int64(napi_env env,
napi_value value,
int64_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptNumber. -
[out] result: Cint64примитив, эквивалентный заданному JavaScriptNumber.
Возвращает napi_ok в случае успеха API. Если в качестве аргумента передано не числовое значение napi_value, возвращает napi_number_expected.
Этот API возвращает эквивалент примитива C int64 для данного JavaScript Number.
Значения вне диапазона Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) будут иметь потерю точности.
Нечисловые значения (NaN, +Infinity, или -Infinity) устанавливают результат в ноль.
napi_get_value_string_latin1
napi_status napi_get_value_string_latin1(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий строку JavaScript. -
[in] buf: Буфер для записи строки, закодированной в ISO-8859-1. ЕслиNULLпередан, возвращается длина строки (в байтах). -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка будет усечена. -
[out] result: Количество байтов, скопированных в буфер, без учёта нулевого терминатора.
Возвращает napi_ok, если API выполнено успешно. Если передан не-String napi_value, возвращается napi_string_expected.
Этот API возвращает строку, закодированную в ISO-8859-1, соответствующую переданному значению.
napi_get_value_string_utf8
napi_status napi_get_value_string_utf8(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий строку JavaScript. -
[in] buf: Буфер для записи UTF8-закодированной строки. ЕслиNULLпередан, возвращается длина строки (в байтах). -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка будет усечена. -
[out] result: Количество байтов, скопированных в буфер, без учёта нулевого терминатора.
Возвращает napi_ok, если API выполнено успешно. Если передан не-String napi_value, возвращается napi_string_expected.
Этот API возвращает UTF8-закодированную строку, соответствующую переданному значению.
napi_get_value_string_utf16
napi_status napi_get_value_string_utf16(napi_env env,
napi_value value,
char16_t* buf,
size_t bufsize,
size_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий строку JavaScript. -
[in] buf: Буфер для записи UTF16-LE-закодированной строки. ЕслиNULLпередан, возвращается длина строки (в 2-байтовых кодовых единицах). -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка будет усечена. -
[out] result: Количество 2-байтовых кодовых единиц, скопированных в буфер, без учёта нулевого терминатора.
Возвращает napi_ok, если API выполнено успешно. Если передан не-String napi_value, возвращается napi_string_expected.
Этот API возвращает UTF16-закодированную строку, соответствующую переданному значению.
napi_get_value_uint32
napi_status napi_get_value_uint32(napi_env env,
napi_value value,
uint32_t* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_value, представляющий JavaScriptNumber. -
[out] result: Примитив C, эквивалентный данномуnapi_valueкакuint32_t.
Возвращает napi_ok, если API выполнено успешно. Если передан нечисловой napi_value параметр, возвращается napi_number_expected.
Этот API возвращает примитивный эквивалент C данного napi_value в виде uint32_t.
Функции получения глобальных экземпляров
napi_get_boolean
napi_status napi_get_boolean(napi_env env, bool value, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение булевого значения для извлечения. -
[out] result:napi_valueпредставляющий JavaScriptBooleanсинглтон для извлечения.
Возвращает napi_ok, если API выполнено успешно.
Этот API используется для возвращения объекта JavaScript-синглтона, используемого для представления данного булевого значения.
napi_get_global
napi_status napi_get_global(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_valueпредставляющий JavaScript-объектglobal.
Возвращает napi_ok, если API выполнено успешно.
Этот API возвращает объект global.
napi_get_null
napi_status napi_get_null(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_valueпредставляющий JavaScript-объектnull.
Возвращает napi_ok, если API выполнено успешно.
Этот API возвращает объект null.
napi_get_undefined
napi_status napi_get_undefined(napi_env env, napi_value* result)
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_value, представляющий значение JavaScript Undefined.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает объект Undefined.
Работа с JavaScript-значениями и абстрактными операциями
N-API предоставляет набор API для выполнения некоторых абстрактных операций над JavaScript-значениями. Некоторые из этих операций описаны в разделе 7 Спецификации языка ECMAScript.
Эти API поддерживают выполнение одного из следующих действий:
- Преобразование JavaScript-значений к определённым типам JavaScript (например,
NumberилиString). - Определение типа JavaScript-значения.
- Проверку равенства между двумя JavaScript-значениями.
napi_coerce_to_bool
napi_status napi_coerce_to_bool(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_value, представляющий преобразованное JavaScript-значениеBoolean.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToBoolean(), как определено в разделе 7.1.2 Спецификации языка ECMAScript. Этот API может быть многопоточным, если для переданного Object определены геттеры.
napi_coerce_to_number
napi_status napi_coerce_to_number(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_value, представляющий преобразованное JavaScript-значениеNumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToNumber(), как определено в разделе 7.1.3 Спецификации языка ECMAScript. Этот API может быть многопоточным, если для переданного Object определены геттеры.
napi_coerce_to_object
napi_status napi_coerce_to_object(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_value, представляющий преобразованное JavaScript-значениеObject.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToObject(), как определено в разделе 7.1.13 Спецификации языка ECMAScript. Этот API может быть многопоточным, если для переданного Object определены геттеры.
napi_coerce_to_string
napi_status napi_coerce_to_string(napi_env env,
napi_value value,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] value: JavaScript-значение для преобразования. -
[out] result:napi_value, представляющий преобразованное JavaScript-значениеString.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToString(), как определено в разделе 7.1.13 Спецификации языка ECMAScript. Этот API может быть многопоточным, если для переданного Object определены геттеры.
napi_typeof
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: JavaScript-значение, тип которого нужно получить. -
[out] result: Тип JavaScript-значения.
Возвращает 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) -
[in] env: Окружение, в котором вызывается API. -
[in] object: Проверяемое значение JavaScript. -
[in] constructor: Объект JavaScript-функции конструктора для проверки. -
[out] result: Булево значение, установленное в true, еслиobject instanceof constructorравно true.
Возвращает napi_ok в случае успешного выполнения API.
Этот API представляет вызов оператора instanceof для объекта, как определено в разделе 12.10.4 спецификации языка ECMAScript.
napi_is_array
napi_status napi_is_array(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Является ли данный объект массивом.
Возвращает napi_ok в случае успешного выполнения API.
Этот API представляет вызов операции IsArray для объекта, как определено в разделе 7.2.2 спецификации языка ECMAScript.
napi_is_arraybuffer
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Является ли данный объект объектомArrayBuffer.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object буфером массива.
napi_is_buffer
napi_status napi_is_buffer(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Представляет ли данноеnapi_valueобъект типаnode::Buffer.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object буфером.
napi_is_date
napi_status napi_is_date(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Представляет ли данныйnapi_valueобъект JavaScript типаDate.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object датой.
napi_is_error
napi_status napi_is_error(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Представляет ли данноеnapi_valueобъект типаError.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object объектом Error.
napi_is_typedarray
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Представляет ли данныйnapi_valueобъект типаTypedArray.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object типом массива.
napi_is_dataview
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result)
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Проверяемое значение JavaScript. -
[out] result: Представляет ли данныйnapi_valueобъект типаDataView.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object объектом типа DataView.
napi_strict_equals
napi_status napi_strict_equals(napi_env env,
napi_value lhs,
napi_value rhs,
bool* result) -
[in] env: Окружение, в котором вызывается API. -
[in] lhs: Проверяемое значение JavaScript. -
[in] rhs: Проверяемое значение JavaScript для сравнения. -
[out] result: Являются ли два объектаnapi_valueравными.
Возвращает napi_ok в случае успешного выполнения API.
Этот API представляет вызов алгоритма строгого равенства, как определено в разделе 7.2.14 спецификации языка ECMAScript.
napi_detach_arraybuffer
napi_status napi_detach_arraybuffer(napi_env env,
napi_value arraybuffer) -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: Объект 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) -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: JavaScriptArrayBufferдля проверки. -
[out] result: Является лиarraybufferотсоединённым.
Возвращает napi_ok если API успешно выполнилось.
ArrayBuffer считается отсоединённым, если его внутренние данные null.
Этот API представляет вызов операции ArrayBuffer IsDetachedBuffer в соответствии со разделом 24.1.1.2 спецификации языка ECMAScript.
Работа с свойствами JavaScript
N-API предоставляет набор API для получения и установки свойств объектов JavaScript. Некоторые из этих типов документированы в разделе 7 спецификации языка ECMAScript.
Свойства в JavaScript представлены как кортеж из ключа и значения. В N-API все ключи свойств могут быть представлены в одном из следующих форматов:
- Именованные: простая строка UTF8
- Индексированные по целочисленному значению: значение индекса, представленное
uint32_t - Значение JavaScript: в N-API они представлены
napi_value. Это может бытьnapi_valueпредставляющаяString,Number, илиSymbol.
Значения N-API представлены типом napi_value. Любой вызов N-API, требующий значения JavaScript, принимает napi_value. Однако, ответственность за проверку того, что napi_value является ожидаемого типа JavaScript, лежит на вызывающей стороне.
API, документированные в этом разделе, предоставляют простой интерфейс для получения и установки свойств произвольных объектов JavaScript, представленных napi_value.
Например, рассмотрите следующий фрагмент кода JavaScript:
const obj = {};
obj.myProp = 123; Аналогичный результат можно получить, используя значения N-API с помощью следующего фрагмента:
napi_status status = napi_generic_failure;
// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create a napi_value for 123
status = napi_create_int32(env, 123, &value);
if (status != napi_ok) return status;
// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status; Индексированные свойства могут быть установлены аналогичным образом. Рассмотрим следующий фрагмент кода JavaScript:
const arr = []; arr[123] = 'hello';
Аналогичный результат можно получить, используя значения N-API с помощью следующего фрагмента:
napi_status status = napi_generic_failure; // const arr = []; napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // Create a napi_value for 'hello' status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &value); if (status != napi_ok) return status; // arr[123] = 'hello'; status = napi_set_element(env, arr, 123, value); if (status != napi_ok) return status;
Свойства могут быть получены с помощью API, описанных в этом разделе. Рассмотрим следующий фрагмент кода JavaScript:
const arr = []; const value = arr[123];
Следующий фрагмент примерно эквивалентен N-API аналогу:
napi_status status = napi_generic_failure; // const arr = [] napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // const value = arr[123] status = napi_get_element(env, arr, 123, &value); if (status != napi_ok) return status;
Наконец, для повышения производительности, несколько свойств могут быть определены на объекте. Рассмотрим следующий фрагмент JavaScript:
const obj = {};
Object.defineProperties(obj, {
'foo': { value: 123, writable: true, configurable: true, enumerable: true },
'bar': { value: 456, writable: true, configurable: true, enumerable: true }
}); Следующий фрагмент примерно эквивалентен N-API аналогу:
napi_status status = napi_status_generic_failure;
// const obj = {};
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_int32(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_int32(env, 456, &barValue);
if (status != napi_ok) return status;
// Set the properties
napi_property_descriptor descriptors[] = {
{ "foo", NULL, NULL, NULL, NULL, fooValue, napi_writable | napi_configurable, NULL },
{ "bar", NULL, NULL, NULL, NULL, barValue, napi_writable | napi_configurable, NULL }
}
status = napi_define_properties(env,
obj,
sizeof(descriptors) / sizeof(descriptors[0]),
descriptors);
if (status != napi_ok) return status; Структуры
napi_property_attributes
typedef enum {
napi_default = 0,
napi_writable = 1 << 0,
napi_enumerable = 1 << 1,
napi_configurable = 1 << 2,
// Used with napi_define_class to distinguish static properties
// from instance properties. Ignored by napi_define_properties.
napi_static = 1 << 10,
// Default for class methods.
napi_default_method = napi_writable | napi_configurable,
// Default for object properties, like in JS obj[prop].
napi_default_property = napi_writable |
napi_enumerable |
napi_configurable,
} napi_property_attributes; napi_property_attributes — это флаги, используемые для управления поведением свойств, установленных на объект JavaScript. Помимо napi_static, они соответствуют атрибутам, перечисленным в разделе 6.1.7.1 спецификации языка ECMAScript. Они могут быть одним или несколькими из следующих битовых флагов:
-
napi_default: Нет явных атрибутов для свойства. По умолчанию свойство является только для чтения, не перечисляемым и не настраиваемым. -
napi_writable: Свойство изменяемое. -
napi_enumerable: Свойство перечисляемое. -
napi_configurable: Свойство настраиваемое, как определено в разделе 6.1.7.1 спецификации языка ECMAScript. -
napi_static: Свойство будет определено как статическое свойство класса, а не свойства экземпляра, что является значением по умолчанию. Используется толькоnapi_define_class. Игнорируетсяnapi_define_properties. -
napi_default_method: Свойство настраиваемое, изменяемое, но не перечисляемое, как метод в классе JS. -
napi_default_property: Свойство изменяемое, перечисляемое и настраиваемое, как свойство, установленное с помощью кода JSobj.key = value.
napi_property_descriptor
typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;
napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;
napi_property_attributes attributes;
void* data;
} napi_property_descriptor; -
utf8name: НеобязательноеStringописание ключа свойства, закодированного в UTF8. Для свойства должен быть указан один изutf8nameилиname. -
name: Необязательноеnapi_valueзначение, которое указывает на JavaScript-строку или символ, используемые в качестве ключа свойства. Для свойства должен быть указан один изutf8nameилиname. -
value: Значение, получаемое при чтении свойства, если свойство является свойством данных. Если это значение передано, необходимо установитьgetter,setter,methodиdataвNULL(так как эти члены не будут использоваться). -
getter: Функция, вызываемая при чтении свойства. Если она передана, необходимо установитьvalueиmethodвNULL(так как эти члены не будут использоваться). Переданная функция вызывается неявно во время выполнения, когда к свойству обращаются из JavaScript-кода (или если чтение свойства выполняется с помощью вызова N-API).napi_callbackсодержит более подробную информацию. -
setter: Функция, вызываемая при записи в свойство. Если она передана, необходимо установитьvalueиmethodвNULL(так как эти члены не будут использоваться). Переданная функция вызывается неявно во время выполнения, когда свойство устанавливается из JavaScript-кода (или если запись в свойство выполняется с помощью вызова N-API).napi_callbackсодержит более подробную информацию. -
method: Установите это значение, чтобы сделать свойство объекта описателя свойства JavaScript-функцией, представленнойmethod. Если это значение передано, необходимо установитьvalue,getterиsetterвNULL(так как эти члены не будут использоваться).napi_callbackсодержит более подробную информацию. -
attributes: Атрибуты, связанные с конкретным свойством. См.napi_property_attributes. -
data: Данные обратного вызова, передаваемые вmethod,getterиsetter, если эта функция вызывается.
Функции
napi_get_property_names
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result); -
[in] env: Среда, в которой вызывается вызов N-API. -
[in] object: Объект, из которого необходимо получить свойства. -
[out] result:napi_value, представляющий массив JavaScript-значений, которые представляют имена свойств объекта. API можно использовать для итерации поresultс помощьюnapi_get_array_lengthиnapi_get_element.
Возвращает napi_ok, если API выполнена успешно.
Это API возвращает имена перечисляемых свойств object в виде массива строк. Свойства object, ключ которых является символом, не будут включены.
napi_get_all_property_names
napi_get_all_property_names(napi_env env,
napi_value object,
napi_key_collection_mode key_mode,
napi_key_filter key_filter,
napi_key_conversion key_conversion,
napi_value* result); -
[in] env: Среда, в которой вызывается вызов N-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); -
[in] env: Среда, в которой вызывается вызов N-API. -
[in] object: Объект, на котором необходимо установить свойство. -
[in] key: Имя свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok, если API выполнена успешно.
Это API устанавливает свойство на переданный Object.
napi_get_property
napi_status napi_get_property(napi_env env,
napi_value object,
napi_value key,
napi_value* result); -
[in] env: Среда, в которой вызывается вызов N-API. -
[in] object: Объект, из которого необходимо получить свойство. -
[in] key: Имя свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok, если API выполнена успешно.
Это API получает запрашиваемое свойство из переданного Object.
napi_has_property
napi_status napi_has_property(napi_env env,
napi_value object,
napi_value key,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, который необходимо запросить. -
[in] key: Название свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, обладает ли переданный Object указанным свойством.
napi_delete_property
napi_status napi_delete_property(napi_env env,
napi_value object,
napi_value key,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, который нужно запросить. -
[in] key: Название свойства, которое нужно удалить. -
[out] result: Удалось ли удалить свойство или нет.resultможно необязательно игнорировать, передавNULL.
Возвращает napi_ok в случае успешного выполнения API.
Этот API пытается удалить собственное свойство key из object.
napi_has_own_property
napi_status napi_has_own_property(napi_env env,
napi_value object,
napi_value key,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, который нужно запросить. -
[in] key: Название собственного свойства, существование которого нужно проверить. -
[out] result: Существует ли собственное свойство в объекте или нет.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, обладает ли переданный Object указанным собственным свойством. key должен быть строкой или Symbol, в противном случае будет выброшено исключение. N-API не будет выполнять никаких преобразований между типами данных.
napi_set_named_property
napi_status napi_set_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value value); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, к которому нужно установить свойство. -
[in] utf8Name: Название свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_set_property со строкой, преобразованной в napi_value через utf8Name.
napi_get_named_property
napi_status napi_get_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, из которого необходимо извлечь свойство. -
[in] utf8Name: Название свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_get_property со строкой, преобразованной в napi_value через utf8Name.
napi_has_named_property
napi_status napi_has_named_property(napi_env env,
napi_value object,
const char* utf8Name,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект для запроса. -
[in] utf8Name: Название свойства, существование которого необходимо проверить. -
[out] result: Существует ли свойство в объекте.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод эквивалентен вызову napi_has_property со строкой, преобразованной в napi_value через utf8Name.
napi_set_element
napi_status napi_set_element(napi_env env,
napi_value object,
uint32_t index,
napi_value value); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, для которого нужно установить свойство. -
[in] index: Индекс свойства для установки. -
[in] value: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот API устанавливает элемент в переданный Object.
napi_get_element
napi_status napi_get_element(napi_env env,
napi_value object,
uint32_t index,
napi_value* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, из которого необходимо извлечь свойство. -
[in] index: Индекс свойства для получения. -
[out] result: Значение свойства.
Возвращает napi_ok в случае успешного выполнения API.
Этот API получает элемент по указанному индексу.
napi_has_element
napi_status napi_has_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект для запроса. -
[in] index: Индекс свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает значение, указывающее, содержит ли Object элемент по запрошенному индексу.
napi_delete_element
napi_status napi_delete_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект для проверки. -
[in] index: Индекс свойства, которое нужно удалить. -
[out] result: Успешно ли удаление элемента.resultможно необязательно пропустить, передавNULL.
Возвращает napi_ok в случае успешного выполнения API.
Этот API пытается удалить указанный index из object.
napi_define_properties
napi_status napi_define_properties(napi_env env,
napi_value object,
size_t property_count,
const napi_property_descriptor* properties); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, из которого извлекаются свойства. -
[in] property_count: Количество элементов в массивеproperties. -
[in] properties: Массив описателей свойств.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет эффективно определять несколько свойств данного объекта. Свойства определяются с помощью описателей свойств (см. napi_property_descriptor). Учитывая массив таких описателей свойств, этот API будет устанавливать свойства на объект по одному, как определено в DefineOwnProperty() (описано в разделе 9.1.6 спецификации ECMA-262).
napi_object_freeze
napi_status napi_object_freeze(napi_env env,
napi_value object); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, который нужно заморозить.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод замораживает данный объект. Это предотвращает добавление новых свойств, удаление существующих свойств, изменение перечисляемости, конфигурируемости или записываемости существующих свойств, а также изменение значений существующих свойств. Также предотвращается изменение прототипа объекта. Это описано в разделе 19.1.2.6 спецификации ECMA-262.
napi_object_seal
napi_status napi_object_seal(napi_env env,
napi_value object); -
[in] env: Окружение, в котором вызывается вызов N-API. -
[in] object: Объект, который нужно запечатать.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод запечатывает данный объект. Это предотвращает добавление новых свойств, а также помечает все существующие свойства как неконфигурируемые. Это описано в разделе 19.1.2.20 спецификации ECMA-262.
Работа с функциями JavaScript
N-API предоставляет набор API, которые позволяют коду JavaScript вызывать нативный код. API N-API, поддерживающие обратный вызов в нативный код, принимают функции обратного вызова, представленные типом napi_callback. Когда JavaScript VM вызывает нативный код, вызывается функция napi_callback . API, документированные в этом разделе, позволяют функции обратного вызова выполнять следующие действия:
- Получение информации о контексте, в котором был вызван обратный вызов.
- Получение аргументов, переданных в обратный вызов.
- Возвращение
napi_valueиз обратного вызова.
Кроме того, N-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); -
[in] env: Окружение, в котором вызывается API. -
[in] recv: Объектthis, переданный вызываемой функции. -
[in] func:napi_value, представляющий вызываемую функцию JavaScript. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массивnapi_values, представляющих значения JavaScript, переданные в качестве аргументов функции. -
[out] result:napi_value, представляющий возвращаемый объект JavaScript.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать объект JavaScript-функции из нативного дополнения. Это основной механизм обратного вызова из нативного кода дополнения в JavaScript. Для особого случая вызова в JavaScript после асинхронной операции см. napi_make_callback.
Пример использования может выглядеть следующим образом. Рассмотрим следующий фрагмент JavaScript:
function AddTwo(num) {
return num + 2;
} Затем, указанную функцию можно вызвать из плагина с помощью следующего кода:
// Get the function named "AddTwo" on the global object napi_value global, add_two, arg; napi_status status = napi_get_global(env, &global); if (status != napi_ok) return; status = napi_get_named_property(env, global, "AddTwo", &add_two); if (status != napi_ok) return; // const arg = 1337 status = napi_create_int32(env, 1337, &arg); if (status != napi_ok) return; napi_value* argv = &arg; size_t argc = 1; // AddTwo(arg); napi_value return_val; status = napi_call_function(env, global, add_two, argc, argv, &return_val); if (status != napi_ok) return; // Convert the result back to a native type int32_t result; status = napi_get_value_int32(env, return_val, &result); if (status != napi_ok) return;
napi_create_function
napi_status napi_create_function(napi_env env,
const char* utf8name,
size_t length,
napi_callback cb,
void* data,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] utf8Name: Имя функции, закодированное в UTF8. Оно отображается в JavaScript как свойство объекта новой функцииname. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTH, если она имеет нулевое завершение. -
[in] cb: Функция нативного кода, которая должна вызываться при вызове объекта этой функции.napi_callbackсодержит более подробную информацию. -
[in] data: Контекст данных, предоставленный пользователем. Он будет передан обратно в функцию при последующем вызове. -
[out] result:napi_valueпредставляющий объект JavaScript-функции для вновь созданной функции.
Возвращает napi_ok, если API выполнилось успешно.
Этот API позволяет автору плагина создавать объект функции в коде нативного языка. Это основной механизм для вызова кода плагина из JavaScript.
Новой созданная функция не отображается автоматически в скрипте после этого вызова. Вместо этого, необходимо явно установить свойство на любом объекте, видимом для JavaScript, чтобы функция стала доступной из скрипта.
Чтобы экспортировать функцию в качестве части экспорта модуля плагина, установите вновь созданную функцию на объект экспорта. Пример модуля может выглядеть следующим образом:
napi_value SayHello(napi_env env, napi_callback_info info) {
printf("Hello\n");
return NULL;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return NULL;
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) Учитывая вышеприведенный код, плагин можно использовать из JavaScript следующим образом:
const myaddon = require('./addon');
myaddon.sayHello(); Строка, переданная в require(), — это имя целевого объекта в binding.gyp, ответственного за создание файла .node.
Любые данные, отличные от NULL, которые передаются в этот API через параметр data, могут быть связаны с результирующей функцией JavaScript (возвращаемой в параметре result) и освобождаться при сборке мусора функции путём передачи и функции JavaScript, и данных в napi_add_finalizer.
Объекты JavaScript-функций описаны в разделе 19.2 спецификации языка ECMAScript.
napi_get_cb_info
napi_status napi_get_cb_info(napi_env env,
napi_callback_info cbinfo,
size_t* argc,
napi_value* argv,
napi_value* thisArg,
void** data) -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация о обратном вызове, переданная в функцию обратного вызова. -
[in-out] argc: Указывает размер предоставленного массиваargvи получает фактическое количество аргументов. -
[out] argv: Буфер, в который копируютсяnapi_valueпредставляющие аргументы. Если аргументов больше, чем предоставленное количество, копируются только запрошенные. Если предоставлено меньше аргументов, чем заявлено, остальная частьargvзаполняетсяnapi_valueзначениями, представляющимиundefined. -
[out] this: Получает аргумент JavaScriptthisдля вызова. -
[out] data: Получает указатель данных для обратного вызова.
Возвращает napi_ok, если API выполнилось успешно.
Этот метод используется внутри функции обратного вызова для извлечения деталей о вызове, таких как аргументы и указатель this из предоставленной информации о обратном вызове.
napi_get_new_target
napi_status napi_get_new_target(napi_env env,
napi_callback_info cbinfo,
napi_value* result) -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация о обратном вызове, переданная в функцию обратного вызова. -
[out] result:new.targetвызова конструктора.
Возвращает 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) -
[in] env: Окружение, в котором вызывается API. -
[in] cons:napi_valueпредставляющий функцию JavaScript, которая должна вызываться как конструктор. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив значений JavaScript какnapi_valueпредставляющих аргументы конструктора. -
[out] result:napi_valueпредставляющий возвращаемый объект JavaScript, который в данном случае является созданным объектом.
Этот метод используется для создания нового значения JavaScript с помощью предоставленной napi_value, которая представляет конструктор для объекта. Например, рассмотрим следующий фрагмент:
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg); Следующее можно приблизить в N-API с помощью следующего фрагмента:
// Get the constructor function MyObject napi_value global, constructor, arg, value; napi_status status = napi_get_global(env, &global); if (status != napi_ok) return; status = napi_get_named_property(env, global, "MyObject", &constructor); if (status != napi_ok) return; // const arg = "hello" status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &arg); if (status != napi_ok) return; napi_value* argv = &arg; size_t argc = 1; // const value = new MyObject(arg) status = napi_new_instance(env, constructor, argc, argv, &value);
Возвращает napi_ok, если API выполнилось успешно.
Обёртка объекта
N-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...
} Ссылка должна быть освобождена, когда она больше не требуется.
В некоторых случаях napi_instanceof() недостаточно для обеспечения того, что JavaScript-объект является обёрткой для определённого нативного типа. Это особенно актуально, когда упакованные JavaScript-объекты передаются обратно в плагин через статические методы, а не как this значение методов прототипа. В таких случаях есть вероятность, что они будут распаковываться неправильно.
const myAddon = require('./build/Release/my_addon.node');
// `openDatabase()` returns a JavaScript object that wraps a native database
// handle.
const dbHandle = myAddon.openDatabase();
// `query()` returns a JavaScript object that wraps a native query handle.
const queryHandle = myAddon.query(dbHandle, 'Gimme ALL the things!');
// There is an accidental error in the line below. The first parameter to
// `myAddon.queryHasRecords()` should be the database handle (`dbHandle`), not
// the query handle (`query`), so the correct condition for the while-loop
// should be
//
// myAddon.queryHasRecords(dbHandle, queryHandle)
//
while (myAddon.queryHasRecords(queryHandle, dbHandle)) {
// retrieve records
} В приведённом выше примере myAddon.queryHasRecords() — метод, принимающий два аргумента. Первый — дескриптор базы данных, второй — дескриптор запроса. Внутренне он распаковывает первый аргумент и преобразует полученный указатель в нативный дескриптор базы данных. Затем он распаковывает второй аргумент и преобразует полученный указатель в дескриптор запроса. Если аргументы переданы в неправильном порядке, преобразования будут выполнены, однако существует большая вероятность того, что базовая операция базы данных завершится ошибкой или даже приведёт к неверному доступу к памяти.
Чтобы гарантировать, что указатель, полученный из первого аргумента, действительно является указателем на дескриптор базы данных, а аналогично, что указатель, полученный из второго аргумента, действительно является указателем на дескриптор запроса, реализация queryHasRecords() должна выполнять проверку типа. Сохранение конструкторов JavaScript-классов, из которых были созданы дескрипторы базы данных и запросов в napi_ref может помочь, поскольку napi_instanceof() может использоваться для проверки того, что экземпляры, переданные в queryHashRecords(), действительно являются экземплярами нужного типа.
К сожалению, napi_instanceof() не защищает от манипуляций с прототипом. Например, прототип экземпляра дескриптора базы данных может быть установлен в прототип конструктора экземпляров дескрипторов запроса. В этом случае экземпляр дескриптора базы данных может выглядеть как экземпляр дескриптора запроса, и он пройдёт napi_instanceof() проверку на экземпляр дескриптора запроса, при этом по-прежнему содержа будет хранить указатель на дескриптор базы данных.
Для этого N-API предоставляет возможности маркировки типов.
Тег типа — целое число длиной 128 бит, уникальное для плагина. N-API предоставляет структуру napi_type_tag для хранения тега типа. Когда такое значение передаётся вместе с JavaScript-объектом, хранящимся в napi_value для napi_type_tag_object(), JavaScript-объект будет «помечен» тегом типа. «Пометка» невидима со стороны JavaScript. Когда JavaScript-объект попадает в нативное связывание, napi_check_object_type_tag() может использоваться вместе с исходным тегом типа для определения, был ли JavaScript-объект ранее «помечен» тегом типа. Это создаёт возможность проверки типов с более высокой точностью, чем napi_instanceof() может предоставить, так как такая маркировка типов сохраняется при манипулировании прототипами и при загрузке/разгрузке плагина.
Продолжая вышеприведённый пример, следующий скелет реализации плагина иллюстрирует использование napi_type_tag_object() и napi_check_object_type_tag().
// This value is the type tag for a database handle. The command
//
// uuidgen | sed -r -e 's/-//g' -e 's/(.{16})(.*)/0x\1, 0x\2/'
//
// can be used to obtain the two values with which to initialize the structure.
static const napi_type_tag DatabaseHandleTypeTag = {
0x1edf75a38336451d, 0xa5ed9ce2e4c00c38
};
// This value is the type tag for a query handle.
static const napi_type_tag QueryHandleTypeTag = {
0x9c73317f9fad44a3, 0x93c3920bf3b0ad6a
};
static napi_value
openDatabase(napi_env env, napi_callback_info info) {
napi_status status;
napi_value result;
// Perform the underlying action which results in a database handle.
DatabaseHandle* dbHandle = open_database();
// Create a new, empty JS object.
status = napi_create_object(env, &result);
if (status != napi_ok) return NULL;
// Tag the object to indicate that it holds a pointer to a `DatabaseHandle`.
status = napi_type_tag_object(env, result, &DatabaseHandleTypeTag);
if (status != napi_ok) return NULL;
// Store the pointer to the `DatabaseHandle` structure inside the JS object.
status = napi_wrap(env, result, dbHandle, NULL, NULL, NULL);
if (status != napi_ok) return NULL;
return result;
}
// Later when we receive a JavaScript object purporting to be a database handle
// we can use `napi_check_object_type_tag()` to ensure that it is indeed such a
// handle.
static napi_value
query(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 2;
napi_value argv[2];
bool is_db_handle;
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (status != napi_ok) return NULL;
// Check that the object passed as the first parameter has the previously
// applied tag.
status = napi_check_object_type_tag(env,
argv[0],
&DatabaseHandleTypeTag,
&is_db_handle);
if (status != napi_ok) return NULL;
// Throw a `TypeError` if it doesn't.
if (!is_db_handle) {
// Throw a TypeError.
return NULL;
}
} napi_define_class
napi_status napi_define_class(napi_env env,
const char* utf8name,
size_t length,
napi_callback constructor,
void* data,
size_t property_count,
const napi_property_descriptor* properties,
napi_value* result); -
[in] env: Среда, в которой вызывается API. -
[in] utf8name: Имя JavaScript-функции-конструктора; необязательно, чтобы оно совпадало с именем C++-класса, хотя это рекомендуется для ясности. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[in] constructor: Функция обратного вызова, обрабатывающая создание экземпляров класса. Это должен быть статический метод класса, а не фактическая функция-конструктор C++.napi_callbackсодержит более подробную информацию. -
[in] data: Дополнительные данные, передаваемые в обратный вызов конструктора как свойствоdataинформации о вызове. -
[in] property_count: Количество элементов в массивеpropertiesаргументов. -
[in] properties: Массив описателей свойств, описывающих статические и экземплярные свойства, аксессоры и методы класса. Смотритеnapi_property_descriptor. -
[out] result: Объектnapi_value, представляющий конструктор функции класса.
Возвращает napi_ok в случае успеха API.
Определяет JavaScript-класс, соответствующий C++-классу, включая:
- Функция-конструктор JavaScript, имеющая имя класса и вызывающая предоставленный обратный вызов конструктора C++.
- Свойства функции-конструктора, соответствующие статическим данным, аксессорам и методам класса C++ (определённые описателями свойств с атрибутом
napi_static). - Свойства объекта
prototypeфункции-конструктора, соответствующие нестатическим данным, аксессорам и методам класса C++ (определённые описателями свойств без атрибутаnapi_static).
Обратный вызов конструктора C++ должен быть статическим методом в классе, который вызывает фактический конструктор класса, затем оборачивает новый экземпляр C++ в объект JavaScript и возвращает объект-обёртку. Подробности см. в napi_wrap().
Функция-конструктор JavaScript, возвращаемая из napi_define_class, часто сохраняется и используется позднее для создания новых экземпляров класса из кода нативных языков, и/или проверки, являются ли предоставленные значения экземплярами класса. В этом случае, чтобы предотвратить сборку мусора для значения функции, создайте постоянную ссылку на неё с помощью napi_create_reference и убедитесь, что счётчик ссылок остаётся >= 1.
Любые не-NULL данные, которые передаются в этот API через параметр data или через поле data элементов массива napi_property_descriptor, могут быть связаны с результирующей функцией-конструктором JavaScript (которая возвращается в параметре result) и освобождаться при сборе мусора класса путём передачи как функции JavaScript, так и данных в napi_add_finalizer.
napi_wrap
napi_status napi_wrap(napi_env env,
napi_value js_object,
void* native_object,
napi_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); -
[in] env: Среда, в которой вызывается API. -
[in] js_object: Объект JavaScript, который будет обёрткой для нативного объекта. -
[in] native_object: Нативный экземпляр, который будет обернут в объект JavaScript. -
[in] finalize_cb: Необязательный нативный обратный вызов, который можно использовать для освобождения нативного экземпляра, когда объект JavaScript готов к сбору мусора.napi_finalizeсодержит более подробную информацию. -
[in] finalize_hint: Необязательный контекстуальный подсказка, которая передаётся обратному вызову finalize. -
[out] result: Необязательная ссылка на обернутый объект.
Возвращает napi_ok, если API выполнилось успешно.
Оборачивает нативный экземпляр в объект JavaScript. Нативный экземпляр можно получить позже с помощью napi_unwrap().
Когда код JavaScript вызывает конструктор класса, определённого с помощью napi_define_class(), вызывается napi_callback для конструктора. После построения экземпляра нативного класса обратный вызов должен вызвать napi_wrap(), чтобы обернуть только что созданный экземпляр в уже созданный объект JavaScript, являющийся параметром this обратного вызова конструктора. (Этот this объект был создан из prototype функции-конструктора, поэтому он уже содержит определения всех свойств и методов экземпляра.)
Обычно при обёртке экземпляра класса должен быть предоставлен обратный вызов finalize, который просто удаляет нативный экземпляр, полученный в качестве аргумента data обратного вызова finalize.
Необязательная возвращаемая ссылка изначально является слабой ссылкой, то есть имеет счётчик ссылок 0. Обычно этот счётчик ссылок временно увеличивается во время асинхронных операций, которые требуют, чтобы экземпляр оставался действительным.
Предупреждение: необязательная возвращаемая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова finalize. Если она удалена до этого момента, обратный вызов finalize может никогда не быть вызван. Поэтому при получении ссылки также требуется обратный вызов finalize, чтобы обеспечить правильное удаление ссылки.
Вызов napi_wrap() второй раз для объекта вернёт ошибку. Чтобы связать другой нативный экземпляр с объектом, сначала используйте napi_remove_wrap().
napi_unwrap
napi_status napi_unwrap(napi_env env,
napi_value js_object,
void** result); -
[in] env: Среда, в которой вызывается API. -
[in] js_object: Объект, связанный с нативным экземпляром. -
[out] result: Указатель на обернутый нативный экземпляр.
Возвращает napi_ok, если API выполнилось успешно.
Возвращает нативный экземпляр, ранее обернутый в объект JavaScript с помощью napi_wrap().
Когда код JavaScript вызывает метод или аксессор свойства класса, вызывается соответствующий napi_callback. Если обратный вызов предназначен для метода или аксессора экземпляра, то параметр this обратного вызова — это объект-обёртка; обернутый экземпляр C++, являющийся целью вызова, можно получить, вызвав napi_unwrap() на объекте-обёртке.
napi_remove_wrap
napi_status napi_remove_wrap(napi_env env,
napi_value js_object,
void** result); -
[in] env: Среда, в которой вызывается API. -
[in] js_object: Объект, связанный с нативным экземпляром. -
[out] result: Указатель на обернутый нативный экземпляр.
Возвращает napi_ok, если API выполнилось успешно.
Возвращает нативное экземпляр, который ранее был обернут в JavaScript-объект js_object с помощью napi_wrap() и удаляет обёртку. Если с обёрнутым объектом был связан обратный вызов finalize, он больше не будет вызываться, когда JavaScript-объект станет мусором.
napi_type_tag_object
napi_status napi_type_tag_object(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, который нужно пометить. -
[in] type_tag: Тег, которым нужно пометить объект.
Возвращает napi_ok при успешном выполнении API.
Связывает значение указателя type_tag с JavaScript-объектом. napi_check_object_type_tag() затем можно использовать для сравнения тега, прикреплённого к объекту, с тегом, принадлежащим дополнению, чтобы убедиться, что объект имеет правильный тип.
Если у объекта уже есть связанный тег типа, этот API вернёт napi_invalid_arg.
napi_check_object_type_tag
napi_status napi_check_object_type_tag(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag,
bool* result); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, тег типа которого нужно проверить. -
[in] type_tag: Тег для сравнения с найденным тегом объекта. -
[out] result: Соответствие заданного тега типа тегу типа объекта.falseтакже возвращается, если на объекте не был найден тег типа.
Возвращает napi_ok при успешном выполнении API.
Сравнивает указатель, переданный как type_tag с любым, который можно найти на js_object. Если на js_object не найден тег или если тег найден, но не совпадает с type_tag, то result устанавливается в значение false. Если тег найден и совпадает с type_tag, то result устанавливается в значение true.
napi_add_finalizer
napi_status napi_add_finalizer(napi_env env,
napi_value js_object,
void* native_object,
napi_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, к которому будет прикреплены данные. -
[in] native_object: Нативные данные, которые будут прикреплены к JavaScript-объекту. -
[in] finalize_cb: Нативный обратный вызов, который будет использован для освобождения нативных данных, когда JavaScript-объект готов к сборке мусора.napi_finalizeсодержит более подробные сведения. -
[in] finalize_hint: Необязательная контекстная подсказка, которая передается обратному вызову finalize. -
[out] result: Необязательная ссылка на JavaScript-объект.
Возвращает napi_ok при успешном выполнении API.
Добавляет обратный вызов napi_finalize, который будет вызван, когда JavaScript-объект в js_object готов к сборке мусора. Этот API похож на napi_wrap(), за исключением:
- нативные данные нельзя получить позже с помощью
napi_unwrap(), - их также нельзя удалить позже с помощью
napi_remove_wrap(), и - API можно вызывать несколько раз с разными данными, чтобы прикрепить каждый из них к JavaScript-объекту, и
- объект, обработанный API, может быть использован с
napi_wrap().
Внимание: Необязательная возвращаемая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова finalize. Если она удалена до этого, то обратный вызов finalize может никогда не быть вызван. Поэтому при получении ссылки также требуется обратный вызов finalize для правильной утилизации ссылки.
Простые асинхронные операции
Модули дополнений часто нуждаются в использовании асинхронных помощников из libuv в рамках своей реализации. Это позволяет им планировать работу для асинхронного выполнения, чтобы их методы могли возвращаться до завершения работы. Это позволяет избежать блокировки общей работы приложения Node.js.
N-API предоставляет стабильный интерфейс ABI для этих вспомогательных функций, охватывающий наиболее распространённые случаи использования асинхронных операций.
N-API определяет структуру napi_async_work, которая используется для управления асинхронными рабочими процессами. Экземпляры создаются/удаляются с помощью napi_create_async_work и napi_delete_async_work.
Обратные вызовы execute и complete являются функциями, которые будут вызваны, когда исполнитель готов к выполнению и когда он завершит свою задачу, соответственно.
Функция execute должна избегать выполнения любых вызовов N-API, которые могут привести к выполнению JavaScript или взаимодействию с JavaScript-объектами. Чаще всего любой код, которому необходимо выполнить вызовы N-API, должен быть выполнен в обратном вызове complete вместо этого. Избегайте использования параметра napi_env в обратном вызове execute, так как это, скорее всего, приведёт к выполнению JavaScript.
Эти функции реализуют следующие интерфейсы:
typedef void (*napi_async_execute_callback)(napi_env env,
void* data);
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); При вызове этих методов параметр data будет содержать предоставленные дополнением данные void*, переданные в вызов napi_create_async_work.
После создания асинхронный рабочий процесс может быть помещён в очередь для выполнения с помощью функции napi_queue_async_work:
napi_status napi_queue_async_work(napi_env env,
napi_async_work work); napi_cancel_async_work можно использовать, если необходимо отменить работу до начала её выполнения.
После вызова napi_cancel_async_work обратный вызов complete будет вызван со значением статуса napi_cancelled. Работа не должна быть удалена до вызова обратного вызова complete, даже если она была отменена.
napi_create_async_work
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
napi_async_work* result); -
[in] env: Окружение, в котором вызывается API. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан в возможныеasync_hooksinitобработчики. -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемый для диагностической информации, предоставляемой APIasync_hooks. -
[in] execute: Встроенная функция, которая должна вызываться для выполнения логики асинхронно. Эта функция вызывается из потока пула рабочих процессов и может выполняться параллельно с основным потоком событий. -
[in] complete: Встроенная функция, которая будет вызвана, когда асинхронная логика завершена или отменена. Эта функция вызывается из основного потока событий.napi_async_complete_callbackсодержит более подробную информацию. -
[in] data: Контекст данных, предоставленный пользователем. Он будет передан обратно в функции execute и complete. -
[out] result:napi_async_work*— дескриптор вновь созданной асинхронной работы.
Возвращает napi_ok в случае успеха API.
Этот API выделяет объект работы, используемый для асинхронного выполнения логики. Он должен быть освобожден с помощью napi_delete_async_work, когда работа больше не требуется.
async_resource_name должен быть строкой с нуль-терминацией, закодированной в UTF-8.
Идентификатор async_resource_name предоставляется пользователем и должен отражать тип выполняемой асинхронной работы. Также рекомендуется использовать именование с префиксами, например, с включением имени модуля. Для получения дополнительной информации см. async_hooks документацию.
napi_delete_async_work
napi_status napi_delete_async_work(napi_env env,
napi_async_work work); -
[in] env: Окружение, в котором вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API освобождает ранее выделенный объект работы.
Этот API может быть вызван даже при наличии ожидающего JavaScript-исключения.
napi_queue_async_work
napi_status napi_queue_async_work(napi_env env,
napi_async_work work); -
[in] env: Окружение, в котором вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API запрашивает планирование ранее выделенной работы для выполнения. После успешного возврата этот API не должен вызываться снова с тем же элементом napi_async_work, в противном случае результат будет неопределенным.
napi_cancel_async_work
napi_status napi_cancel_async_work(napi_env env,
napi_async_work work); -
[in] env: Окружение, в котором вызывается API. -
[in] work: Дескриптор, возвращенный вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API отменяет запланированную работу, если она ещё не начата. Если она уже начала выполняться, её нельзя отменить, и возвращается napi_generic_failure. В случае успеха обратный вызов complete вызывается со значением статуса napi_cancelled. Работа не должна быть удалена до вызова обратного вызова complete, даже если она была успешно отменена.
Этот API может быть вызван даже при наличии ожидающего JavaScript-исключения.
Настраиваемые асинхронные операции
Простые асинхронные API работы могут не подойти для всех сценариев. При использовании других асинхронных механизмов следующие API необходимы для обеспечения правильного отслеживания асинхронной операции средой выполнения.
napi_async_init
napi_status napi_async_init(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_context* result) -
[in] env: Окружение, в котором вызывается API. -
[in] async_resource: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. Для сохранения совместимости ABI с предыдущими версиями передачаNULLдляasync_resourceне вызовет ошибку, однако это приведёт к неправильной работе асинхронных хуков для созданного napi_async_context. Возможные проблемы включают потерю асинхронного контекста при использовании API AsyncLocalStorage. -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемого для диагностической информации, экспонируемой APIasync_hooks. -
[out] result: Инициализированный асинхронный контекст.
Возвращает napi_ok в случае успешного выполнения API.
napi_async_destroy
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context); -
[in] env: Окружение, в котором вызывается API. -
[in] async_context: Асинхронный контекст, подлежащий уничтожению.
Возвращает napi_ok в случае успешного выполнения API.
Этот API может быть вызван даже при наличии ожидающей обработки исключения JavaScript.
napi_make_callback
NAPI_EXTERN napi_status napi_make_callback(napi_env env,
napi_async_context async_context,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] async_context: Контекст асинхронной операции, вызывающей обратный вызов. Обычно это значение, полученное ранее изnapi_async_init. ОднакоNULLтакже разрешено, что указывает на использование текущего асинхронного контекста (если таковой имеется) для обратного вызова. -
[in] recv: Объектthis, переданный вызываемой функции. -
[in] func:napi_value, представляющий функцию JavaScript, подлежащую вызову. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив значений JavaScript какnapi_value, представляющих аргументы функции. -
[out] result:napi_value, представляющий возвращаемый объект JavaScript.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать объект JavaScript-функции из расширения нативного кода. Этот API похож на napi_call_function. Однако он используется для вызова из нативного кода в JavaScript после возврата из асинхронной операции (когда на стеке нет другого скрипта). Это достаточно простой обертка над node::MakeCallback.
Обратите внимание, что использование napi_make_callback не обязательно внутри napi_async_complete_callback; в этом случае асинхронный контекст обратного вызова уже настроен, поэтому прямой вызов napi_call_function является достаточным и подходящим. Функция napi_make_callback может потребоваться при реализации пользовательского асинхронного поведения, не использующего napi_create_async_work.
Любые process.nextTick или 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) -
[in] env: Окружение, в котором вызывается API. -
[in] resource_object: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. -
[in] context: Контекст асинхронной операции, вызывающей обратный вызов. Должно быть значение, полученное ранее изnapi_async_init. -
[out] result: Созданный контекст.
В некоторых случаях (например, при разрешении промисов) необходимо иметь эквивалент контекста, связанного с обратным вызовом, при выполнении определённых вызовов N-API. Если на стеке нет другого скрипта, функции napi_open_callback_scope и napi_close_callback_scope могут использоваться для открытия/закрытия необходимого контекста.
napi_close_callback_scope
NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
napi_callback_scope scope) -
[in] env: Окружение, в котором вызывается API. -
[in] scope: Закрываемый контекст.
Этот API может быть вызван даже при наличии ожидающей обработки исключения JavaScript.
Управление версиями
napi_get_node_version
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
const char* release;
} napi_node_version;
napi_status napi_get_node_version(napi_env env,
const napi_node_version** version); -
[in] env: Окружение, в котором вызывается API. -
[out] version: Указатель на информацию о версии самого Node.js.
Возвращает napi_ok в случае успешного выполнения API.
Эта функция заполняет структуру version значениями основной, дополнительной и исправленной версии Node.js, которая в настоящее время запущена, и поле release значением process.release.name.
Возвращаемый буфер статически выделен и не требует освобождения.
napi_get_version
napi_status napi_get_version(napi_env env,
uint32_t* result); -
[in] env: Окружение, в котором вызывается API. -
[out] result: Наивысшая поддерживаемая версия N-API.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает наивысшую поддерживаемую версию N-API, используемую исполняемой средой Node.js. N-API планируется развивать таким образом, чтобы новые версии Node.js могли поддерживать дополнительные функции API. Для того чтобы дополнение могло использовать новую функцию при запуске с версиями Node.js, которые ее поддерживают, обеспечивая при этом обратную совместимость с версиями, которые ее не поддерживают:
- Вызовите
napi_get_version(), чтобы определить, доступен ли API. - Если доступен, динамически загрузите указатель на функцию, используя
uv_dlsym(). - Используйте динамически загруженный указатель для вызова функции.
- Если функция недоступна, предоставьте альтернативную реализацию, которая не использует эту функцию.
Управление памятью
napi_adjust_external_memory
NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env,
int64_t change_in_bytes,
int64_t* result); -
[in] env: Окружение, в котором вызывается API. -
[in] change_in_bytes: Изменение во внешней памяти, которую поддерживают JavaScript-объекты. -
[out] result: Измененное значение.
Возвращает napi_ok в случае успешного выполнения API.
Эта функция предоставляет V8 информацию о количестве внешней памяти, поддерживаемой JavaScript-объектами (например, JavaScript-объект, указывающий на свою память, выделенную с помощью нативного модуля). Регистрация внешней памяти вызовет сборку мусора глобального уровня чаще, чем в противном случае.
Обещания
N-API предоставляет средства для создания Promise объектов, как описано в разделе 25.4 спецификации ECMA. Он реализует обещания как пару объектов. Когда обещание создаётся с помощью napi_create_promise(), создаётся объект "отложенного" и возвращается вместе с Promise. Объект отложенного выполнения связан с созданным Promise и является единственным способом разрешить или отклонить Promise с помощью napi_resolve_deferred() или napi_reject_deferred() . Объект отложенного выполнения, созданный napi_create_promise() , освобождается napi_resolve_deferred() или napi_reject_deferred(). Объект Promise может быть возвращён JavaScript, где он может быть использован в обычном порядке.
Например, чтобы создать обещание и передать его асинхронному рабочему процессу:
napi_deferred deferred; napi_value promise; napi_status status; // Create the promise. status = napi_create_promise(env, &deferred, &promise); if (status != napi_ok) return NULL; // Pass the deferred to a function that performs an asynchronous action. do_something_asynchronous(deferred); // Return the promise to JS return promise;
Вышеприведённая функция do_something_asynchronous() выполнит свои асинхронные действия, а затем разрешит или отклонит отложенное, тем самым завершив обещание и освободив отложенное:
napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (asynchronous_action_succeeded) {
status = napi_resolve_deferred(env, deferred, undefined);
} else {
status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;
// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL; napi_create_promise
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise); -
[in] env: Окружение, в котором вызывается API. -
[out] deferred: Новый созданный объект отложенного выполнения, который позже может быть переданnapi_resolve_deferred()илиnapi_reject_deferred()для разрешения соответственно отклонения связанного с ним обещания. -
[out] promise: JavaScript-обещание, связанное с объектом отложенного выполнения.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт объект отложенного выполнения и JavaScript-обещание.
napi_resolve_deferred
napi_status napi_resolve_deferred(napi_env env,
napi_deferred deferred,
napi_value resolution); -
[in] env: Окружение, в котором вызывается API. -
[in] deferred: Объект отложенного выполнения, ассоциированное обещание которого нужно разрешить. -
[in] resolution: Значение, с помощью которого необходимо разрешить обещание.
Этот API разрешает JavaScript-обещание с помощью объекта отложенного выполнения, с которым оно связано. Таким образом, он может быть использован только для разрешения JavaScript-обещаний, для которых доступен соответствующий объект отложенного выполнения. Это фактически означает, что обещание должно было быть создано с помощью napi_create_promise(), а объект отложенного выполнения, возвращённый из этого вызова, должен был быть сохранён для передачи в этот API.
Объект отложенного выполнения освобождается при успешном завершении.
napi_reject_deferred
napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection); -
[in] env: Окружение, в котором вызывается API. -
[in] deferred: Объект отложенного выполнения, ассоциированное обещание которого нужно отклонить. -
[in] rejection: Значение, с помощью которого необходимо отклонить обещание.
Этот API отклоняет JavaScript-обещание с помощью объекта отложенного выполнения, с которым оно связано. Таким образом, он может быть использован только для отклонения JavaScript-обещаний, для которых доступен соответствующий объект отложенного выполнения. Это фактически означает, что обещание должно было быть создано с помощью napi_create_promise() , а объект отложенного выполнения, возвращённый из этого вызова, должен был быть сохранён для передачи в этот API.
Отложенный объект освобождается при успешном выполнении.
napi_is_promise
napi_status napi_is_promise(napi_env env,
napi_value value,
bool* is_promise); -
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение для проверки. -
[out] is_promise: Флаг, указывающий, является лиpromiseобъектом родного promise (то есть, объектом promise, созданным основой движка).
Выполнение скрипта
N-API предоставляет API для выполнения строки JavaScript-кода с помощью основного движка JavaScript.
napi_run_script
NAPI_EXTERN napi_status napi_run_script(napi_env env,
napi_value script,
napi_value* result); -
[in] env: Окружение, в котором вызывается API. -
[in] script: Строка JavaScript-кода, содержащая скрипт для выполнения. -
[out] result: Значение, полученное в результате выполнения скрипта.
Эта функция выполняет строку JavaScript-кода и возвращает её результат с учетом следующих особенностей:
- В отличие от
eval, эта функция не позволяет скрипту получить доступ к текущей лексической области видимости, а значит, и к области видимости модуля, что означает, что псевдоглобальные переменные, такие какrequire, недоступны. - Скрипт может получить доступ к глобальной области видимости. Объявления функций и
varв скрипте будут добавлены в объектglobal. Объявления переменных с использованиемletиconstбудут доступны глобально, но не будут добавлены в объектglobal. - Значение
thisвнутри скрипта равноglobal.
Цикл событий libuv
N-API предоставляет функцию для получения текущего цикла событий, связанного с определённым napi_env.
napi_get_uv_event_loop
NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env,
struct uv_loop_s** loop); -
[in] env: Окружение, в котором вызывается API. -
[out] loop: Текущая инстанция цикла libuv.
Асинхронные потокобезопасные вызовы функций
Функции JavaScript обычно могут вызываться только из основного потока нативного плагина. Если плагин создаёт дополнительные потоки, то функции N-API, требующие napi_env, napi_value, или napi_ref, не должны вызываться из этих потоков.
Когда плагин имеет дополнительные потоки, и функции JavaScript необходимо вызывать на основе обработки, выполненной этими потоками, эти потоки должны взаимодействовать с основным потоком плагина, чтобы основной поток мог вызвать функцию JavaScript от их имени. Потокобезопасные API предоставляют лёгкий способ для этого.
Эти API предоставляют тип napi_threadsafe_function а также API для создания, уничтожения и вызова объектов этого типа. napi_value создаёт постоянную ссылку на 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.
Фактический вызов в 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(), так как N-API выполняет call_js_cb в контексте, подходящем для обратных вызовов.
Счётчик ссылок для функций с безопасностью потоков
Потоки могут добавляться и удаляться из объекта napi_threadsafe_function в течение его существования. Таким образом, помимо указания начального количества потоков при создании, можно вызвать napi_acquire_threadsafe_function, чтобы указать, что новый поток начнёт использовать функцию с безопасностью потоков. Аналогично, можно вызвать napi_release_threadsafe_function, чтобы указать, что существующий поток перестанет использовать функцию с безопасностью потоков.
Объекты napi_threadsafe_function уничтожаются, когда каждый поток, использующий объект, вызвал napi_release_threadsafe_function() или получил возвращаемый статус napi_closing в ответ на вызов napi_call_threadsafe_function. Очередь опустошается перед уничтожением napi_threadsafe_function. napi_release_threadsafe_function() должен быть последним API-вызовом в совокупности с данным napi_threadsafe_function, поскольку после завершения вызова нет гарантии, что napi_threadsafe_function всё ещё выделен. По той же причине не используйте функцию с безопасностью потоков после получения возвращаемого значения napi_closing в ответ на вызов napi_call_threadsafe_function. Данные, связанные с napi_threadsafe_function могут быть освобождены в его обратном вызове napi_finalize, который был передан в napi_create_threadsafe_function(). Параметр initial_thread_count вызова napi_create_threadsafe_function отмечает начальное количество приобретений функций с безопасностью потоков, вместо вызова napi_acquire_threadsafe_function несколько раз при создании.
Как только количество потоков, использующих napi_threadsafe_function, достигнет нуля, дополнительные потоки не смогут начать использовать его, вызывая napi_acquire_threadsafe_function(). На самом деле, все последующие API-вызовы, связанные с ним, кроме napi_release_threadsafe_function(), вернут значение ошибки napi_closing.
Функцию с безопасностью потоков можно «прервать», присвоив значение napi_tsfn_abort параметру napi_release_threadsafe_function(). Это заставит все последующие API-вызовы, связанные с функцией с безопасностью потоков, кроме napi_release_threadsafe_function(), вернуть napi_closing, даже прежде чем счётчик ссылок достигнет нуля. В частности, napi_call_threadsafe_function() вернёт napi_closing, тем самым сообщив потокам, что асинхронные вызовы функции с безопасностью потоков больше невозможны. Это может быть использовано в качестве критерия для завершения потока. После получения возвращаемого значения napi_closing от napi_call_threadsafe_function() поток больше не должен использовать функцию с безопасностью потоков, так как она больше не гарантированно выделена.
Решение о продолжении работы процесса
Аналогично обработчикам libuv, функции с безопасностью потоков могут быть «ссылочными» и «нессылочными». «Ссылочная» функция с безопасностью потоков заставит цикл событий в потоке, в котором она была создана, оставаться активным до уничтожения функции с безопасностью потоков. В противоположность этому, «нессылочная» функция с безопасностью потоков не будет препятствовать выходу цикла событий. API napi_ref_threadsafe_function и napi_unref_threadsafe_function существуют для этой цели.
Ни napi_unref_threadsafe_function не отмечает функции с безопасностью потоков как подлежащие уничтожению, ни napi_ref_threadsafe_function не предотвращает их уничтожение.
napi_create_threadsafe_function
NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result); -
[in] env: Среда, в которой вызывается API. -
[in] func: Необязательная JavaScript-функция, вызываемая с другого потока. Она должна быть предоставлена, еслиNULLпередаётся вcall_js_cb. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. -
[in] async_resource_name: Строка JavaScript, предоставляющая идентификатор типа ресурса для диагностической информации, экспонируемой APIasync_hooks. -
[in] max_queue_size: Максимальный размер очереди.0для отсутствия ограничения. -
[in] initial_thread_count: Начальное число аквизиций, т.е. начальное число потоков, включая основной поток, которые будут использовать эту функцию. -
[in] thread_finalize_data: Необязательные данные, передаваемые вthread_finalize_cb. -
[in] thread_finalize_cb: Необязательная функция, вызываемая при уничтоженииnapi_threadsafe_function. -
[in] context: Необязательные данные, прикрепляемые к результатуnapi_threadsafe_function. -
[in] call_js_cb: Необязательный обратный вызов, который вызывает JavaScript-функцию в ответ на вызов в другом потоке. Этот обратный вызов будет вызван в основном потоке. Если не указан, JavaScript-функция будет вызвана без параметров и со значениемundefinedв качестве своегоthisзначения.napi_threadsafe_function_call_jsсодержит дополнительные сведения. -
[out] result: Асинхронная потокобезопасная JavaScript-функция.
napi_get_threadsafe_function_context
NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
void** result); -
[in] func: Потокобезопасная функция, для которой необходимо получить контекст. -
[out] result: Место для хранения контекста.
Этот API может быть вызван из любого потока, который использует func.
napi_call_threadsafe_function
NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking); -
[in] func: Асинхронная потокобезопасная JavaScript-функция для вызова. -
[in] data: Данные для отправки в JavaScript через обратный вызовcall_js_cb, предоставленный во время создания потокобезопасной JavaScript-функции. -
[in] is_blocking: Флаг, значение которого может бытьnapi_tsfn_blockingдля указания, что вызов должен заблокироваться, если очередь заполнена, илиnapi_tsfn_nonblockingдля указания, что вызов должен возвратиться немедленно со статусомnapi_queue_fullпри заполнении очереди.
Этот API вернёт napi_closing если napi_release_threadsafe_function() был вызван со значением abort установленным в napi_tsfn_abort из любого потока. Значение добавляется в очередь только если API возвращает napi_ok.
Этот API может быть вызван из любого потока, который использует func.
napi_acquire_threadsafe_function
NAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func);
-
[in] func: Асинхронная потокобезопасная JavaScript-функция, с которой нужно начать работу.
Поток должен вызвать этот API перед передачей func в любые другие API потокобезопасности, чтобы указать, что он будет использовать func. Это предотвращает уничтожение func при остановке всех других потоков.
Этот API может быть вызван из любого потока, который начнёт использовать func.
napi_release_threadsafe_function
NAPI_EXTERN napi_status
napi_release_threadsafe_function(napi_threadsafe_function func,
napi_threadsafe_function_release_mode mode); -
[in] func: Асинхронная потокобезопасная JavaScript-функция, для которой необходимо уменьшить счётчик ссылок. -
[in] mode: Флаг, значение которого может бытьnapi_tsfn_releaseдля указания, что текущий поток больше не будет делать вызовы к потокобезопасной функции, илиnapi_tsfn_abortдля указания, что помимо текущего потока никакой другой поток не должен делать дальнейшие вызовы к потокобезопасной функции. Если установленоnapi_tsfn_abort, дальнейшие вызовыnapi_call_threadsafe_function()вернутnapi_closing, и никаких дальнейших значений не будет помещено в очередь.
Поток должен вызвать этот API, когда он перестаёт использовать func. Передача func в любые потокобезопасные API после вызова этого API приведёт к неопределённым результатам, так как func может быть уничтожена.
Этот API может быть вызван из любого потока, который перестанет использовать func.
napi_ref_threadsafe_function
NAPI_EXTERN napi_status napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
-
[in] env: Среда, в которой вызывается API. -
[in] func: Потокобезопасная функция для ссылки.
Этот API используется для указания, что цикл событий, работающий в главном потоке, не должен завершаться, пока func не будет уничтожена. Подобно uv_ref, он также идемпотентен.
Ни napi_unref_threadsafe_function не помечает функции потокобезопасности как уничтожаемые, ни napi_ref_threadsafe_function не предотвращает их уничтожение. napi_acquire_threadsafe_function и napi_release_threadsafe_function предназначены для этой цели.
Этот API может быть вызван только из основного потока.
napi_unref_threadsafe_function
NAPI_EXTERN napi_status napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
-
[in] env: Среда, в которой вызывается API. -
[in] func: Функция потокобезопасности, которую нужно аннулировать.
Этот API используется для указания того, что цикл событий, работающий в основном потоке, может завершиться до того, как func будет уничтожен. Аналогично uv_unref, он также идемпотентен.
Этот API может быть вызван только из основного потока.
Вспомогательные функции
node_api_get_module_file_name
NAPI_EXTERN napi_status node_api_get_module_file_name(napi_env env, const char** result);
-
[in] env: Среда, в которой вызывается API. -
[out] result: URL, содержащий абсолютный путь к расположению, из которого был загружен плагин. Для файла на локальной файловой системе он будет начинаться сfile://. Строка имеет нуль-терминатор и принадлежитenv, поэтому ее нельзя изменять или освобождать.
result может быть пустой строкой, если процесс загрузки плагина не смог определить имя файла плагина во время загрузки.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v12.x/docs/api/n-api.html