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