Node-API
Node-API (ранее N-API) — это API для создания нативных плагинов. Оно независимо от базового движка JavaScript (например, V8) и поддерживается в рамках самого Node.js. Это API будет стабильным с точки зрения интерфейса бинарных данных (ABI) между версиями Node.js. Оно предназначено для изоляции плагинов от изменений в базовом движке JavaScript и позволяет модулям, скомпилированным для одной основной версии, работать в более поздних основных версиях Node.js без перекомпиляции. В руководстве ABI Stability приведено более подробное объяснение.
Плагины строятся/упаковываются с использованием тех же подходов/инструментов, что и в разделе Плагины на 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"); copy
napi_status status;
napi_value object, string;
status = napi_create_object(env, &object);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_create_string_utf8(env, "bar", NAPI_AUTO_LENGTH, &string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
}
status = napi_set_named_property(env, object, "foo", string);
if (status != napi_ok) {
napi_throw_error(env, ...);
return;
} copy В результате плагин использует только экспортируемые C API. В результате он по-прежнему получает преимущества стабильности ABI, предоставляемой C API.
При использовании node-addon-api вместо C API, начните с документации API по ссылке docs для node-addon-api.
В Ресурсе Node-API представлен отличный ориентир и советы для разработчиков, только начинающих работу с Node-API и node-addon-api. Дополнительные медиаресурсы можно найти на странице Node-API Media.
Последствия стабильности ABI
Несмотря на то, что Node-API гарантирует стабильность ABI, другие части Node.js этого не гарантируют, и любые внешние библиотеки, используемые плагином, могут тоже не гарантировать. В частности, ни один из следующих API не гарантирует стабильность ABI между основными версиями:
-
C++ API Node.js, доступные через любой из
#include <node.h> #include <node_buffer.h> #include <node_version.h> #include <node_object_wrap.h> copy
-
API libuv, которые также включены в Node.js и доступны через
#include <uv.h> copy
-
API V8, доступные через
#include <v8.h> copy
Таким образом, для того, чтобы плагин оставался совместимым с ABI между основными версиями Node.js, он должен использовать Node-API исключительно, ограничивая себя использованием
#include <node_api.h> copy
и проверяя для всех внешних библиотек, которые он использует, что внешняя библиотека гарантирует стабильность ABI, подобную Node-API.
Компиляция
В отличие от модулей, написанных на JavaScript, разработка и развертывание нативных плагинов Node.js с использованием Node-API требует дополнительного набора инструментов. Помимо базовых инструментов, необходимых для разработки для Node.js, разработчику нативных плагинов нужен набор инструментов, способный компилировать код C и C++ в двоичный файл. Кроме того, в зависимости от того, как развернут нативный плагин, пользователю нативного плагина также понадобится установленный набор инструментов C/C++.
Для разработчиков Linux необходимые пакеты инструментов C/C++ легко доступны. GCC широко используется в сообществе Node.js для компиляции и тестирования на различных платформах. Для многих разработчиков инфраструктура компилятора LLVM также является хорошим выбором.
Для разработчиков macOS Xcode предоставляет все необходимые инструменты компилятора. Однако нет необходимости устанавливать весь IDE Xcode. Следующая команда устанавливает необходимый набор инструментов:
xcode-select --install copy
Для разработчиков Windows Visual Studio предоставляет все необходимые инструменты компилятора. Однако нет необходимости устанавливать весь IDE Visual Studio. Следующая команда устанавливает необходимый набор инструментов:
npm install --global windows-build-tools copy
В разделах ниже описаны дополнительные инструменты, доступные для разработки и развертывания нативных плагинов Node.js.
Инструменты сборки
Для успешной установки нативного плагина оба перечисленных здесь инструмента требуют, чтобы пользователи плагина имели установленный набор инструментов C/C++.
node-gyp
node-gyp — это система сборки, основанная на gyp-next, форке Google'овского инструмента GYP, и поставляется вместе с npm. Для работы GYP, и соответственно node-gyp, требуется установленный Python.
Исторически node-gyp был инструментом выбора для сборки нативных плагинов. Он имеет широкое распространение и документацию. Однако некоторые разработчики столкнулись с ограничениями в node-gyp.
CMake.js
CMake.js — это альтернативная система сборки, основанная на CMake.
CMake.js — хороший выбор для проектов, которые уже используют CMake, или для разработчиков, сталкивающихся с ограничениями node-gyp. build_with_cmake — пример проекта нативного плагина, использующего CMake.
Загрузка предварительно скомпилированных бинарных файлов
Эти три инструмента позволяют разработчикам и администраторам нативных плагинов создавать и загружать двоичные файлы на публичные или частные серверы. Эти инструменты обычно интегрируются с системами CI/CD сборки, такими как Travis CI и AppVeyor, для компиляции и загрузки бинарных файлов для различных платформ и архитектур. Затем эти двоичные файлы доступны для загрузки пользователям, которым не требуется устанавливать набор инструментов C/C++.
node-pre-gyp
node-pre-gyp — это инструмент, основанный на node-gyp, который добавляет возможность загружать двоичные файлы на сервер по выбору разработчика. node-pre-gyp имеет особенно хорошую поддержку загрузки бинарных файлов на Amazon S3.
prebuild
prebuild — это инструмент, поддерживающий сборку с использованием node-gyp или CMake.js. В отличие от node-pre-gyp, который поддерживает различные серверы, prebuild загружает двоичные файлы только в выпуски GitHub. prebuild — хороший выбор для проектов GitHub, использующих CMake.js.
prebuildify
prebuildify — это инструмент, основанный на node-gyp. Преимущество prebuildify заключается в том, что скомпилированные двоичные файлы встроены в нативный плагин при загрузке на npm. Бинарные файлы загружаются с npm и сразу доступны пользователю модуля при установке нативного плагина.
Использование
Для использования функций Node-API включите файл node_api.h, который расположен в каталоге src в дереве разработки Node:
#include <node_api.h> copy
Это позволит использовать по умолчанию NAPI_VERSION для данной версии Node.js. Для обеспечения совместимости с конкретными версиями Node-API версия может быть указана явно при включении заголовка:
#define NAPI_VERSION 3 #include <node_api.h> copy
Это ограничивает поверхность Node-API только функциональностью, которая была доступна в указанных (и более ранних) версиях.
Часть поверхности Node-API является экспериментальной и требует явного включения:
#define NAPI_EXPERIMENTAL #include <node_api.h> copy
В этом случае вся поверхность API, включая любые экспериментальные API, будет доступна коду модуля.
Иногда вводятся экспериментальные функции, которые влияют на уже выпущенные и стабильные API. Эти функции можно отключить с помощью опции исключения:
#define NAPI_EXPERIMENTAL #define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT #include <node_api.h> copy
где <FEATURE_NAME> — имя экспериментальной функции, которая влияет на экспериментальные и стабильные API.
Матрица версий Node-API
До версии 9 версии Node-API были аддитивными и версиями, независимыми от Node.js. Это означало, что любая версия являлась расширением предыдущей версии, содержащей все API предыдущей версии с некоторыми дополнениями. Каждая версия Node.js поддерживала только одну версию Node-API. Например, v18.15.0 поддерживает только версию Node-API 8. Стабильность ABI достигалась, потому что 8 была строгим супермножеством всех предыдущих версий.
Начиная с версии 9, хотя версии Node-API по-прежнему имеют независимые версии, дополнение, работающее с версией Node-API 9, может потребовать обновлений кода для работы с версией Node-API 10. Тем не менее, стабильность ABI поддерживается, потому что версии Node.js, которые поддерживают версии Node-API выше 8, будут поддерживать все версии между 8 и самой высокой поддерживаемой версией и по умолчанию будут предоставлять API версии 8, если дополнение не выберет более высокую версию Node-API. Этот подход обеспечивает гибкость для лучшей оптимизации существующих функций Node-API, сохраняя при этом стабильность ABI. Существующие дополнения могут продолжать работать без перекомпиляции, используя более раннюю версию Node-API. Если дополнению необходимы функции из более новой версии Node-API, для использования этих новых функций потребуются изменения в существующем коде и перекомпиляция.
В версиях Node.js, которые поддерживают Node-API версии 9 и выше, определение NAPI_VERSION=X и использование существующих макросов инициализации дополнения позволят закрепить запрошенную версию Node-API, которая будет использоваться во время выполнения, в дополнении. Если NAPI_VERSION не задано, оно будет по умолчанию 8.
Эта таблица может быть неактуальной в более старых потоках, самая актуальная информация находится в последней документации API: Матрица версий Node-API
| Версия Node-API | Поддерживается в |
|---|---|
| 9 | v18.17.0+, 20.3.0+, 21.0.0 и все последующие версии |
| 8 | v12.22.0+, v14.17.0+, v15.12.0+, 16.0.0 и все последующие версии |
| 7 | v10.23.0+, v12.19.0+, v14.12.0+, 15.0.0 и все последующие версии |
| 6 | v10.20.0+, v12.17.0+, 14.0.0 и все последующие версии |
| 5 | v10.17.0+, v12.11.0+, 13.0.0 и все последующие версии |
| 4 | v10.16.0+, v11.8.0+, 12.0.0 и все последующие версии |
| 3 | v6.14.2*, 8.11.2+, v9.11.0+*, 10.0.0 и все последующие версии |
| 2 | v8.10.0+*, v9.3.0+*, 10.0.0 и все последующие версии |
| 1 | v8.6.0+**, v9.0.0+*, 10.0.0 и все последующие версии |
* Node-API был экспериментальным.
** Node.js 8.0.0 включал Node-API как экспериментальный. Он был выпущен как Node-API версии 1, но продолжал развиваться до Node.js 8.6.0. API отличается в версиях до Node.js 8.6.0. Мы рекомендуем Node-API версии 3 или выше.
Каждая документированная API для Node-API будет иметь заголовок с именем added in:, а стабильные API будут иметь дополнительный заголовок Node-API version:. API можно напрямую использовать при использовании версии Node.js, которая поддерживает версию Node-API, показанную в Node-API version: или выше. При использовании версии Node.js, которая не поддерживает Node-API version: в списке или если Node-API 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. Для этих реализаций API, специфичные для Node.js, могут быть неприменимы.
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_ copy
// addon.c
#include "addon.h"
#define NODE_API_CALL(env, call) \
do { \
napi_status status = (call); \
if (status != napi_ok) { \
const napi_extended_error_info* error_info = NULL; \
napi_get_last_error_info((env), &error_info); \
const char* err_message = error_info->error_message; \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
/* If an exception is already pending, don't rethrow it */ \
if (!is_pending) { \
const char* message = (err_message == NULL) \
? "empty error message" \
: err_message; \
napi_throw_error((env), NULL, message); \
} \
return NULL; \
} \
} while(0)
static napi_value
DoSomethingUseful(napi_env env, napi_callback_info info) {
// Do something useful.
return NULL;
}
napi_value create_addon(napi_env env) {
napi_value result;
NODE_API_CALL(env, napi_create_object(env, &result));
napi_value exported_function;
NODE_API_CALL(env, napi_create_function(env,
"doSomethingUseful",
NAPI_AUTO_LENGTH,
DoSomethingUseful,
NULL,
&exported_function));
NODE_API_CALL(env, napi_set_named_property(env,
result,
"doSomethingUseful",
exported_function));
return result;
} copy // addon_node.c
#include <node_api.h>
#include "addon.h"
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
// This function body is expected to return a `napi_value`.
// The variables `napi_env env` and `napi_value exports` may be used within
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
return create_addon(env);
} copy API жизненного цикла окружения
Раздел 8.7 Спецификации языка ECMAScript определяет понятие «Агент» как автономную среду, в которой выполняется JavaScript-код. Процесс может запускать и завершать несколько таких агентов как одновременно, так и последовательно.
Среда Node.js соответствует ECMAScript-агенту. В основном процессе среда создаётся при запуске, а дополнительные среды могут быть созданы в отдельных потоках, чтобы служить рабочими потоками. Когда Node.js встроен в другое приложение, основной поток приложения также может многократно создавать и уничтожать среду Node.js в течение жизненного цикла процесса приложения, таким образом, каждая созданная приложением среда Node.js может, в свою очередь, в течение своего жизненного цикла создавать и уничтожать дополнительные среды как рабочие потоки.
С точки зрения нативного дополнения это означает, что предоставляемые им привязки могут вызываться многократно, из нескольких контекстов и даже одновременно из нескольких потоков.
Нативным дополнениям может потребоваться выделять глобальное состояние, которое они используют в течение жизненного цикла среды Node.js, чтобы состояние было уникальным для каждого экземпляра дополнения.
Для этого Node-API предоставляет способ связывать данные таким образом, чтобы их жизненный цикл был привязан к жизненному циклу среды Node.js.
napi_set_instance_data
napi_status napi_set_instance_data(node_api_nogc_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[in] data: Элемент данных, который необходимо сделать доступным для привязок этого экземпляра. -
[in] finalize_cb: Функция, которая вызывается при завершении работы среды. Функция получаетdata, чтобы она могла его освободить.napi_finalizeсодержит более подробную информацию. -
[in] finalize_hint: Необязательный параметр, передаваемый в обратный вызов finalize во время сбора.
Возвращает napi_ok в случае успешного выполнения API.
Эта API связывает data с текущей запущенной средой Node.js. data можно позже получить с помощью napi_get_instance_data(). Любые ранее связанные данные, установленные с помощью предыдущего вызова napi_set_instance_data(), будут перезаписаны. Если ранее вызывался finalize_cb, он не будет вызван.
napi_get_instance_data
napi_status napi_get_instance_data(node_api_nogc_env env,
void** data); copy -
[in] env: Окружение, в котором вызывается вызов Node-API. -
[out] data: Элемент данных, который был ранее связан с текущей запущенной средой Node.js вызовомnapi_set_instance_data().
Возвращает napi_ok в случае успешного выполнения API.
Эта API извлекает данные, которые были ранее связаны с текущей запущенной средой Node.js с помощью napi_set_instance_data(). Если данных нет, вызов выполнится успешно, и data будет установлено в NULL.
Основные типы данных Node-API
Node-API предоставляет следующие фундаментальные типы данных в качестве абстракций, используемых различными API. Эти API следует рассматривать как непрозрачные, инспектируемые только с помощью других вызовов Node-API.
napi_status
Целочисленный код состояния, указывающий на успех или неудачу вызова Node-API. В настоящее время поддерживаются следующие коды состояния.
typedef enum {
napi_ok,
napi_invalid_arg,
napi_object_expected,
napi_string_expected,
napi_name_expected,
napi_function_expected,
napi_number_expected,
napi_boolean_expected,
napi_array_expected,
napi_generic_failure,
napi_pending_exception,
napi_cancelled,
napi_escape_called_twice,
napi_handle_scope_mismatch,
napi_callback_scope_mismatch,
napi_queue_full,
napi_closing,
napi_bigint_expected,
napi_date_expected,
napi_arraybuffer_expected,
napi_detachable_arraybuffer_expected,
napi_would_deadlock, /* unused */
napi_no_external_buffers_allowed,
napi_cannot_run_js
} napi_status; copy Если при возврате API с неудачным статусом требуется дополнительная информация, её можно получить, вызвав napi_get_last_error_info.
napi_extended_error_info
typedef struct {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
} napi_extended_error_info; copy -
error_message: Строка UTF8, содержащая описание ошибки, нейтральное по отношению к виртуальной машине. -
engine_reserved: Зарезервировано для деталей ошибки, специфичных для виртуальной машины. В настоящее время для любой виртуальной машины это не реализовано. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. В настоящее время для любой виртуальной машины это не реализовано. -
error_code: Код состояния Node-API, породивший последнюю ошибку.
См. раздел Обработка ошибок для дополнительной информации.
napi_env
napi_env используется для представления контекста, который подлежащая реализации Node-API может использовать для сохранения состояния, специфичного для виртуальной машины. Эта структура передаётся нативные функции при их вызове, и её необходимо передавать обратно при выполнении вызовов Node-API. Конкретно, та же napi_env, которая была передана при первоначальном вызове нативной функции, должна быть передана в любые последующие вложенные вызовы Node-API. Кэширование napi_env в целях общего повторного использования и передача napi_env между экземплярами одного и того же плагина, выполняемого на различных Worker потоках, запрещено. napi_env становится недействительным при разгрузке экземпляра нативного плагина. Уведомление об этом событии доставляется с помощью обратных вызовов, предоставленных napi_add_env_cleanup_hook и napi_set_instance_data.
node_api_nogc_env
Этот вариант napi_env передаётся синхронным финализаторам (node_api_nogc_finalize). Существует подмножество Node-API, которые принимают параметр типа node_api_nogc_env в качестве своего первого аргумента. Эти API не обращаются к состоянию JavaScript-движка и поэтому безопасны для вызова из синхронных финализаторов. Передача параметра типа napi_env в эти API разрешена, однако передача параметра типа node_api_nogc_env в API, которые обращаются к состоянию JavaScript-движка, запрещена. Попытка сделать это без приведения типов приведёт к предупреждению компилятора или ошибке при компиляции плагинов с флагами, которые заставляют их выдавать предупреждения и/или ошибки при передаче неверных типов указателей в функцию. Вызов таких API из синхронного финализатора в конечном итоге приведёт к завершению приложения.
napi_value
Это непрозрачный указатель, используемый для представления JavaScript-значения.
napi_threadsafe_function
Это непрозрачный указатель, представляющий JavaScript-функцию, которую можно вызывать асинхронно из нескольких потоков с помощью napi_call_threadsafe_function().
napi_threadsafe_function_release_mode
Значение, передаваемое napi_release_threadsafe_function() для указания, должна ли функция с защитой от одновременного доступа закрываться немедленно (napi_tsfn_abort) или просто освобождаться (napi_tsfn_release) и, следовательно, быть доступной для последующего использования через napi_acquire_threadsafe_function() и napi_call_threadsafe_function().
typedef enum {
napi_tsfn_release,
napi_tsfn_abort
} napi_threadsafe_function_release_mode; copy
napi_threadsafe_function_call_mode
Значение, передаваемое napi_call_threadsafe_function() для указания, следует ли блокировать вызов, когда очередь, связанная с функцией с защитой от одновременного доступа, полна.
typedef enum {
napi_tsfn_nonblocking,
napi_tsfn_blocking
} napi_threadsafe_function_call_mode; copy Типы управления памятью Node-API
napi_handle_scope
Это абстракция, используемая для управления и изменения жизненного цикла объектов, созданных в определённом контексте. В целом, значения Node-API создаются в контексте области видимости handle. Когда нативный метод вызывается из JavaScript, существует область видимости handle по умолчанию. Если пользователь не создаёт явно новую область видимости handle, значения Node-API будут созданы в области видимости handle по умолчанию. Для любых вызовов кода за пределами выполнения нативного метода (например, во время вызова обратного вызова libuv) модуль обязан создать область видимости перед вызовом функций, которые могут привести к созданию JavaScript-значений.
Области видимости handle создаются с помощью napi_open_handle_scope и уничтожаются с помощью napi_close_handle_scope. Закрытие области видимости может указать сборщику мусора, что все napi_values, созданные в течение срока действия области видимости handle, больше не ссылаются из текущей области видимости стека.
Для получения дополнительной информации ознакомьтесь с разделом Управление жизненным циклом объектов.
napi_escapable_handle_scope
Области видимости handle с возможностью передачи — это специальный тип области видимости handle для возврата значений, созданных в определённой области видимости handle, в родительскую область видимости.
napi_ref
Это абстракция, используемая для ссылки на napi_value. Это позволяет пользователям управлять жизненным циклом JavaScript-значений, включая явное определение их минимального срока действия.
Для получения дополнительной информации ознакомьтесь с разделом Управление жизненным циклом объектов.
napi_type_tag
128-битовое значение, хранящееся в виде двух 64-битовых беззнаковых целых чисел. Оно служит в качестве UUID, с помощью которого JavaScript-объекты или externals могут быть «метчены» для обеспечения принадлежности к определённому типу. Это более надёжная проверка, чем napi_instanceof, потому что последняя может давать ложноположительные результаты, если прототип объекта был изменён. Мечение по типу наиболее полезно в сочетании с napi_wrap, поскольку оно гарантирует, что указатель, полученный из обернутого объекта, может быть безопасно приведён к нативному типу, соответствующему тегу типа, который был ранее применён к JavaScript-объекту.
typedef struct {
uint64_t lower;
uint64_t upper;
} napi_type_tag; copy
napi_async_cleanup_hook_handle
Непрозрачное значение, возвращаемое napi_add_async_cleanup_hook. Оно должно быть передано napi_remove_async_cleanup_hook, когда цепочка асинхронных событий очистки завершается.
Типы обратных вызовов Node-API
napi_callback_info
Непрозрамый тип данных, передаваемый в функцию обратного вызова. Он может использоваться для получения дополнительной информации о контексте, в котором был вызван обратный вызов.
napi_callback
Тип указателя на функцию, предоставленный пользователем, для нативных функций, которые должны быть представлены JavaScript через Node-API. Функции обратного вызова должны удовлетворять следующей сигнатуре:
typedef napi_value (*napi_callback)(napi_env, napi_callback_info); copy
За исключением случаев, обсуждаемых в разделе Управление жизненным циклом объектов, создание области видимости handle и/или обратного вызова внутри napi_callback не требуется.
node_api_nogc_finalize
Тип указателя на функцию, предоставленный плагином, который позволяет пользователю получать уведомления о том, что данные, принадлежащие внешнему источнику, готовы к очистке, потому что объект, с которым они были связаны, был собран сборщиком мусора. Пользователь должен предоставить функцию, удовлетворяющую следующей сигнатуре, которая будет вызываться при сборе объекта. В настоящее время, node_api_nogc_finalize может использоваться для определения момента сбора объектов, имеющих внешние данные.
typedef void (*node_api_nogc_finalize)(node_api_nogc_env env,
void* finalize_data,
void* finalize_hint); copy За исключением случаев, обсуждаемых в разделе Управление жизненным циклом объектов, создание области видимости handle и/или обратного вызова внутри тела функции не требуется.
Поскольку эти функции могут вызываться, когда JavaScript-движок находится в состоянии, когда он не может выполнять JavaScript-код, вызывать могут только Node-API, которые принимают node_api_nogc_env в качестве первого параметра. node_api_post_finalizer может быть использован для планирования вызовов Node-API, требующих доступа к состоянию JavaScript-движка, для выполнения после завершения текущего цикла сбора мусора.
В случае node_api_create_external_string_latin1 и node_api_create_external_string_utf16 параметр env может быть null, так как внешние строки могут быть собраны в последней части завершения среды.
История изменений:
-
экспериментальная (
NAPI_EXPERIMENTAL):Можно вызывать только вызовы Node-API, которые принимают
node_api_nogc_envв качестве своего первого параметра, в противном случае приложение будет завершено с соответствующим сообщением об ошибке. Эту функцию можно отключить, определивNODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT.
napi_finalize
Тип указателя на функцию, предоставленный плагином, который позволяет пользователю запланировать группу вызовов Node-API в ответ на событие сбора мусора, после завершения цикла сбора мусора. Эти указатели на функции могут быть использованы с node_api_post_finalizer.
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint); copy История изменений:
-
экспериментальный (
NAPI_EXPERIMENTALопределён):Функция такого типа больше не может использоваться в качестве финализатора, за исключением использования
node_api_post_finalizer. Вместо этого необходимо использоватьnode_api_nogc_finalize. Данную функцию можно отключить, определивNODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT.
napi_async_execute_callback
Указатель на функцию, используемый с функциями, поддерживающими асинхронные операции. Функции обратного вызова должны соответствовать следующему подписи:
typedef void (*napi_async_execute_callback)(napi_env env, void* data); copy
Реализации этой функции должны избегать выполнения вызовов Node-API, которые выполняют JavaScript или взаимодействуют с объектами JavaScript. Вызовы Node-API должны выполняться в napi_async_complete_callback вместо этого. Не используйте параметр napi_env, так как это, вероятно, приведёт к выполнению JavaScript.
napi_async_complete_callback
Указатель на функцию, используемый с функциями, поддерживающими асинхронные операции. Функции обратного вызова должны соответствовать следующему подписи:
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); copy Если создание дескриптора и/или области обратного вызова внутри тела функции не требуется по причинам, обсуждаемым в разделе Управление жизненным циклом объектов, то его не нужно создавать.
napi_threadsafe_function_call_js
Указатель на функцию, используемый с асинхронными потокобезопасными вызовами функций. Обратный вызов будет вызван в главном потоке. Его цель — использование элемента данных, поступающего через очередь из одного из вторичных потоков, для построения параметров, необходимых для вызова в JavaScript, обычно через napi_call_function, и затем выполнить вызов в JavaScript.
Данные, поступающие из вторичного потока через очередь, передаются в параметре data, а функция JavaScript для вызова передаётся в параметре js_callback.
Node-API подготавливает среду перед вызовом этого обратного вызова, поэтому достаточно вызвать функцию JavaScript через napi_call_function вместо napi_make_callback.
Функции обратного вызова должны соответствовать следующему подписи:
typedef void (*napi_threadsafe_function_call_js)(napi_env env,
napi_value js_callback,
void* context,
void* data); copy -
[in] env: Среда, используемая для вызовов API, илиNULL, если потокобезопасная функция разрушается иdataможет потребоваться освободить. -
[in] js_callback: Функция JavaScript для вызова, илиNULL, если потокобезопасная функция разрушается иdataможет потребоваться освободить. Она также может бытьNULL, если потокобезопасная функция была создана безjs_callback. -
[in] context: Необязательные данные, с которыми была создана потокобезопасная функция. -
[in] data: Данные, созданные вторичным потоком. Обработчик обратного вызова несет ответственность за преобразование этих нативных данных в значения JavaScript (с помощью функций Node-API), которые можно передавать в качестве параметров при вызовеjs_callback. Этот указатель полностью управляется потоками и этим обратным вызовом. Таким образом, этот обратный вызов должен освободить данные.
Если создание дескриптора и/или области обратного вызова внутри тела функции не требуется по причинам, обсуждаемым в разделе Управление жизненным циклом объектов, то его не нужно создавать.
napi_cleanup_hook
Указатель на функцию, используемый с napi_add_env_cleanup_hook. Она будет вызвана при разрушении среды.
Функции обратного вызова должны соответствовать следующему подписи:
typedef void (*napi_cleanup_hook)(void* data); copy
-
[in] data: Данные, переданные вnapi_add_env_cleanup_hook.
napi_async_cleanup_hook
Указатель на функцию, используемый с napi_add_async_cleanup_hook. Она будет вызвана при разрушении среды.
Функции обратного вызова должны соответствовать следующему подписи:
typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle,
void* data); copy -
[in] handle: Дескриптор, который необходимо передать вnapi_remove_async_cleanup_hookпосле завершения асинхронной очистки. -
[in] data: Данные, переданные вnapi_add_async_cleanup_hook.
Тело функции должно инициировать асинхронные действия очистки, после чего handle необходимо передать в вызове napi_remove_async_cleanup_hook.
Обработка ошибок
Node-API использует значения возврата и JavaScript-исключения для обработки ошибок. Следующие разделы объясняют подход для каждого случая.
Значения возврата
Все функции Node-API используют одинаковый шаблон обработки ошибок. Тип возвращаемого значения всех функций API — napi_status.
Значение возврата будет napi_ok, если запрос был выполнен успешно и не было брошено необработанное JavaScript-исключение. Если произошла ошибка И было брошено исключение, будет возвращено значение napi_status для ошибки. Если было брошено исключение, но ошибка не произошла, будет возвращено значение napi_pending_exception.
В случаях, когда возвращается значение, отличное от napi_ok или napi_pending_exception, необходимо вызвать napi_is_exception_pending, чтобы проверить, ожидается ли исключение. Подробности см. в разделе об исключениях.
Полный набор возможных значений napi_status определен в napi_api_types.h.
Значение возврата napi_status предоставляет независимое от виртуальной машины представление ошибки, которая произошла. В некоторых случаях полезно получить более подробную информацию, включая строку, представляющую ошибку, а также информацию, специфичную для виртуальной машины (движка).
Для получения этой информации предоставлена napi_get_last_error_info, которая возвращает структуру napi_extended_error_info. Формат структуры napi_extended_error_info следующий:
typedef struct napi_extended_error_info {
const char* error_message;
void* engine_reserved;
uint32_t engine_error_code;
napi_status error_code;
}; copy -
error_message: Текстовое представление произошедшей ошибки. -
engine_reserved: Непрозрачная ручка, предназначенная только для использования движком. -
engine_error_code: Код ошибки, специфичный для виртуальной машины. -
error_code: Код состояния Node-API для последней ошибки.
napi_get_last_error_info возвращает информацию о последнем вызове Node-API.
Не полагайтесь на содержимое или формат расширенной информации, так как она не подчиняется SemVer и может измениться в любое время. Она предназначена только для целей ведения логов.
napi_get_last_error_info
napi_status
napi_get_last_error_info(node_api_nogc_env env,
const napi_extended_error_info** result); copy -
[in] env: Среда, в которой вызывается API. -
[out] result: Структураnapi_extended_error_infoс дополнительной информацией об ошибке.
Возвращает napi_ok в случае успешного выполнения API.
Этот API получает структуру napi_extended_error_info с информацией о последней произошедшей ошибке.
Содержимое возвращенной структуры napi_extended_error_info является действительным только до тех пор, пока функция Node-API не будет вызвана на той же env. Это включает вызов napi_is_exception_pending, поэтому часто необходимо скопировать информацию, чтобы ее можно было использовать позже. Указатель, возвращаемый в error_message, указывает на статически определенную строку, поэтому его безопасно использовать, если вы скопировали его из поля error_message (которое будет перезаписано) до вызова другой функции Node-API.
Не полагайтесь на содержимое или формат расширенной информации, так как она не подчиняется SemVer и может измениться в любое время. Она предназначена только для целей ведения логов.
Этот API можно вызывать, даже если ожидается JavaScript-исключение.
Исключения
Любой вызов функции Node-API может привести к ожидаемому JavaScript-исключению. Это относится ко всем функциям API, даже к тем, которые могут не вызывать выполнение JavaScript.
Если значение napi_status , возвращаемое функцией, равно napi_ok, то исключение не ожидается и дополнительных действий не требуется. Если возвращаемое значение napi_status отличается от napi_ok или napi_pending_exception, для попытки восстановления и продолжения вместо простого немедленного возврата необходимо вызвать napi_is_exception_pending для определения того, ожидается исключение или нет.
Во многих случаях, когда функция Node-API вызывается, а исключение уже ожидается, функция вернется немедленно со значением napi_status napi_pending_exception. Однако это не относится ко всем функциям. Node-API позволяет вызывать подмножество функций для обеспечения некоторой минимальной очистки перед возвратом в JavaScript. В этом случае napi_status будет отражать состояние для функции. Она не будет отражать предыдущие ожидающие исключения. Чтобы избежать путаницы, проверяйте статус ошибки после каждого вызова функции.
Когда ожидается исключение, можно использовать один из двух подходов.
Первый подход заключается в выполнении необходимой очистки и возвращении, чтобы выполнение вернулось в JavaScript. В рамках перехода обратно в JavaScript исключение будет брошено в той точке кода JavaScript, где вызывался родной метод. Поведение большинства вызовов Node-API не определено, когда ожидается исключение, и многие просто вернут napi_pending_exception, поэтому делайте как можно меньше, а затем возвращайтесь в JavaScript, где исключение можно обработать.
Второй подход заключается в попытке обработать исключение. В некоторых случаях родной код может перехватить исключение, принять соответствующие меры и продолжить работу. Это рекомендуется только в конкретных случаях, когда известно, что исключение можно безопасно обработать. В этих случаях можно использовать napi_get_and_clear_last_exception для получения и очистки исключения. При успехе результат будет содержать дескриптор последнего брошенного JavaScript-исключения Object. Если после получения исключения выяснится, что исключение нельзя обработать, его можно повторно бросить с помощью napi_throw, где error — значение JavaScript, которое нужно бросить.
Также доступны следующие служебные функции, в случае, если родной код нуждается в том, чтобы бросить исключение или определить, является ли napi_value экземпляром JavaScript-объекта Error: napi_throw_error, napi_throw_type_error, napi_throw_range_error, node_api_throw_syntax_error и napi_is_error.
Также доступны следующие служебные функции, если нужно создать объект Error в родном коде: napi_create_error, napi_create_type_error, napi_create_range_error и node_api_create_syntax_error, где результат — napi_value, указывающий на недавно созданный JavaScript-объект Error.
Проект Node.js добавляет коды ошибок ко всем ошибкам, генерируемым внутри. Цель состоит в том, чтобы приложения использовали эти коды ошибок для проверки всех ошибок. Соответствующие сообщения об ошибках сохранятся, но будут использоваться только для ведения журнала и отображения, с предположением, что сообщение может измениться без применения SemVer. Для поддержки этой модели в Node-API, как во внутренней функциональности, так и для функциональности конкретного модуля (как хорошая практика), функции throw_ и create_ принимают необязательный параметр code, который представляет собой строку кода, который необходимо добавить в объект ошибки. Если необязательный параметр NULL, то код не будет связан с ошибкой. Если код предоставлен, имя, связанное с ошибкой, также обновляется до:
originalName [code] copy
где originalName — исходное имя, связанное с ошибкой, а code — предоставленный код. Например, если код 'ERR_ERROR_1' и создается TypeError, имя будет:
TypeError [ERR_ERROR_1] copy
napi_throw
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error); copy
-
[in] env: Среда, в которой вызывается API. -
[in] error: Значение JavaScript, которое нужно бросить.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает предоставленное значение JavaScript.
napi_throw_error
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
const char* code,
const char* msg); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-исключение Error с предоставленным текстом.
napi_throw_type_error
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
const char* code,
const char* msg); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-исключение TypeError с предоставленным текстом.
napi_throw_range_error
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
const char* code,
const char* msg); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-исключение RangeError с предоставленным текстом.
node_api_throw_syntax_error
NAPI_EXTERN napi_status node_api_throw_syntax_error(napi_env env,
const char* code,
const char* msg); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательный код ошибки, который нужно установить в ошибку. -
[in] msg: Строка C, представляющая текст, который нужно связать с ошибкой.
Возвращает napi_ok в случае успешного выполнения API.
Этот API бросает JavaScript-исключение SyntaxError с предоставленным текстом.
napi_is_error
NAPI_EXTERN napi_status napi_is_error(napi_env env,
napi_value value,
bool* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_value, который необходимо проверить. -
[out] result: Логическое значение, устанавливаемое в true, еслиnapi_valueпредставляет ошибку, и в false в противном случае.
Возвращает napi_ok в случае успешного выполнения API.
Этот API запрашивает napi_value для проверки, является ли он объектом ошибки.
napi_create_error
NAPI_EXTERN napi_status napi_create_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который нужно ассоциировать с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_valueсозданной ошибки.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает JavaScript Error с предоставленным текстом.
napi_create_type_error
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который нужно ассоциировать с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает JavaScript TypeError с предоставленным текстом.
napi_create_range_error
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который нужно ассоциировать с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает JavaScript RangeError с предоставленным текстом.
node_api_create_syntax_error
NAPI_EXTERN napi_status node_api_create_syntax_error(napi_env env,
napi_value code,
napi_value msg,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] code: Необязательныйnapi_valueсо строкой для кода ошибки, который нужно ассоциировать с ошибкой. -
[in] msg:napi_value, который ссылается на JavaScriptstring, используемый в качестве сообщения дляError. -
[out] result:napi_value, представляющий созданную ошибку.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает JavaScript SyntaxError с предоставленным текстом.
napi_get_and_clear_last_exception
napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[out] result: Исключение, если оно ожидается,NULLв противном случае.
Возвращает napi_ok в случае успешного выполнения API.
Этот API можно вызывать, даже если ожидается JavaScript-исключение.
napi_is_exception_pending
napi_status napi_is_exception_pending(napi_env env, bool* result); copy
-
[in] env: Среда, в которой вызывается API. -
[out] result: Логическое значение, устанавливаемое в true, если ожидается исключение.
Возвращает napi_ok в случае успешного выполнения API.
Этот API можно вызывать, даже если ожидается JavaScript-исключение.
napi_fatal_exception
napi_status napi_fatal_exception(napi_env env, napi_value err); copy
-
[in] env: Среда, в которой вызывается API. -
[in] err: Ошибка, передаваемая в'uncaughtException'.
Вызвать 'uncaughtException' в JavaScript. Полезно, если асинхронный вызов обратного вызова генерирует исключение без возможности восстановления.
Критические ошибки
В случае неисправимой ошибки в нативном дополнении, может быть выброшено критическое исключение, чтобы немедленно завершить процесс.
napi_fatal_error
NAPI_NO_RETURN void napi_fatal_error(const char* location,
size_t location_len,
const char* message,
size_t message_len); copy -
[in] location: Необязательное место, в котором произошла ошибка. -
[in] location_len: Длина места в байтах илиNAPI_AUTO_LENGTHесли оно имеет нуль-терминацию. -
[in] message: Сообщение, связанное с ошибкой. -
[in] message_len: Длина сообщения в байтах илиNAPI_AUTO_LENGTHесли оно имеет нуль-терминацию.
Вызов функции не возвращает значение, процесс будет завершен.
Этот API можно вызывать, даже если ожидается JavaScript-исключение.
Управление жизненным циклом объектов
При выполнении вызовов Node-API могут возвращаться ссылки на объекты в куче подчинённой виртуальной машины в виде napi_values. Эти ссылки должны удерживать объекты «живыми» до тех пор, пока они больше не требуются кодом нативном языке, иначе объекты могут быть собраны сборщиком мусора до того, как код нативном языке закончит их использование.
Когда возвращаются ссылки на объекты, они связываются с «областью видимости». Срок жизни по умолчанию связан со сроком жизни вызова метода нативном языке. В результате ссылки по умолчанию остаются действительными, и объекты, связанные с этими ссылками, будут удерживаться живыми на протяжении всего срока жизни вызова метода нативном языке.
Однако во многих случаях необходимо, чтобы ссылки оставались действительными в течение срока жизни, который короче или длиннее, чем срок жизни метода нативном языке. В следующих разделах описываются функции Node-API, которые могут использоваться для изменения срока жизни ссылки от значения по умолчанию.
Сокращение срока жизни ссылки по сравнению со сроком жизни метода нативном языке
Часто необходимо сократить срок жизни ссылок по сравнению со сроком жизни метода нативном языке. Например, рассмотрим метод нативном языке, имеющий цикл, который перебирает элементы в большом массиве:
for (int i = 0; i < 1000000; i++) {
napi_value result;
napi_status status = napi_get_element(env, object, i, &result);
if (status != napi_ok) {
break;
}
// do something with element
} copy Это приведет к созданию большого количества ссылок, что потребует значительных ресурсов. Кроме того, даже если код нативном языке может использовать только последнюю ссылку, все связанные объекты также будут удерживаться живыми, поскольку они все имеют одну и ту же область видимости.
Для решения этой проблемы Node-API предоставляет возможность создания новой «области видимости», с которой будут связаны вновь созданные ссылки. После того, как эти ссылки больше не нужны, область видимости может быть «закрыта», и все ссылки, связанные с областью видимости, станут недействительными. Методы для открытия/закрытия областей видимости — napi_open_handle_scope и napi_close_handle_scope.
Node-API поддерживает только одну вложенную иерархию областей видимости. В любое время существует только одна активная область видимости, и все новые ссылки будут связаны с этой областью видимости, пока она активна. Области видимости должны закрываться в обратном порядке к тому, в котором они были открыты. Кроме того, все области видимости, созданные в методе нативном языке, должны быть закрыты перед возвратом из этого метода.
Взяв предыдущий пример, добавление вызовов napi_open_handle_scope и napi_close_handle_scope гарантирует, что не более одной ссылки будет действительной на протяжении всего выполнения цикла:
for (int i = 0; i < 1000000; i++) {
napi_handle_scope scope;
napi_status status = napi_open_handle_scope(env, &scope);
if (status != napi_ok) {
break;
}
napi_value result;
status = napi_get_element(env, object, i, &result);
if (status != napi_ok) {
break;
}
// do something with element
status = napi_close_handle_scope(env, scope);
if (status != napi_ok) {
break;
}
} copy При вложенности областей видимости в некоторых случаях ссылке из внутренней области видимости необходимо жить дольше, чем срок жизни этой области видимости. Node-API поддерживает «извлекаемую область видимости», чтобы поддержать этот случай. Извлекаемая область видимости позволяет одной ссылке быть «продвинутой» так, чтобы она «выбралась» из текущей области видимости, и срок жизни ссылки меняется с текущей области видимости на область внешней области видимости.
Методы для открытия/закрытия извлекаемых областей видимости — napi_open_escapable_handle_scope и napi_close_escapable_handle_scope.
Запрос на продвижение ссылки выполняется через napi_escape_handle, который может быть вызван только один раз.
napi_open_handle_scope
NAPI_EXTERN napi_status napi_open_handle_scope(napi_env env,
napi_handle_scope* result); copy -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющая новую область видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API открывает новую область видимости.
napi_close_handle_scope
NAPI_EXTERN napi_status napi_close_handle_scope(napi_env env,
napi_handle_scope scope); copy -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющая область видимости, которая должна быть закрыта.
Возвращает napi_ok в случае успешного выполнения API.
Этот API закрывает область видимости, переданную в качестве параметра. Области видимости должны закрываться в обратном порядке к тому, в котором они были созданы.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
napi_open_escapable_handle_scope
NAPI_EXTERN napi_status
napi_open_escapable_handle_scope(napi_env env,
napi_handle_scope* result); copy -
[in] env: Среда, в которой вызывается API. -
[out] result:napi_valueпредставляющая новую область видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API открывает новую область видимости, из которой один объект может быть продвинут во внешнюю область видимости.
napi_close_escapable_handle_scope
NAPI_EXTERN napi_status
napi_close_escapable_handle_scope(napi_env env,
napi_handle_scope scope); copy -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющая область видимости, которая должна быть закрыта.
Возвращает napi_ok в случае успешного выполнения API.
Этот API закрывает область видимости, переданную в качестве параметра. Области видимости должны закрываться в обратном порядке к тому, в котором они были созданы.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
napi_escape_handle
napi_status napi_escape_handle(napi_env env,
napi_escapable_handle_scope scope,
napi_value escapee,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] scope:napi_valueпредставляющая текущую область видимости. -
[in] escapee:napi_valueпредставляющая JavaScriptObjectкоторый должен быть извлечён. -
[out] result:napi_valueпредставляющая ссылку на извлечённыйObjectво внешней области видимости.
Возвращает napi_ok в случае успешного выполнения API.
Этот API продвигает ссылку на JavaScript-объект, чтобы она была действительной на протяжении всего срока жизни внешней области видимости. Она может быть вызвана только один раз на область видимости. Если она вызывается более одного раза, будет возвращено сообщение об ошибке.
Этот API может быть вызван даже при наличии ожидающего исключения JavaScript.
Ссылки на значения со сроком жизни, превышающим срок жизни метода нативном языке
В некоторых случаях дополнение потребует возможности создавать и ссылаться на значения со сроком жизни, превышающим срок жизни одного вызова метода нативном языке. Например, для создания конструктора и последующего использования этого конструктора в запросе на создание экземпляров необходимо иметь возможность ссылаться на объект конструктора в нескольких различных запросах создания экземпляров. Это было бы невозможно с обычной ссылкой, возвращаемой как napi_value, как описано в предыдущем разделе. Срок жизни обычной ссылки управляется областями видимости, и все области видимости должны быть закрыты перед завершением метода нативном языке.
Node-API предоставляет методы для создания постоянных ссылок на значения. В настоящее время Node-API позволяет создавать ссылки только для ограниченного набора типов значений, включая объект, внешний объект, функцию и символ.
Каждая ссылка имеет связанный счётчик с значением 0 или выше, который определяет, будет ли ссылка удерживать соответствующее значение живым. Ссылки со значением счётчика 0 не препятствуют сборке мусора значений. Значения типа объект (объект, функция, внешний объект) и символ становятся «слабыми» ссылками и по-прежнему могут быть доступны, даже если они не собраны сборщиком мусора. Любое значение счётчика, большее 0, предотвратит сборку мусора соответствующих значений.
Значения символов имеют различные варианты. Настоящее поведение слабой ссылки поддерживается только локальными символами, созданными с помощью функции napi_create_symbol или вызовами конструктора JavaScript Symbol(). Глобально зарегистрированные символы, созданные с помощью функции node_api_symbol_for или вызовами функций JavaScript Symbol.for(), всегда остаются сильными ссылками, потому что сборщик мусора не собирает их. То же самое относится к общеизвестным символам, таким как Symbol.iterator. Их также никогда не собирает сборщик мусора.
Ссылки могут быть созданы с начальным значением счётчика. Затем счётчик может быть изменён с помощью napi_reference_ref и napi_reference_unref. Если объект будет собран, а счётчик ссылки равен 0, все последующие вызовы получения объекта, связанного с ссылкой napi_get_reference_value, вернут NULL для возвращаемого napi_value. Попытка вызвать napi_reference_ref для ссылки, объект которой был собран, приведет к ошибке.
Ссылки должны быть удалены, когда они больше не требуются дополнением. При удалении ссылки она больше не будет препятствовать сборке мусора соответствующего объекта. Отсутствие удаления постоянной ссылки приводит к «утечке памяти», где как нативная память для постоянной ссылки, так и соответствующий объект в куче будут удерживаться вечно.
Могут быть созданы несколько постоянных ссылок, которые ссылаются на один и тот же объект, каждая из которых будет либо удерживать объект живым, либо нет, в зависимости от своего индивидуального счётчика. Несколько постоянных ссылок на один и тот же объект могут привести к непредвиденному удержанию живой нативной памяти. Нативные структуры для постоянной ссылки должны быть удержаны живыми до выполнения финализаторов для ссылающегося объекта. Если новая постоянная ссылка создается для того же объекта, финализаторы для этого объекта не будут выполнены, и нативная память, на которую указывает предыдущая постоянная ссылка, не будет освобождена. Этого можно избежать, вызвав napi_delete_reference в дополнение к napi_reference_unref по возможности.
История изменений:
-
Экспериментальный (
NAPI_EXPERIMENTALопределено):Ссылки могут быть созданы для всех типов значений. Новые поддерживаемые типы значений не поддерживают семантику слабой ссылки, и значения этих типов освобождаются, когда счётчик ссылок становится 0, и больше не могут быть доступны по ссылке.
napi_create_reference
NAPI_EXTERN napi_status napi_create_reference(napi_env env,
napi_value value,
uint32_t initial_refcount,
napi_ref* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] value:napi_valueдля которого создаётся ссылка. -
[in] initial_refcount: Начальный счётчик ссылок для новой ссылки. -
[out] result:napi_refуказывающий на новую ссылку.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт новую ссылку со указанным значением счётчика ссылок на переданное значение.
napi_delete_reference
NAPI_EXTERN napi_status napi_delete_reference(napi_env env, napi_ref ref); copy
-
[in] env: Окружение, в котором вызывается API. -
[in] ref:napi_refдля удаления.
Возвращает napi_ok в случае успешного выполнения API.
Этот API удаляет переданную ссылку.
Этот API может быть вызван даже при наличии ожидающейся JavaScript-исключительной ситуации.
napi_reference_ref
NAPI_EXTERN napi_status napi_reference_ref(napi_env env,
napi_ref ref,
uint32_t* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] ref:napi_refдля которой будет увеличен счётчик ссылок. -
[out] result: Новый счётчик ссылок.
Возвращает napi_ok в случае успешного выполнения API.
Этот API увеличивает счётчик ссылок для переданной ссылки и возвращает результирующий счётчик ссылок.
napi_reference_unref
NAPI_EXTERN napi_status napi_reference_unref(napi_env env,
napi_ref ref,
uint32_t* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] ref:napi_refдля которой будет уменьшен счётчик ссылок. -
[out] result: Новый счётчик ссылок.
Возвращает napi_ok в случае успешного выполнения API.
Этот API уменьшает счётчик ссылок для переданной ссылки и возвращает результирующий счётчик ссылок.
napi_get_reference_value
NAPI_EXTERN napi_status napi_get_reference_value(napi_env env,
napi_ref ref,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] ref:napi_refдля которой запрашивается соответствующее значение. -
[out] result:napi_valueссылаемый наnapi_ref.
Возвращает napi_ok в случае успешного выполнения API.
Если ссылка всё ещё действительна, этот API возвращает napi_value , представляющее JavaScript-значение, связанное с napi_ref. В противном случае результат будет NULL.
Очистка при выходе из текущей среды Node.js
Хотя процесс Node.js обычно освобождает все свои ресурсы при выходе, разработчики, использующие Node.js, или будущая поддержка Worker, могут потребовать от дополнений зарегистрировать обработчики очистки, которые будут выполнены после выхода из текущей среды Node.js.
Node-API предоставляет функции для регистрации и отмены регистрации таких обратных вызовов. Когда эти обратные вызовы выполняются, все ресурсы, которые удерживает дополнение, должны быть освобождены.
napi_add_env_cleanup_hook
NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_nogc_env env,
napi_cleanup_hook fun,
void* arg); copy Регистрирует fun как функцию, которая будет выполнена с параметром arg после выхода из текущей среды Node.js.
Функция может быть указана несколько раз с различными значениями arg. В этом случае она будет вызвана несколько раз. Указание одинаковых значений fun и arg несколько раз запрещено и приведёт к прерыванию процесса.
Обработчики будут вызваны в обратном порядке, т.е. последний добавленный будет вызван первым.
Удаление этого обработчика может быть выполнено с помощью napi_remove_env_cleanup_hook. Обычно это происходит при разборке ресурса, для которого был добавлен этот обработчик.
Для асинхронной очистки доступна napi_add_async_cleanup_hook.
napi_remove_env_cleanup_hook
NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_nogc_env env,
void (*fun)(void* arg),
void* arg); copy Отменяет регистрацию fun как функции, которая будет выполнена с параметром arg после выхода из текущей среды Node.js. И аргумент, и значение функции должны точно совпадать.
Функция должна была первоначально быть зарегистрирована с помощью napi_add_env_cleanup_hook, иначе процесс прервётся.
napi_add_async_cleanup_hook
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
node_api_nogc_env env,
napi_async_cleanup_hook hook,
void* arg,
napi_async_cleanup_hook_handle* remove_handle); copy -
[in] env: Окружение, в котором вызывается API. -
[in] hook: Указатель на функцию, которая будет вызвана при завершении среды. -
[in] arg: Указатель, который будет передан вhookпри его вызове. -
[out] remove_handle: Необязательная обработка, которая ссылается на асинхронный обработчик очистки.
Регистрирует hook, которая является функцией типа napi_async_cleanup_hook, как функцию, которая будет выполнена с параметрами remove_handle и arg после выхода из текущей среды Node.js.
В отличие от napi_add_env_cleanup_hook, этот обработчик может быть асинхронным.
В остальном поведение в целом соответствует napi_add_env_cleanup_hook.
Если remove_handle не NULL, в него будет сохранёно невидимое значение, которое позже должно быть передано в napi_remove_async_cleanup_hook, независимо от того, был ли обработчик уже вызван. Обычно это происходит при разборке ресурса, для которого был добавлен этот обработчик.
napi_remove_async_cleanup_hook
NAPI_EXTERN napi_status napi_remove_async_cleanup_hook(
napi_async_cleanup_hook_handle remove_handle); copy -
[in] remove_handle: Обработка асинхронной очистки, созданная с помощьюnapi_add_async_cleanup_hook.
Отменяет регистрацию обработчика очистки, соответствующего remove_handle. Это предотвратит выполнение обработчика, если он ещё не начал выполняться. Это необходимо сделать с любым значением napi_async_cleanup_hook_handle , полученным из napi_add_async_cleanup_hook.
Заключительная обработка при выходе из среды Node.js
Среда Node.js может быть разложена в любой момент, как только это возможно, при запрете выполнения JavaScript, например, по запросу worker.terminate(). При разборе среды немедленно и независимо вызываются зарегистрированные обработчики завершения для JavaScript-объектов, функций с поддержкой потоков и данных экземпляра среды.
Вызов обработчиков napi_finalize планируется после вручную зарегистрированных обработчиков очистки. Чтобы гарантировать правильный порядок завершения дополнений во время завершения среды, чтобы избежать использования после освобождения в обратном вызове napi_finalize, дополнения должны зарегистрировать обработчик очистки с помощью napi_add_env_cleanup_hook и napi_add_async_cleanup_hook для ручного освобождения выделенного ресурса в правильном порядке.
Регистрация модуля
Модули Node-API регистрируются аналогично другим модулям, за исключением того, что вместо макроса NODE_MODULE используется следующее:
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) copy
Следующее отличие — сигнатура метода Init. Для модуля Node-API она выглядит следующим образом:
napi_value Init(napi_env env, napi_value exports); copy
Возвращаемое значение от Init рассматривается как объект exports для модуля. Метод Init получает пустой объект через параметр exports для удобства. Если Init возвращает NULL, параметр, переданный как exports , экспортируется модулем. Модули Node-API не могут изменять объект module, но могут указать что-либо в качестве свойства exports модуля.
Для добавления метода hello в качестве функции, чтобы его можно было вызывать как метод, предоставляемый дополнением:
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor desc = {
"hello",
NULL,
Method,
NULL,
NULL,
NULL,
napi_writable | napi_enumerable | napi_configurable,
NULL
};
status = napi_define_properties(env, exports, 1, &desc);
if (status != napi_ok) return NULL;
return exports;
} copy Для установки функции, которая будет возвращена require() для дополнения:
napi_value Init(napi_env env, napi_value exports) {
napi_value method;
napi_status status;
status = napi_create_function(env, "exports", NAPI_AUTO_LENGTH, Method, NULL, &method);
if (status != napi_ok) return NULL;
return method;
} copy Для определения класса, чтобы можно было создавать новые экземпляры (часто используется с обёртыванием объекта):
// NOTE: partial example, not all referenced code is included
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor properties[] = {
{ "value", NULL, NULL, GetValue, SetValue, NULL, napi_writable | napi_configurable, NULL },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
};
napi_value cons;
status =
napi_define_class(env, "MyObject", New, NULL, 3, properties, &cons);
if (status != napi_ok) return NULL;
status = napi_create_reference(env, cons, 1, &constructor);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "MyObject", cons);
if (status != napi_ok) return NULL;
return exports;
} copy Также можно использовать макрос NAPI_MODULE_INIT, который является сокращением для NAPI_MODULE и определения функции Init:
NAPI_MODULE_INIT(/* napi_env env, napi_value exports */) {
napi_value answer;
napi_status result;
status = napi_create_int64(env, 42, &answer);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "answer", answer);
if (status != napi_ok) return NULL;
return exports;
} copy Параметры env и exports предоставляются в теле макроса NAPI_MODULE_INIT.
Все дополнения Node-API осознают контекст, что означает, что они могут быть загружены несколько раз. При объявлении такого модуля необходимо учитывать несколько моментов проектирования. Дополнительные сведения см. в документации по модулям с осознанием контекста.
Переменные env и exports будут доступны внутри тела функции после вызова макроса.
Дополнительные сведения о настройке свойств объектов см. в разделе Работа со свойствами JavaScript.
Дополнительные сведения о создании модулей дополнений в целом см. в существующей документации API.
Работа со значениями JavaScript
Node-API предоставляет набор API для создания всех типов значений JavaScript. Некоторые из этих типов документированы в разделе 6 Спецификации языка ECMAScript.
В основном, эти API используются для одного из следующих действий:
- Создание нового объекта JavaScript
- Преобразование примитивного типа C в значение Node-API
- Преобразование значения Node-API в примитивный тип C
- Получение глобальных экземпляров, включая
undefinedиnull
Значения Node-API представлены типом napi_value. Любой вызов Node-API, требующий значения JavaScript, принимает napi_value. В некоторых случаях API проверяет тип napi_value заранее. Однако для лучшей производительности лучше, чтобы вызывающая сторона убедилась, что napi_value имеет ожидаемый типом JavaScript для API.
Типы перечислений
napi_key_collection_mode
typedef enum {
napi_key_include_prototypes,
napi_key_own_only
} napi_key_collection_mode; copy Описывает перечисления фильтров Keys/Properties:
napi_key_collection_mode ограничивает диапазон собранных свойств.
napi_key_own_only ограничивает собранные свойства только заданным объектом. napi_key_include_prototypes также включит все ключи цепочки прототипов объектов.
napi_key_filter
typedef enum {
napi_key_all_properties = 0,
napi_key_writable = 1,
napi_key_enumerable = 1 << 1,
napi_key_configurable = 1 << 2,
napi_key_skip_strings = 1 << 3,
napi_key_skip_symbols = 1 << 4
} napi_key_filter; copy Биты фильтра свойств. Их можно объединять с помощью операции OR для создания составного фильтра.
napi_key_conversion
typedef enum {
napi_key_keep_numbers,
napi_key_numbers_to_strings
} napi_key_conversion; copy napi_key_numbers_to_strings преобразует целочисленные индексы в строки. napi_key_keep_numbers вернет числа для целочисленных индексов.
napi_valuetype
typedef enum {
// ES6 types (corresponds to typeof)
napi_undefined,
napi_null,
napi_boolean,
napi_number,
napi_string,
napi_symbol,
napi_object,
napi_function,
napi_external,
napi_bigint,
} napi_valuetype; copy Описывает тип napi_value. Как правило, он соответствует типам, описанным в разделе 6.1 Спецификации языка ECMAScript. Помимо типов в этом разделе, napi_valuetype также может представлять Function и Object с внешними данными.
Значение JavaScript типа napi_external в JavaScript отображается как обычный объект, к которому нельзя установить свойства и у которого нет прототипа.
napi_typedarray_type
typedef enum {
napi_int8_array,
napi_uint8_array,
napi_uint8_clamped_array,
napi_int16_array,
napi_uint16_array,
napi_int32_array,
napi_uint32_array,
napi_float32_array,
napi_float64_array,
napi_bigint64_array,
napi_biguint64_array,
} napi_typedarray_type; copy Это представляет собой базовый бинарный скалярный тип данных TypedArray . Элементы этого перечисления соответствуют разделу 22.2 Спецификации языка ECMAScript.
Функции создания объектов
napi_create_array
napi_status napi_create_array(napi_env env, napi_value* result) copy
-
[in] env: Среда, в которой вызывается вызов Node-API. -
[out] result:napi_value, представляющий JavaScriptArray.
Возвращает napi_ok , если API выполнено успешно.
Этот API возвращает значение Node-API, соответствующее типу JavaScript Array. Массивы JavaScript описаны в разделе 22.1 Спецификации языка ECMAScript.
napi_create_array_with_length
napi_status napi_create_array_with_length(napi_env env,
size_t length,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Начальная длинаArray. -
[out] result: Anapi_valuerepresenting a JavaScriptArray.
Возвращает napi_ok , если API выполнено успешно.
Этот API возвращает значение Node-API, соответствующее типу JavaScript Array . Свойство length Array устанавливается в переданный параметр length. Однако гарантии предварительной выделения буфера VM при создании массива нет. Это поведение зависит от реализации базовой VM. Если буфер должен представлять собой непрерывный блок памяти, который можно непосредственно читать и/или записывать через C, используйте napi_create_external_arraybuffer.
Массивы JavaScript описаны в разделе 22.1 Спецификации языка ECMAScript.
napi_create_arraybuffer
napi_status napi_create_arraybuffer(napi_env env,
size_t byte_length,
void** data,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Размер в байтах создаваемого буфера массива. -
[out] data: Указатель на базовый байтовый буферArrayBuffer.dataможно необязательно пропустить, передавNULL. -
[out] result: Anapi_valuerepresenting a JavaScriptArrayBuffer.
Возвращает 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) copy -
[in] env: Среда, в которой вызывается API. -
[in] size: Размер базового буфера в байтах. -
[out] data: Сырой указатель на базовый буфер.dataможно необязательно пропустить, передавNULL. -
[out] result: Anapi_valuerepresenting anode::Buffer.
Возвращает napi_ok , если API выполнено успешно.
Этот API выделяет объект node::Buffer. Хотя эта структура по-прежнему полностью поддерживается, в большинстве случаев достаточно использовать TypedArray.
napi_create_buffer_copy
napi_status napi_create_buffer_copy(napi_env env,
size_t length,
const void* data,
void** result_data,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] size: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Сырой указатель на исходный буфер для копирования. -
[out] result_data: Указатель на базовый буфер данных новогоBuffer.result_dataможно необязательно пропустить, передавNULL. -
[out] result: Anapi_valuerepresenting anode::Buffer.
Возвращает napi_ok , если API выполнено успешно.
Этот API выделяет объект node::Buffer и инициализирует его данными, скопированными из переданного буфера. Хотя эта структура по-прежнему полностью поддерживается, в большинстве случаев достаточно использовать TypedArray.
napi_create_date
napi_status napi_create_date(napi_env env,
double time,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] time: Значение времени ECMAScript в миллисекундах с момента 01 января 1970 года по UTC. -
[out] result: Anapi_valuerepresenting a JavaScriptDate.
Возвращает napi_ok , если API выполнено успешно.
Этот API не учитывает високосных секунд; они игнорируются, так как ECMAScript соответствует спецификации времени POSIX.
Этот API выделяет объект JavaScript Date.
Объекты JavaScript Date описаны в разделе 20.3 Спецификации языка ECMAScript.
napi_create_external
napi_status napi_create_external(napi_env env,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] data: Сырой указатель на внешние данные. -
[in] finalize_cb: Необязательный обратный вызов, который вызывается при сборке внешнего значения.napi_finalizeсодержит больше деталей. -
[in] finalize_hint: Необязательное значение, передаваемое обратной функции finalize при сборке. -
[out] result: Anapi_valueпредставляющий внешнее значение.
Возвращает napi_ok , если API выполнено успешно.
Этот API выделяет значение JavaScript с прикрепленными к нему внешними данными. Это используется для передачи внешних данных через код JavaScript, чтобы их можно было получить позже кодом на C, используя napi_get_value_external.
API добавляет обратный вызов napi_finalize, который вызывается, когда только что созданный объект JavaScript был собран сборщиком мусора.
Созданное значение не является объектом и, следовательно, не поддерживает дополнительные свойства. Это считается отдельным типом значения: вызов napi_typeof() с внешним значением возвращает napi_external.
napi_create_external_arraybuffer
napi_status
napi_create_external_arraybuffer(napi_env env,
void* external_data,
size_t byte_length,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] external_data: Указатель на базовую байтовую буферArrayBuffer. -
[in] byte_length: Длина базового буфера в байтах. -
[in] finalize_cb: Необязательный обратный вызов, который вызывается при сбореArrayBuffer.napi_finalizeсодержит более подробную информацию. -
[in] finalize_hint: Необязательный параметр, передаваемый обратному вызову finalize во время сбора. -
[out] result:napi_value, представляющий JavaScriptArrayBuffer.
Возвращает napi_ok в случае успешного выполнения API.
Некоторые среды выполнения, отличные от Node.js, отказались от поддержки внешних буферов. В средах выполнения, отличных от Node.js, этот метод может возвращать napi_no_external_buffers_allowed для обозначения отсутствия поддержки внешних буферов. Одним из таких сред выполнения является Electron, как описано в этом вопросе electron/issues/35801.
Для обеспечения максимальной совместимости со всеми средами выполнения вы можете определить NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED в своем расширении перед включением заголовков node-api. Это скроет 2 функции, создающие внешние буферы. Это гарантирует ошибку компиляции, если вы случайно используете один из этих методов.
Этот API возвращает значение Node-API, соответствующее JavaScript ArrayBuffer. Базовый байтовый буфер ArrayBuffer выделен и управляется внешним образом. Вызывающая сторона должна гарантировать, что байтовый буфер остается допустимым до вызова обратного вызова finalize.
API добавляет обратный вызов napi_finalize, который будет вызван при сборке JavaScript-объекта, который только что был создан.
JavaScript ArrayBuffer описаны в Разделе 24.1 спецификации языка ECMAScript.
napi_create_external_buffer
napi_status napi_create_external_buffer(napi_env env,
size_t length,
void* data,
napi_finalize finalize_cb,
void* finalize_hint,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Размер входного буфера в байтах (должен быть таким же, как размер нового буфера). -
[in] data: Необработанный указатель на базовый буфер для экспонирования JavaScript. -
[in] finalize_cb: Необязательный обратный вызов, который вызывается при сбореArrayBuffer.napi_finalizeсодержит более подробную информацию. -
[in] finalize_hint: Необязательный параметр, передаваемый обратному вызову finalize во время сбора. -
[out] result:napi_value, представляющийnode::Buffer.
Возвращает napi_ok в случае успешного выполнения API.
Некоторые среды выполнения, отличные от Node.js, отказались от поддержки внешних буферов. В средах выполнения, отличных от Node.js, этот метод может возвращать napi_no_external_buffers_allowed для обозначения отсутствия поддержки внешних буферов. Одним из таких сред выполнения является Electron, как описано в этом вопросе electron/issues/35801.
Для обеспечения максимальной совместимости со всеми средами выполнения вы можете определить NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED в своем расширении перед включением заголовков node-api. Это скроет 2 функции, создающие внешние буферы. Это гарантирует ошибку компиляции, если вы случайно используете один из этих методов.
Этот API выделяет объект node::Buffer и инициализирует его данными, подкреплёнными переданным буфером. Хотя это по-прежнему полностью поддерживаемая структура данных, в большинстве случаев достаточно использовать TypedArray.
API добавляет обратный вызов napi_finalize, который будет вызван при сборке JavaScript-объекта, который только что был создан.
Для Node.js >=4 Buffers являются Uint8Array.
napi_create_object
napi_status napi_create_object(napi_env env, napi_value* result) copy
-
[in] env: Среда, в которой вызывается API. -
[out] result:napi_value, представляющий JavaScriptObject.
Возвращает napi_ok в случае успешного выполнения API.
Этот API выделяет стандартный JavaScript Object. Это эквивалентно выполнению new Object() в JavaScript.
Тип JavaScript Object описан в Разделе 6.1.7 спецификации языка ECMAScript.
napi_create_symbol
napi_status napi_create_symbol(napi_env env,
napi_value description,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] description: Необязательноеnapi_value, которое ссылается на JavaScriptstringдля установки в качестве описания символа. -
[out] result:napi_value, представляющий JavaScriptsymbol.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт значение JavaScript symbol из UTF8-строки C.
Тип JavaScript symbol описан в Разделе 19.4 спецификации языка ECMAScript.
node_api_symbol_for
napi_status node_api_symbol_for(napi_env env,
const char* utf8description,
size_t length,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] utf8description: UTF-8 строка C, представляющая текст, который будет использоваться в качестве описания символа. -
[in] length: Длина описания строки в байтах илиNAPI_AUTO_LENGTHесли она завершается нулём. -
[out] result:napi_value, представляющий JavaScriptsymbol.
Возвращает napi_ok в случае успешного выполнения API.
Этот API ищет в глобальной базе данных существующий символ с заданным описанием. Если символ уже существует, он будет возвращён, в противном случае новый символ будет создан в базе данных.
Тип JavaScript symbol описан в Разделе 19.4 спецификации языка ECMAScript.
napi_create_typedarray
napi_status napi_create_typedarray(napi_env env,
napi_typedarray_type type,
size_t length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] type: Скалярный тип данных элементов внутриTypedArray. -
[in] length: Количество элементов вTypedArray. -
[in] arraybuffer:ArrayBufferлежащий в основе массива с типом. -
[in] byte_offset: Смещение в байтах внутриArrayBuffer, с которого следует начать проекциюTypedArray. -
[out] result:napi_value, представляющий JavaScriptTypedArray.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт JavaScript TypedArray объект над существующим ArrayBuffer. Объекты TypedArray предоставляют массив-подобный вид на лежащем в основе буфере данных, где каждый элемент имеет тот же лежащий в основе двоичный скалярный тип данных.
Требуется, чтобы (length * size_of_element) + byte_offset было <= размеру в байтах переданного массива. В противном случае возникает исключение RangeError.
JavaScript TypedArray объекты описаны в Разделе 22.2 спецификации языка ECMAScript.
napi_create_dataview
napi_status napi_create_dataview(napi_env env,
size_t byte_length,
napi_value arraybuffer,
size_t byte_offset,
napi_value* result) copy -
[in] env: Среда, в которой вызывается API. -
[in] length: Количество элементов вDataView. -
[in] arraybuffer:ArrayBufferлежащий в основеDataView. -
[in] byte_offset: Смещение в байтах внутриArrayBuffer, с которого следует начать проекциюDataView. -
[out] result:napi_value, представляющий JavaScriptDataView.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт JavaScript DataView объект над существующим ArrayBuffer. Объекты DataView обеспечивают массив-подобный вид на лежащем в основе буфере данных, но позволяют использовать элементы разного размера и типа в ArrayBuffer.
Требуется, чтобы byte_length + byte_offset было меньше или равно размеру в байтах переданного массива. В противном случае возникает исключение RangeError.
JavaScript DataView объекты описаны в Разделе 24.3 спецификации языка ECMAScript.
Функции для преобразования типов C в Node-API
napi_create_int32
napi_status napi_create_int32(napi_env env, int32_t value, napi_value* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result:napi_value, представляющий JavaScriptnumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для преобразования типа C int32_t в тип JavaScript number.
Тип JavaScript number описан в Разделе 6.1.6 спецификации языка ECMAScript.
napi_create_uint32
napi_status napi_create_uint32(napi_env env, uint32_t value, napi_value* result) copy
-
[in] env: Среда, в которой вызывается API. -
[in] value: Беззнаковое целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result:napi_value, представляющий JavaScriptnumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для преобразования типа C uint32_t в тип JavaScript number.
Тип JavaScript number описан в Разделе 6.1.6 спецификации языка ECMAScript.
napi_create_int64
napi_status napi_create_int64(napi_env env, int64_t value, napi_value* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Целочисленное значение, которое должно быть представлено в JavaScript. -
[out] result:napi_value, представляющий собой JavaScriptnumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для преобразования типа C int64_t в тип JavaScript number.
Тип JavaScript number описан в Разделе 6.1.6 спецификации языка ECMAScript. Обратите внимание, что весь диапазон int64_t не может быть представлен с полной точностью в JavaScript. Целочисленные значения вне диапазона Number.MIN_SAFE_INTEGER -(2**53 - 1) - Number.MAX_SAFE_INTEGER (2**53 - 1) потеряют точность.
napi_create_double
napi_status napi_create_double(napi_env env, double value, napi_value* result) copy
-
[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); copy -
[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); copy -
[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); copy -
[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); copy -
[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.
node_api_create_external_string_latin1
napi_status
node_api_create_external_string_latin1(napi_env env,
char* str,
size_t length,
napi_finalize finalize_callback,
void* finalize_hint,
napi_value* result,
bool* copied); copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке ISO-8859-1. -
[in] length: Длина строки в байтах, илиNAPI_AUTO_LENGTHесли строка завершается нулём. -
[in] finalize_callback: Функция, которая вызывается при сборе мусора строки. Функция вызывается со следующими параметрами:-
[in] env: Окружение, в котором работает плагин. Это значение может быть null, если строка собирается в рамках завершения работы worker или основного экземпляра Node.js. -
[in] data: Это значениеstrкак указательvoid*. -
[in] finalize_hint: Это значениеfinalize_hint, переданное в API.napi_finalizeсодержит более подробную информацию. Этот параметр является необязательным. Передача значения null означает, что плагин не нуждается в уведомлении при сборе мусора соответствующей JavaScript строки.
-
-
[in] finalize_hint: Необязательный параметр для передачи в коллбэк finalize при сборе мусора. -
[out] result:napi_valueпредставляющий собой JavaScriptstring. -
[out] copied: Была ли скопирована строка. Если была, то finalizer уже был вызван для удаленияstr.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создает значение JavaScript string из C-строки в кодировке ISO-8859-1. Оригинальная строка может не копироваться и должна существовать на протяжении всего жизненного цикла JavaScript-значения.
Тип 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) copy -
[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.
node_api_create_external_string_utf16
napi_status
node_api_create_external_string_utf16(napi_env env,
char16_t* str,
size_t length,
napi_finalize finalize_callback,
void* finalize_hint,
napi_value* result,
bool* copied); copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку в кодировке UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах, илиNAPI_AUTO_LENGTHесли она завершается нулём. -
[in] finalize_callback: Функция, которая вызывается при сборе мусора строки. Функция вызывается со следующими параметрами:-
[in] env: Окружение, в котором работает плагин. Это значение может быть null, если строка собирается в рамках завершения работы worker или основного экземпляра Node.js. -
[in] data: Это значениеstrкак указательvoid*. -
[in] finalize_hint: Это значениеfinalize_hint, переданное в API.napi_finalizeсодержит более подробную информацию. Этот параметр является необязательным. Передача значения null означает, что плагин не нуждается в уведомлении при сборе мусора соответствующей JavaScript строки.
-
-
[in] finalize_hint: Необязательный параметр для передачи в коллбэк finalize при сборе мусора. -
[out] result:napi_value, представляющий собой JavaScriptstring. -
[out] copied: Была ли скопирована строка. Если была, то finalizer уже был вызван для удаленияstr.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создает значение JavaScript string из C-строки в кодировке UTF16-LE. Оригинальная строка может не копироваться и должна существовать на протяжении всего жизненного цикла JavaScript-значения.
Тип 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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку UTF8. -
[in] length: Длина строки в байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объектnapi_value, представляющий JavaScriptstring.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт значение JavaScript string из UTF8-строки C. Исходная строка копируется.
Тип JavaScript string описан в разделе 6.1.4 спецификации ECMAScript Language Specification.
node_api_create_property_key_utf16
napi_status NAPI_CDECL node_api_create_property_key_utf16(napi_env env,
const char16_t* str,
size_t length,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] str: Буфер символов, представляющий строку в формате UTF16-LE. -
[in] length: Длина строки в двухбайтовых кодовых единицах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[out] result: Объектnapi_value, представляющий оптимизированное JavaScriptstring, используемое в качестве ключа свойства для объектов.
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт оптимизированное значение JavaScript string из UTF16-LE-кодированной строки C, которое используется как ключ свойства для объектов. Исходная строка копируется.
Многие JavaScript-движки, включая V8, используют интернализованные строки в качестве ключей для установки и получения значений свойств. Они обычно используют хеш-таблицу для создания и поиска таких строк. Хотя это добавляет некоторую стоимость при создании каждого ключа, это улучшает производительность после этого, позволяя сравнивать указатели строк вместо самих строк.
Если новая JavaScript-строка должна использоваться в качестве ключа свойства, то для некоторых JavaScript-движков будет эффективнее использовать функцию node_api_create_property_key_utf16. В противном случае используйте функции napi_create_string_utf16 или node_api_create_external_string_utf16, так как при использовании этого метода может быть дополнительная нагрузка.
Тип JavaScript string описан в разделе 6.1.4 спецификации ECMAScript Language Specification.
Функции преобразования из Node-API в типы C
napi_get_array_length
napi_status napi_get_array_length(napi_env env,
napi_value value,
uint32_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptArray, длина которого запрашивается. -
[out] result:uint32представляющий длину массива.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает длину массива.
Длина Array описана в разделе 22.1.4.1 спецификации ECMAScript Language Specification.
napi_get_arraybuffer_info
napi_status napi_get_arraybuffer_info(napi_env env,
napi_value arraybuffer,
void** data,
size_t* byte_length) copy -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющийnode::BufferилиUint8Array, который запрашивается. -
[out] data: Базовый буфер данныхnode::BufferилиUint8Array. Если длина равна0, это может бытьNULLили любое другое значение указателя. -
[out] length: Длина базового буфера данных в байтах.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод возвращает идентичные data и byte_length как napi_get_typedarray_info. И napi_get_typedarray_info принимает node::Buffer (Uint8Array) в качестве значения тоже.
Этот API используется для получения базового буфера данных node::Buffer и его длины.
Предупреждение: Будьте осторожны при использовании этого API, так как жизненный цикл базового буфера данных не гарантируется, если он управляется виртуальной машиной.
napi_get_prototype
napi_status napi_get_prototype(napi_env env,
napi_value object,
napi_value* result) copy -
[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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] typedarray:napi_valueпредставляющийTypedArrayчьи свойства нужно запросить. -
[out] type: Скалярный тип данных элементов внутриTypedArray. -
[out] length: Количество элементов вTypedArray. -
[out] data: Буфер данных, лежащий в основеTypedArray, скорректированный значениемbyte_offset, так что он указывает на первый элемент вTypedArray. Если длина массива равна0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer:ArrayBufferлежащий в основеTypedArray. -
[out] byte_offset: Смещение в байтах в базовом массиве, с которого начинается проекция первого элемента массива. Значение параметра data уже скорректировано, так что data указывает на первый элемент в массиве. Таким образом, первый байт базового массива будет по адресуdata - byte_offset.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает различные свойства массива с типом данных.
Любой из выходных параметров может быть NULL, если это свойство не нужно.
Предупреждение: Будьте осторожны при использовании этого API, так как жизненный цикл базового буфера данных не гарантируется, если он управляется виртуальной машиной.
napi_get_dataview_info
napi_status napi_get_dataview_info(napi_env env,
napi_value dataview,
size_t* byte_length,
void** data,
napi_value* arraybuffer,
size_t* byte_offset) copy -
[in] env: Окружение, в котором вызывается API. -
[in] dataview:napi_valueпредставляющийDataView, чьи свойства нужно запросить. -
[out] byte_length: Количество байтов вDataView. -
[out] data: Базовый буфер данныхDataView. Если byte_length равно0, это может бытьNULLили любое другое значение указателя. -
[out] arraybuffer:ArrayBufferлежащий в основеDataView. -
[out] byte_offset: Смещение в байтах в буфере данных, с которого начать проекциюDataView.
Возвращает napi_ok в случае успешного выполнения API.
Любой из выходных параметров может быть NULL, если это свойство не нужно.
Этот API возвращает различные свойства DataView.
napi_get_date_value
napi_status napi_get_date_value(napi_env env,
napi_value value,
double* result) copy -
[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) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptBoolean. -
[out] result: Примитивное C булево значение, эквивалентное заданному JavaScriptBoolean.
Возвращает napi_ok в случае успешного выполнения API. Если передан не-булевое napi_value значение, возвращается napi_boolean_expected.
Этот API возвращает C булево значение, эквивалентное заданному JavaScript Boolean.
napi_get_value_double
napi_status napi_get_value_double(napi_env env,
napi_value value,
double* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptnumber. -
[out] result: C double, эквивалентное заданному JavaScriptnumber.
Возвращает napi_ok, если API выполнено успешно. Если на вход передано не числовое napi_value, то возвращается napi_number_expected.
Этот API возвращает C double, эквивалентное заданному JavaScript number.
napi_get_value_bigint_int64
napi_status napi_get_value_bigint_int64(napi_env env,
napi_value value,
int64_t* result,
bool* lossless); copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptBigInt. -
[out] result: 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); copy -
[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); copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptBigInt. -
[out] sign_bit: Целое число, определяющее знак JavaScriptBigInt. -
[in/out] word_count: Должно быть инициализировано длиной массиваwords. После возврата, будет установлено фактическое количество слов, необходимое для хранения этогоBigInt. -
[out] words: Указатель на предварительно выделенный массив 64-битных слов.
Возвращает napi_ok, если API выполнено успешно.
Этот API преобразует единственное значение BigInt в знаковый бит, 64-битный массив в формате little-endian и количество элементов в массиве. sign_bit и words могут быть оба установлены в NULL, чтобы получить только word_count.
napi_get_value_external
napi_status napi_get_value_external(napi_env env,
napi_value value,
void** result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScript внешнее значение. -
[out] result: Указатель на данные, обернутые JavaScript внешним значением.
Возвращает napi_ok, если API выполнено успешно. Если на вход передано не внешнее napi_value, то возвращается napi_invalid_arg.
Этот API извлекает указатель на внешние данные, которые были ранее переданы в napi_create_external().
napi_get_value_int32
napi_status napi_get_value_int32(napi_env env,
napi_value value,
int32_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptnumber. -
[out] result: 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) copy -
[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) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScript строку. -
[in] buf: Буфер для записи строки в кодировке ISO-8859-1. ЕслиNULLпередано, длина строки в байтах (без учёта нуль-терминатора) возвращается вresult. -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка усекается и завершается нулём. -
[out] result: Количество байтов, скопированных в буфер (без учёта нуль-терминатора).
Возвращает napi_ok, если API выполнено успешно. Если передано не string napi_value, то возвращает napi_string_expected.
Этот API возвращает строку в кодировке ISO-8859-1, соответствующую переданному значению.
napi_get_value_string_utf8
napi_status napi_get_value_string_utf8(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScript строку. -
[in] buf: Буфер для записи UTF8-строки. ЕслиNULLпередано, длина строки в байтах (без учёта нуль-терминатора) возвращается вresult. -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка усекается и завершается нулём. -
[out] result: Количество байтов, скопированных в буфер (без учёта нуль-терминатора).
Возвращает napi_ok, если API выполнено успешно. Если передано не string napi_value, то возвращает napi_string_expected.
Этот API возвращает UTF8-строку, соответствующую переданному значению.
napi_get_value_string_utf16
napi_status napi_get_value_string_utf16(napi_env env,
napi_value value,
char16_t* buf,
size_t bufsize,
size_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScript строку. -
[in] buf: Буфер для записи UTF16-LE-строки. ЕслиNULLпередано, длина строки в 2-байтовых кодовых единицах (без учёта нуль-терминатора) возвращается. -
[in] bufsize: Размер буфера назначения. Если этого значения недостаточно, возвращаемая строка усекается и завершается нулём. -
[out] result: Количество 2-байтовых кодовых единиц, скопированных в буфер (без учёта нуль-терминатора).
Возвращает napi_ok, если API выполнено успешно. Если передано не string napi_value, то возвращает napi_string_expected.
Этот API возвращает UTF16-строку, соответствующую переданному значению.
napi_get_value_uint32
napi_status napi_get_value_uint32(napi_env env,
napi_value value,
uint32_t* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value:napi_valueпредставляющий JavaScriptnumber. -
[out] result: C значение, эквивалентное заданному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) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение булевого типа для извлечения. -
[out] result:napi_value, представляющий собой синглтон JavaScriptBooleanдля извлечения.
Возвращает napi_ok в случае успешного выполнения API.
Этот API используется для возвращения объекта синглтона JavaScript, используемого для представления заданного булевого значения.
napi_get_global
napi_status napi_get_global(napi_env env, napi_value* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_value, представляющий собой объект JavaScriptglobal.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает объект global .
napi_get_null
napi_status napi_get_null(napi_env env, napi_value* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_value, представляющий собой объект JavaScriptnull.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает объект null .
napi_get_undefined
napi_status napi_get_undefined(napi_env env, napi_value* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[out] result:napi_value, представляющий собой значение JavaScript Undefined.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает объект Undefined.
Работа с значениями JavaScript и абстрактными операциями
Node-API предоставляет набор API для выполнения некоторых абстрактных операций со значениями JavaScript. Некоторые из этих операций задокументированы в разделе 7 Спецификации языка ECMAScript.
Эти API поддерживают выполнение следующих действий:
- Преобразование значений JavaScript к определенным типам JavaScript (таким как
numberилиstring). - Проверка типа значения JavaScript.
- Проверка равенства двух значений JavaScript.
Преобразование значения в булево
napi_status napi_coerce_to_bool(napi_env env,
napi_value value,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое необходимо преобразовать. -
[out] result:napi_value, представляющий преобразованное значение JavaScriptBoolean.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToBoolean(), как определено в разделе 7.1.2 Спецификации языка ECMAScript.
Преобразование значения в число
napi_status napi_coerce_to_number(napi_env env,
napi_value value,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое необходимо преобразовать. -
[out] result:napi_value, представляющий преобразованное значение JavaScriptnumber.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToNumber(), как определено в разделе 7.1.3 Спецификации языка ECMAScript. Эта функция потенциально выполняет JS-код, если переданное значение является объектом.
Преобразование значения в объект
napi_status napi_coerce_to_object(napi_env env,
napi_value value,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое необходимо преобразовать. -
[out] result:napi_value, представляющий преобразованное значение JavaScriptObject.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToObject(), как определено в разделе 7.1.13 Спецификации языка ECMAScript.
Преобразование значения в строку
napi_status napi_coerce_to_string(napi_env env,
napi_value value,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое необходимо преобразовать. -
[out] result:napi_value, представляющий преобразованное значение JavaScriptstring.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует абстрактную операцию ToString(), как определено в разделе 7.1.13 Спецификации языка ECMAScript. Эта функция потенциально выполняет JS-код, если переданное значение является объектом.
Оператор typeof
napi_status napi_typeof(napi_env env, napi_value value, napi_valuetype* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, тип которого необходимо получить. -
[out] result: Тип значения JavaScript.
Возвращает napi_ok в случае успешного выполнения API.
-
napi_invalid_argесли типvalueне является известным типом ECMAScript иvalueне является внешним значением.
Этот API имитирует поведение оператора typeof, применяемого к объекту, как определено в разделе 12.5.5 Спецификации языка ECMAScript. Однако существуют некоторые различия:
- Поддержка обнаружения внешних значений.
- Обнаружение
nullкак отдельного типа, в то время как ECMAScripttypeofбудет обнаруживатьobject.
Если у value неверный тип, возвращается ошибка.
Оператор instanceof
napi_status napi_instanceof(napi_env env,
napi_value object,
napi_value constructor,
bool* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] object: Значение JavaScript, которое нужно проверить. -
[in] constructor: Объект JavaScript функции-конструктора, с которым нужно сравнить. -
[out] result: Логическое значение, устанавливаемое в true, еслиobject instanceof constructorравно true.
Возвращает napi_ok в случае успешного выполнения API.
Этот API имитирует вызов оператора instanceof для объекта, как определено в разделе 12.10.4 Спецификации языка ECMAScript.
Проверка на массив
napi_status napi_is_array(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли данный объект массивом.
Возвращает napi_ok в случае успешного выполнения API.
Этот API имитирует вызов операции IsArray для объекта, как определено в разделе 7.2.2 Спецификации языка ECMAScript.
Проверка на ArrayBuffer
napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли данный объект ArrayBuffer.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object буфером массива.
Проверка на буфер
napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Представляет ли данноеnapi_valueобъект типаnode::BufferилиUint8Array.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object буфером или объектом Uint8Array. Для проверки на Uint8Array рекомендуется использовать napi_is_typedarray.
Проверка на дату
napi_status napi_is_date(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли переданныйnapi_valueобъектом JavaScript типаDate.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object датой.
Проверка на ошибку
napi_status napi_is_error(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли переданныйnapi_valueобъектом типаError.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object объектом типа Error.
Проверка на типизированный массив
napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли переданныйnapi_valueтипизированным массивомTypedArray.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object типизированным массивом.
Проверка на DataView
napi_status napi_is_dataview(napi_env env, napi_value value, bool* result) copy
-
[in] env: Окружение, в котором вызывается API. -
[in] value: Значение JavaScript, которое нужно проверить. -
[out] result: Является ли переданныйnapi_valueобъектом типаDataView.
Возвращает napi_ok в случае успешного выполнения API.
Этот API проверяет, является ли переданный Object объектом DataView.
Строгое равенство
napi_status napi_strict_equals(napi_env env,
napi_value lhs,
napi_value rhs,
bool* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] lhs: Значение JavaScript, которое нужно проверить. -
[in] rhs: Значение JavaScript, с которым нужно сравнить. -
[out] result: Являются ли два объектаnapi_valueравными.
Возвращает napi_ok в случае успешного выполнения API.
Этот API реализует алгоритм строгого равенства, как определено в разделе 7.2.14 Спецификации языка ECMAScript.
Отсоединение ArrayBuffer
napi_status napi_detach_arraybuffer(napi_env env,
napi_value arraybuffer) copy -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: JavaScriptArrayBuffer, который нужно отсоединить.
Возвращает napi_ok в случае успеха API. Если передан неотсоединяемый ArrayBuffer, возвращает napi_detachable_arraybuffer_expected.
Как правило, ArrayBuffer считается неотсоединяемым, если он был отсоединён ранее. Движок может накладывать дополнительные условия на то, является ли ArrayBuffer отсоединяемым. Например, V8 требует, чтобы ArrayBuffer был внешним, то есть созданным с помощью napi_create_external_arraybuffer.
Этот API представляет собой вызов операции отсоединения ArrayBuffer, как определено в Разделе 24.1.1.3 спецификации языка ECMAScript.
napi_is_detached_arraybuffer
napi_status napi_is_detached_arraybuffer(napi_env env,
napi_value arraybuffer,
bool* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] arraybuffer: JavaScriptArrayBuffer, который нужно проверить. -
[out] result: Является лиarraybufferотсоединённым.
Возвращает napi_ok в случае успеха API.
ArrayBuffer считается отсоединённым, если его внутренние данные null.
Этот API представляет собой вызов операции проверки отсоединения ArrayBuffer IsDetachedBuffer, как определено в Разделе 24.1.1.2 спецификации языка ECMAScript.
Работа с свойствами JavaScript
Node-API предоставляет набор API для получения и установки свойств объектов JavaScript. Некоторые из этих типов документированы в Разделе 7 спецификации языка ECMAScript.
Свойства в JavaScript представлены как кортеж из ключа и значения. В Node-API все ключи свойств могут быть представлены в одном из следующих форматов:
- Именованные: простая строка UTF8
- Индексированные по целым числам: значение индекса, представленное как
uint32_t - Значение JavaScript: в Node-API они представлены как
napi_value. Это может бытьnapi_value, представляющееstring,number, илиsymbol.
Значения Node-API представлены типом napi_value. Любой вызов Node-API, требующий значения JavaScript, принимает napi_value. Однако, ответственность за обеспечение того, что napi_value имеет ожидаемый типом JavaScript, лежит на вызывающей стороне.
API, документированные в этом разделе, предоставляют простой интерфейс для получения и установки свойств произвольных объектов JavaScript, представленных как napi_value.
Например, рассмотрим следующий фрагмент кода JavaScript:
const obj = {};
obj.myProp = 123; copy Аналогичный результат можно получить, используя значения Node-API с помощью следующего фрагмента:
napi_status status = napi_generic_failure;
// const obj = {}
napi_value obj, value;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create a napi_value for 123
status = napi_create_int32(env, 123, &value);
if (status != napi_ok) return status;
// obj.myProp = 123
status = napi_set_named_property(env, obj, "myProp", value);
if (status != napi_ok) return status; copy Индексированные свойства можно установить аналогичным образом. Рассмотрим следующий фрагмент JavaScript:
const arr = []; arr[123] = 'hello'; copy
Аналогичный результат можно получить, используя значения Node-API с помощью следующего фрагмента:
napi_status status = napi_generic_failure; // const arr = []; napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // Create a napi_value for 'hello' status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &value); if (status != napi_ok) return status; // arr[123] = 'hello'; status = napi_set_element(env, arr, 123, value); if (status != napi_ok) return status; copy
Свойства можно получить, используя API, описанные в этом разделе. Рассмотрим следующий фрагмент JavaScript:
const arr = []; const value = arr[123]; copy
Следующее приблизительно эквивалентно Node-API:
napi_status status = napi_generic_failure; // const arr = [] napi_value arr, value; status = napi_create_array(env, &arr); if (status != napi_ok) return status; // const value = arr[123] status = napi_get_element(env, arr, 123, &value); if (status != napi_ok) return status; copy
Наконец, для повышения производительности можно определить несколько свойств на объекте. Рассмотрим следующий JavaScript:
const obj = {};
Object.defineProperties(obj, {
'foo': { value: 123, writable: true, configurable: true, enumerable: true },
'bar': { value: 456, writable: true, configurable: true, enumerable: true },
}); copy Следующее приблизительно эквивалентно Node-API:
napi_status status = napi_status_generic_failure;
// const obj = {};
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return status;
// Create napi_values for 123 and 456
napi_value fooValue, barValue;
status = napi_create_int32(env, 123, &fooValue);
if (status != napi_ok) return status;
status = napi_create_int32(env, 456, &barValue);
if (status != napi_ok) return status;
// Set the properties
napi_property_descriptor descriptors[] = {
{ "foo", NULL, NULL, NULL, NULL, fooValue, napi_writable | napi_configurable, NULL },
{ "bar", NULL, NULL, NULL, NULL, barValue, napi_writable | napi_configurable, NULL }
}
status = napi_define_properties(env,
obj,
sizeof(descriptors) / sizeof(descriptors[0]),
descriptors);
if (status != napi_ok) return status; copy Структуры
napi_property_attributes
typedef enum {
napi_default = 0,
napi_writable = 1 << 0,
napi_enumerable = 1 << 1,
napi_configurable = 1 << 2,
// Used with napi_define_class to distinguish static properties
// from instance properties. Ignored by napi_define_properties.
napi_static = 1 << 10,
// Default for class methods.
napi_default_method = napi_writable | napi_configurable,
// Default for object properties, like in JS obj[prop].
napi_default_jsproperty = napi_writable |
napi_enumerable |
napi_configurable,
} napi_property_attributes; copy napi_property_attributes — это флаги, используемые для управления поведением свойств, установленных на объекте JavaScript. Помимо napi_static, они соответствуют атрибутам, перечисленным в Разделе 6.1.7.1 спецификации языка ECMAScript. Они могут быть одним или несколькими из следующих битовых флагов:
-
napi_default: Нет явных атрибутов, заданных для свойства. По умолчанию свойство является только для чтения, не перечисляемым и не настраиваемым. -
napi_writable: Свойство записываемое. -
napi_enumerable: Свойство перечисляемое. -
napi_configurable: Свойство настраиваемое, как определено в Разделе 6.1.7.1 спецификации языка ECMAScript. -
napi_static: Свойство будет определено как статическое свойство класса, а не свойства экземпляра (по умолчанию). Используется только вnapi_define_class. Игнорируется вnapi_define_properties. -
napi_default_method: Как метод в классе JS, свойство настраиваемое и записываемое, но не перечисляемое. -
napi_default_jsproperty: Как свойство, установленное через присваивание в JavaScript, свойство записываемое, перечисляемое и настраиваемое.
napi_property_descriptor
typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;
napi_callback method;
napi_callback getter;
napi_callback setter;
napi_value value;
napi_property_attributes attributes;
void* data;
} napi_property_descriptor; copy -
utf8name: Необязательная строка, описывающая ключ свойства, закодированная в UTF8. Для свойства должен быть указан один изutf8nameилиname. -
name: Необязательноеnapi_value, указывающее на JavaScript-строку или символ, используемые в качестве ключа свойства. Для свойства должен быть указан один изutf8nameилиname. -
value: Значение, возвращаемое при чтении свойства, если оно является свойством данных. Если передано, установитеgetter,setter,methodиdataвNULL(поскольку эти члены не будут использоваться). -
getter: Функция, вызываемая при чтении свойства. Если передана, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Эта функция вызывается неявно во время выполнения при обращении к свойству из кода JavaScript (или при чтении свойства с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
setter: Функция, вызываемая при записи в свойство. Если передана, установитеvalueиmethodвNULL(поскольку эти члены не будут использоваться). Эта функция вызывается неявно во время выполнения при изменении значения свойства из кода JavaScript (или при записи в свойство с помощью вызова Node-API).napi_callbackсодержит дополнительные сведения. -
method: Установите это значение, чтобы сделать свойствоvalueобъекта-описателя свойством JavaScript, представленным какmethod. Если передано, установитеvalue,getterиsetterвNULL(поскольку эти члены не будут использоваться).napi_callbackсодержит дополнительные сведения. -
attributes: Атрибуты, связанные с конкретным свойством. См.napi_property_attributes. -
data: Данные обратного вызова, передаваемые вmethod,getterиsetterпри вызове этой функции.
Функции
napi_get_property_names
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого необходимо получить свойства. -
[out] result:napi_valueпредставляющий массив значений JavaScript, представляющих имена свойств объекта. 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); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого необходимо получить свойства. -
[in] key_mode: Включать ли свойства прототипа. -
[in] key_filter: Какие свойства получить (перечисляемые/доступные/записываемые). -
[in] key_conversion: Преобразовывать ли индексированные ключи свойств в строки. -
[out] result:napi_valueпредставляющий массив значений JavaScript, представляющих имена свойств объекта.napi_get_array_lengthиnapi_get_elementмогут использоваться для перебораresult.
Возвращает napi_ok при успешном выполнении API.
Это API возвращает массив, содержащий имена доступных свойств объекта.
napi_set_property
napi_status napi_set_property(napi_env env,
napi_value object,
napi_value key,
napi_value value); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, на котором нужно установить свойство. -
[in] key: Имя свойства для установки. -
[in] value: Значение свойства.
Возвращает napi_ok при успешном выполнении API.
Это API устанавливает свойство на переданный Object.
napi_get_property
napi_status napi_get_property(napi_env env,
napi_value object,
napi_value key,
napi_value* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого необходимо получить свойство. -
[in] key: Имя свойства для получения. -
[out] result: Значение свойства.
Возвращает napi_ok при успешном выполнении API.
Это API получает запрашиваемое свойство из переданного Object.
napi_has_property
napi_status napi_has_property(napi_env env,
napi_value object,
napi_value key,
bool* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для проверки. -
[in] key: Имя свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok при успешном выполнении API.
Это API проверяет, содержит ли переданный Object свойство с заданным именем.
napi_delete_property
napi_status napi_delete_property(napi_env env,
napi_value object,
napi_value key,
bool* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для проверки. -
[in] key: Имя свойства для удаления. -
[out] result: Удалось ли удалить свойство.resultнеобязательно можно игнорировать, передавNULL.
Возвращает napi_ok если API выполнилась успешно.
Этот API пытается удалить собственную свойство key из object.
napi_has_own_property
napi_status napi_has_own_property(napi_env env,
napi_value object,
napi_value key,
bool* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] key: Название собственного свойства, существование которого нужно проверить. -
[out] result: Существует ли собственное свойство в объекте или нет.
Возвращает napi_ok если API выполнилась успешно.
Этот API проверяет, содержит ли переданный Object указанное собственное свойство. key должен быть string или symbol, иначе будет выброшено исключение. Node-API не будет выполнять никаких преобразований между типами данных.
napi_set_named_property
napi_status napi_set_named_property(napi_env env,
napi_value object,
const char* utf8Name,
napi_value value); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, в котором нужно установить свойство. -
[in] utf8Name: Название свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok если API выполнилась успешно.
Этот метод эквивалентен вызову napi_set_property с 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); copy -
[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); copy -
[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); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого нужно установить свойства. -
[in] index: Индекс свойства, которое нужно установить. -
[in] value: Значение свойства.
Возвращает napi_ok если API выполнилась успешно.
Этот API устанавливает элемент в переданном Object.
napi_get_element
napi_status napi_get_element(napi_env env,
napi_value object,
uint32_t index,
napi_value* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойство. -
[in] index: Индекс свойства, которое нужно получить. -
[out] result: Значение свойства.
Возвращает napi_ok если API выполнилась успешно.
Этот API получает элемент по запрошенному индексу.
napi_has_element
napi_status napi_has_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] index: Индекс свойства, существование которого нужно проверить. -
[out] result: Существует ли свойство в объекте или нет.
Возвращает napi_ok если API выполнилась успешно.
Этот API возвращает, содержит ли переданный Object элемент по запрошенному индексу.
napi_delete_element
napi_status napi_delete_element(napi_env env,
napi_value object,
uint32_t index,
bool* result); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект для запроса. -
[in] index: Индекс свойства для удаления. -
[out] result: Удалось ли удалить элемент или нет.resultможно при желании проигнорировать, передавNULL.
Возвращает napi_ok если API выполнилась успешно.
Этот API пытается удалить указанный index из object.
napi_define_properties
napi_status napi_define_properties(napi_env env,
napi_value object,
size_t property_count,
const napi_property_descriptor* properties); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, из которого нужно получить свойства. -
[in] property_count: Количество элементов в массивеproperties. -
[in] properties: Массив дескрипторов свойств.
Возвращает napi_ok если API выполнилась успешно.
Этот метод позволяет эффективно определять несколько свойств в данном объекте. Свойства определяются с помощью дескрипторов свойств (см. napi_property_descriptor). Учитывая массив таких дескрипторов свойств, этот API установит свойства в объекте по одному, как определено DefineOwnProperty() (описано в разделе 9.1.6 спецификации ECMA-262).
napi_object_freeze
napi_status napi_object_freeze(napi_env env,
napi_value object); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, который нужно заморозить.
Возвращает napi_ok если API выполнилась успешно.
Этот метод замораживает данный объект. Это предотвращает добавление новых свойств, удаление существующих свойств, изменение перечисляемости, конфигурируемости или записи существующих свойств, а также изменение значений существующих свойств. Также предотвращает изменение прототипа объекта. Это описано в разделе 19.1.2.6 спецификации ECMA-262.
napi_object_seal
napi_status napi_object_seal(napi_env env,
napi_value object); copy -
[in] env: Среда, в которой вызывается вызов Node-API. -
[in] object: Объект, который нужно запечатать.
Возвращает napi_ok если API выполнилась успешно.
Этот метод запечатывает данный объект. Это предотвращает добавление новых свойств, а также помечает все существующие свойства как неконфигурируемые. Это описано в разделе 19.1.2.20 спецификации ECMA-262.
Работа с функциями JavaScript
Node-API предоставляет набор API, которые позволяют коду JavaScript вызывать функции нативного кода. Node-API, поддерживающие обратные вызовы в нативный код, принимают функции обратного вызова, представленные типом napi_callback. Когда JavaScript VM вызывает нативный код, вызывается функция napi_callback . API, документированные в этом разделе, позволяют функции обратного вызова выполнять следующие действия:
- Получить информацию о контексте, в котором был вызван обратный вызов.
- Получить аргументы, переданные в обратный вызов.
- Возвратить значение
napi_valueиз обратного вызова.
Кроме того, Node-API предоставляет набор функций, позволяющих вызывать функции JavaScript из нативного кода. Можно либо вызвать функцию как обычный вызов функции JavaScript, либо как конструкторскую функцию.
Любые данные, отличные от NULL , которые передаются этому API через поле data элементов napi_property_descriptor, могут быть связаны с object и освобождены всякий раз, когда object собирается сборщиком мусора, передав и object, и данные функции napi_add_finalizer.
napi_call_function
NAPI_EXTERN napi_status napi_call_function(napi_env env,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] recv: Переданное значениеthisвызываемой функции. -
[in] func: Представлениеnapi_valueвызываемой функции JavaScript. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массивnapi_values, представляющий JavaScript-значения, переданные в качестве аргументов функции. -
[out] result: Представлениеnapi_valueвозвращаемого JavaScript-объекта.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать объект функции JavaScript из нативного дополнения. Это основной механизм обратного вызова из нативного кода дополнения в JavaScript. Для специального случая вызова JavaScript после асинхронной операции см. napi_make_callback.
Пример использования может выглядеть следующим образом. Рассмотрим следующий фрагмент JavaScript:
function AddTwo(num) {
return num + 2;
}
global.AddTwo = AddTwo; copy Затем, вышеупомянутую функцию можно вызвать из нативного дополнения с помощью следующего кода:
// Get the function named "AddTwo" on the global object napi_value global, add_two, arg; napi_status status = napi_get_global(env, &global); if (status != napi_ok) return; status = napi_get_named_property(env, global, "AddTwo", &add_two); if (status != napi_ok) return; // const arg = 1337 status = napi_create_int32(env, 1337, &arg); if (status != napi_ok) return; napi_value* argv = &arg; size_t argc = 1; // AddTwo(arg); napi_value return_val; status = napi_call_function(env, global, add_two, argc, argv, &return_val); if (status != napi_ok) return; // Convert the result back to a native type int32_t result; status = napi_get_value_int32(env, return_val, &result); if (status != napi_ok) return; copy
napi_create_function
napi_status napi_create_function(napi_env env,
const char* utf8name,
size_t length,
napi_callback cb,
void* data,
napi_value* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] utf8Name: Необязательное имя функции, закодированное в UTF8. Оно отображается в JavaScript как свойствоnameнового объекта функции. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTH, если она завершается нулём. -
[in] cb: Нативная функция, которая должна вызываться при вызове этого объекта функции.napi_callbackсодержит более подробную информацию. -
[in] data: Контекст данных, предоставленный пользователем. Он будет передан обратно в функцию при её последующем вызове. -
[out] result: Представлениеnapi_valueобъекта JavaScript-функции для вновь созданной функции.
Возвращает napi_ok в случае успешного выполнения API.
Этот API позволяет автору дополнения создавать объект функции в нативном коде. Это основной механизм вызова в нативный код дополнения из JavaScript.
Новой созданная функция не отображается автоматически в скрипте после этого вызова. Вместо этого, свойство должно быть явно установлено на любом объекте, видимом для JavaScript, чтобы функция стала доступной из скрипта.
Для экспорта функции как части экспорта модуля дополнения установите вновь созданную функцию на объект экспорта. Пример модуля может выглядеть следующим образом:
napi_value SayHello(napi_env env, napi_callback_info info) {
printf("Hello\n");
return NULL;
}
napi_value Init(napi_env env, napi_value exports) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, 0, SayHello, NULL, &fn);
if (status != napi_ok) return NULL;
status = napi_set_named_property(env, exports, "sayHello", fn);
if (status != napi_ok) return NULL;
return exports;
}
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init) copy Учитывая вышеприведённый код, дополнение можно использовать из JavaScript следующим образом:
const myaddon = require('./addon');
myaddon.sayHello(); copy Строка, переданная в require() , является именем целевого объекта в binding.gyp , ответственного за создание файла .node.
Любые данные, отличные от NULL , которые передаются этому API через параметр data, могут быть связаны с результирующей функцией JavaScript (которая возвращается в параметре result) и освобождаться всякий раз, когда функция собирается сборщиком мусора, передав и функцию JavaScript, и данные в napi_add_finalizer.
Объекты JavaScript-функций описаны в разделе 19.2 спецификации языка ECMAScript.
napi_get_cb_info
napi_status napi_get_cb_info(napi_env env,
napi_callback_info cbinfo,
size_t* argc,
napi_value* argv,
napi_value* thisArg,
void** data) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация об обратном вызове, переданная в функцию обратного вызова. -
[in-out] argc: Указывает длину массиваargvи получает фактическое количество аргументов.argcможно необязательно игнорировать, передавNULL. -
[out] argv: Массив C изnapi_value, в который будут скопированы аргументы. Если аргументов больше, чем указанное количество, будут скопированы только запрошенные аргументы. Если предоставлено меньше аргументов, чем заявлено, остальные элементыargvзаполняются значениямиnapi_value, представляющимиundefined.argvможно необязательно игнорировать, передавNULL. -
[out] thisArg: Получает JavaScript-аргументthisдля вызова.thisArgможно необязательно игнорировать, передавNULL. -
[out] data: Получает указатель на данные для обратного вызова.dataможно необязательно игнорировать, передавNULL.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод используется внутри функции обратного вызова для извлечения деталей о вызове, таких как аргументы и указатель this из заданной информации о обратном вызове.
napi_get_new_target
napi_status napi_get_new_target(napi_env env,
napi_callback_info cbinfo,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cbinfo: Информация об обратном вызове, переданная в функцию обратного вызова. -
[out] result:new.targetвызова конструктора.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает new.target вызова конструктора. Если текущий обратный вызов не является вызовом конструктора, результат равен NULL.
napi_new_instance
napi_status napi_new_instance(napi_env env,
napi_value cons,
size_t argc,
napi_value* argv,
napi_value* result) copy -
[in] env: Окружение, в котором вызывается API. -
[in] cons:napi_valueпредставляющий функцию JavaScript, которая будет вызвана в качестве конструктора. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив JavaScript-значений какnapi_value, представляющих аргументы конструктора. Еслиargcравно нулю, этот параметр можно опустить, передавNULL. -
[out] result:napi_value, представляющий возвращаемый JavaScript-объект, который в данном случае является созданным объектом.
Этот метод используется для создания нового JavaScript-значения с использованием заданного napi_value , представляющего конструктор для объекта. Например, рассмотрим следующий фрагмент:
function MyObject(param) {
this.param = param;
}
const arg = 'hello';
const value = new MyObject(arg); copy Следующее можно приблизительно смоделировать в Node-API с помощью следующего фрагмента:
// Get the constructor function MyObject napi_value global, constructor, arg, value; napi_status status = napi_get_global(env, &global); if (status != napi_ok) return; status = napi_get_named_property(env, global, "MyObject", &constructor); if (status != napi_ok) return; // const arg = "hello" status = napi_create_string_utf8(env, "hello", NAPI_AUTO_LENGTH, &arg); if (status != napi_ok) return; napi_value* argv = &arg; size_t argc = 1; // const value = new MyObject(arg) status = napi_new_instance(env, constructor, argc, argv, &value); copy
Возвращает napi_ok в случае успешного выполнения API.
Обёртка объекта
Node-API предоставляет способ «обёртки» классов и экземпляров C++ таким образом, чтобы конструктор и методы класса можно было вызывать из JavaScript.
- API
napi_define_classопределяет JavaScript-класс с конструктором, статическими свойствами и методами, а также свойствами и методами экземпляров, соответствующими классу C++. - Когда код JavaScript вызывает конструктор, обратный вызов конструктора использует
napi_wrapдля обёртки нового экземпляра C++ в JavaScript-объект, а затем возвращает обёрнутый объект. - Когда код JavaScript вызывает метод или аксессор свойства класса, вызывается соответствующая
napi_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...
} copy Ссылка должна быть освобождена, когда она больше не нужна.
В некоторых случаях napi_instanceof() недостаточно для обеспечения того, что JavaScript-объект является обёрткой для определённого типа нативного кода. Это особенно актуально, когда обёрнутые JavaScript-объекты передаются обратно в плагин через статические методы, а не как this значение методов прототипа. В таких случаях существует вероятность неправильного развёртывания.
const myAddon = require('./build/Release/my_addon.node');
// `openDatabase()` returns a JavaScript object that wraps a native database
// handle.
const dbHandle = myAddon.openDatabase();
// `query()` returns a JavaScript object that wraps a native query handle.
const queryHandle = myAddon.query(dbHandle, 'Gimme ALL the things!');
// There is an accidental error in the line below. The first parameter to
// `myAddon.queryHasRecords()` should be the database handle (`dbHandle`), not
// the query handle (`query`), so the correct condition for the while-loop
// should be
//
// myAddon.queryHasRecords(dbHandle, queryHandle)
//
while (myAddon.queryHasRecords(queryHandle, dbHandle)) {
// retrieve records
} copy В приведённом выше примере myAddon.queryHasRecords() — это метод, принимающий два аргумента. Первый — дескриптор базы данных, а второй — дескриптор запроса. Внутренне он разворачивает первый аргумент и приводит полученный указатель к указателю на дескриптор базы данных. Затем он разворачивает второй аргумент и приводит полученный указатель к указателю на дескриптор запроса. Если аргументы переданы в неправильном порядке, приведение типов сработает, однако существует высокая вероятность того, что основная операция базы данных завершится неудачей или даже приведёт к доступу к недействительному участку памяти.
Для обеспечения того, что указатель, полученный из первого аргумента, действительно является указателем на дескриптор базы данных, и аналогично, что указатель, полученный из второго аргумента, действительно является указателем на дескриптор запроса, реализация queryHasRecords() должна выполнить валидацию типа. Сохранение конструктора JavaScript-класса, из которого был создан дескриптор базы данных, и конструктора, из которого был создан дескриптор запроса, в napi_ref может помочь, поскольку napi_instanceof() можно использовать для проверки того, что экземпляры, переданные в queryHashRecords(), действительно имеют правильный тип.
К сожалению, napi_instanceof() не защищает от манипуляций с прототипом. Например, прототип экземпляра дескриптора базы данных может быть установлен в прототип конструктора экземпляров дескриптора запроса. В этом случае экземпляр дескриптора базы данных может быть принят за экземпляр дескриптора запроса, и он пройдёт napi_instanceof() проверку на экземпляр дескриптора запроса, всё ещё содержа при этом указатель на дескриптор базы данных.
Для решения этой проблемы Node-API предоставляет возможности тегов типов.
Тег типа — это 128-битное целое число, уникальное для плагина. Node-API предоставляет структуру napi_type_tag для хранения тега типа. Когда такое значение передаётся вместе с JavaScript-объектом или external значением, хранящимся в napi_value в napi_type_tag_object(), JavaScript-объект будет «меченым» тегом типа. Отметка невидима со стороны JavaScript. Когда JavaScript-объект попадает в нативное связывание, napi_check_object_type_tag() можно использовать вместе с исходным тегом типа для определения того, был ли JavaScript-объект ранее «помечен» тегом типа. Это создаёт возможность проверки типов с большей точностью, чем napi_instanceof() может обеспечить, поскольку такие теги типов сохраняются при манипуляциях с прототипом и при загрузке/перезагрузке плагина.
Продолжая вышеприведенный пример, следующий каркас реализации плагина демонстрирует использование napi_type_tag_object() и napi_check_object_type_tag().
// This value is the type tag for a database handle. The command
//
// uuidgen | sed -r -e 's/-//g' -e 's/(.{16})(.*)/0x\1, 0x\2/'
//
// can be used to obtain the two values with which to initialize the structure.
static const napi_type_tag DatabaseHandleTypeTag = {
0x1edf75a38336451d, 0xa5ed9ce2e4c00c38
};
// This value is the type tag for a query handle.
static const napi_type_tag QueryHandleTypeTag = {
0x9c73317f9fad44a3, 0x93c3920bf3b0ad6a
};
static napi_value
openDatabase(napi_env env, napi_callback_info info) {
napi_status status;
napi_value result;
// Perform the underlying action which results in a database handle.
DatabaseHandle* dbHandle = open_database();
// Create a new, empty JS object.
status = napi_create_object(env, &result);
if (status != napi_ok) return NULL;
// Tag the object to indicate that it holds a pointer to a `DatabaseHandle`.
status = napi_type_tag_object(env, result, &DatabaseHandleTypeTag);
if (status != napi_ok) return NULL;
// Store the pointer to the `DatabaseHandle` structure inside the JS object.
status = napi_wrap(env, result, dbHandle, NULL, NULL, NULL);
if (status != napi_ok) return NULL;
return result;
}
// Later when we receive a JavaScript object purporting to be a database handle
// we can use `napi_check_object_type_tag()` to ensure that it is indeed such a
// handle.
static napi_value
query(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc = 2;
napi_value argv[2];
bool is_db_handle;
status = napi_get_cb_info(env, info, &argc, argv, NULL, NULL);
if (status != napi_ok) return NULL;
// Check that the object passed as the first parameter has the previously
// applied tag.
status = napi_check_object_type_tag(env,
argv[0],
&DatabaseHandleTypeTag,
&is_db_handle);
if (status != napi_ok) return NULL;
// Throw a `TypeError` if it doesn't.
if (!is_db_handle) {
// Throw a TypeError.
return NULL;
}
} copy
napi_define_class
napi_status napi_define_class(napi_env env,
const char* utf8name,
size_t length,
napi_callback constructor,
void* data,
size_t property_count,
const napi_property_descriptor* properties,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] utf8name: Имя JavaScript-конструкторной функции. Для ясности рекомендуется использовать имя C++-класса при обёртывании C++-класса. -
[in] length: Длинаutf8nameв байтах илиNAPI_AUTO_LENGTH, если она имеет нулевую терминируемость. -
[in] constructor: Функция обратного вызова, обрабатывающая создание экземпляров класса. При обёртывании C++-класса этот метод должен быть статическим членом с сигнатуройnapi_callback. Конструктор C++-класса использовать нельзя.napi_callbackпредоставляет более подробную информацию. -
[in] data: Дополнительные данные, передаваемые обратнему вызову конструктора как свойствоdataинформации о обратном вызове. -
[in] property_count: Количество элементов в массиве аргументовproperties. -
[in] properties: Массив описателей свойств, описывающих статические и экземплярные данные, аксессоры и методы класса. См.napi_property_descriptor. -
[out] result:napi_valueпредставляющий конструктор функцию класса.
Возвращает napi_ok в случае успешного выполнения API.
Определяет JavaScript-класс, включая:
- Функцию JavaScript-конструктора, имеющую имя класса. При обёртывании соответствующего C++-класса, обратный вызов, переданный через
constructorможет быть использован для создания нового экземпляра C++-класса, который затем может быть помещён в экземпляр JavaScript-объекта, создаваемого с помощьюnapi_wrap. - Свойства в конструкторной функции, чья реализация может вызывать соответствующие статические данные, аксессоры и методы C++-класса (определённые описателями свойств с атрибутом
napi_static). - Свойства в объекте
prototypeконструкторной функции. При обёртывании C++-класса, нестатические данные, аксессоры и методы C++-класса можно вызывать из статических функций, заданных в описателях свойств без атрибутаnapi_staticпосле получения экземпляра C++-класса, размещённого внутри экземпляра JavaScript-объекта, с помощьюnapi_unwrap.
При обёртывании C++-класса, обратный вызов конструктора C++, переданный через constructor, должен быть статическим методом класса, вызывающим фактический конструктор класса, затем обёртывающим новый экземпляр C++ в JavaScript-объект и возвращающим обёрнутый объект. См. napi_wrap для получения подробностей.
Функция JavaScript-конструктора, возвращаемая из napi_define_class, часто сохраняется и используется позднее для создания новых экземпляров класса из нативного кода и/или для проверки того, являются ли предоставленные значения экземплярами класса. В этом случае, чтобы предотвратить сборку мусора функции, можно создать сильную постоянную ссылку на неё с помощью napi_create_reference, гарантируя, что счётчик ссылок поддерживается >= 1.
Любые не-NULL данные, которые передаются в этот API через параметр data или через поле data элементов массива napi_property_descriptor, могут быть связаны с результирующим JavaScript-конструктором (который возвращается в параметре result) и освобождаться, когда класс собирается мусором путём передачи как JavaScript-функции, так и данных в napi_add_finalizer.
napi_wrap
napi_status napi_wrap(napi_env env,
napi_value js_object,
void* native_object,
napi_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] js_object: JavaScript-объект, который будет обёрткой для нативного объекта. -
[in] native_object: Нативный экземпляр, который будет обёрнут в JavaScript-объект. -
[in] finalize_cb: Необязательный нативный обратный вызов, который может быть использован для освобождения нативного экземпляра, когда JavaScript-объект был собран мусором.napi_finalizeпредоставляет более подробную информацию. -
[in] finalize_hint: Необязательный контекстуальный подсказка, который передаётся обратному вызову освобождения. -
[out] result: Необязательная ссылка на обёрнутый объект.
Возвращает napi_ok в случае успешного выполнения API.
Обёртка нативного экземпляра в JavaScript-объект. Нативный экземпляр можно получить позже, используя napi_unwrap().
Когда код JavaScript вызывает конструктор класса, определённого с помощью napi_define_class(), вызывается napi_callback для конструктора. После создания экземпляра нативного класса, обратный вызов должен вызвать napi_wrap() для обёртки недавно созданного экземпляра в уже созданный JavaScript-объект, являющийся аргументом this обратного вызова конструктора. (Этот this объект был создан из прототипа prototype конструкторной функции, поэтому он уже имеет определения всех свойств и методов экземпляров.)
Обычно при обёртывании экземпляра класса должен быть предоставлен обратный вызов освобождения, который просто удаляет нативный экземпляр, полученный в качестве аргумента data обратного вызова освобождения.
Необязательная возвращаемая ссылка изначально является слабой ссылкой, то есть имеет счётчик ссылок 0. Обычно этот счётчик ссылок временно увеличивается во время асинхронных операций, требующих сохранения актуальности экземпляра.
Внимание: необязательная возвращаемая ссылка (если получена) должна быть удалена через napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова освобождения. Если она удалена до этого, то обратный вызов освобождения может никогда не быть вызван. Поэтому при получении ссылки также требуется обратный вызов освобождения для правильной утилизации ссылки.
Обратные вызовы освобождения могут быть отложены, создавая окно, в котором объект был собран мусором (и слабая ссылка недоступна), но обратный вызов освобождения ещё не был вызван. При использовании napi_get_reference_value() на слабых ссылках, возвращаемых napi_wrap(), вы должны обрабатывать пустой результат.
Вызов napi_wrap() второй раз для объекта вернёт ошибку. Чтобы связать другой нативный экземпляр с объектом, сначала используйте napi_remove_wrap().
napi_unwrap
napi_status napi_unwrap(napi_env env,
napi_value js_object,
void** result); copy -
[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); copy -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: Объект, связанный с нативным экземпляром. -
[out] result: Указатель на обернутый нативный экземпляр.
Возвращает napi_ok в случае успешного выполнения API.
Извлекает нативный экземпляр, который был ранее обернут в JavaScript-объект js_object с помощью napi_wrap() и удаляет обёртку. Если был связан обратный вызов для завершения, он больше не будет вызываться при сборке мусора JavaScript-объекта.
napi_type_tag_object
napi_status napi_type_tag_object(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag); copy -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект или external для маркировки. -
[in] type_tag: Тег, с помощью которого объект должен быть помечен.
Возвращает napi_ok в случае успешного выполнения API.
Связывает значение указателя type_tag с JavaScript-объектом или external. napi_check_object_type_tag() может затем использоваться для сравнения тега, который был прикреплён к объекту, с тегом, принадлежащим дополнению, чтобы убедиться, что объект имеет правильный тип.
Если у объекта уже есть связанный тег типа, этот API вернёт napi_invalid_arg.
napi_check_object_type_tag
napi_status napi_check_object_type_tag(napi_env env,
napi_value js_object,
const napi_type_tag* type_tag,
bool* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект или external, тег типа которого необходимо проверить. -
[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* finalize_data,
node_api_nogc_finalize finalize_cb,
void* finalize_hint,
napi_ref* result); copy -
[in] env: Окружение, в котором вызывается API. -
[in] js_object: JavaScript-объект, к которому будет прикреплены нативные данные. -
[in] finalize_data: Необязательные данные, передаваемые вfinalize_cb. -
[in] finalize_cb: Нативный обратный вызов, который будет использоваться для освобождения нативных данных, когда JavaScript-объект будет собран мусором.napi_finalizeсодержит более подробную информацию. -
[in] finalize_hint: Необязательное контекстное значение, передаваемое обратному вызову завершения. -
[out] result: Необязательная ссылка на JavaScript-объект.
Возвращает napi_ok в случае успешного выполнения API.
Добавляет обратный вызов napi_finalize, который будет вызван, когда JavaScript-объект в js_object будет собран мусором.
Этот API может вызываться несколько раз для одного JavaScript-объекта.
Внимание: Необязательная возвращаемая ссылка (если получена) должна быть удалена с помощью napi_delete_reference ТОЛЬКО в ответ на вызов обратного вызова завершения. Если она удалена до этого, обратный вызов завершения может никогда не быть вызван. Таким образом, при получении ссылки необходим и обратный вызов завершения для правильного удаления ссылки.
node_api_post_finalizer
napi_status node_api_post_finalizer(node_api_nogc_env env,
napi_finalize finalize_cb,
void* finalize_data,
void* finalize_hint); copy -
[in] env: Окружение, в котором вызывается API. -
[in] finalize_cb: Нативный обратный вызов, который будет использоваться для освобождения нативных данных, когда JavaScript-объект будет собран мусором.napi_finalizeсодержит более подробную информацию. -
[in] finalize_data: Необязательные данные, передаваемые вfinalize_cb. -
[in] finalize_hint: Необязательное контекстное значение, передаваемое обратному вызову завершения.
Возвращает napi_ok в случае успешного выполнения API.
Планирует вызов обратного вызова napi_finalize асинхронно в цикле событий.
Обычно финализаторы вызываются во время сбора мусора (GC). В этот момент вызов любого Node-API, который может привести к изменениям в состоянии GC, будет заблокирован и приведёт к сбою Node.js.
node_api_post_finalizer помогает обойти это ограничение, позволяя дополнению отложить вызовы таких Node-API до момента вне цикла завершения GC.
Простые асинхронные операции
Модули дополнений часто нуждаются в использовании асинхронных помощников из libuv в рамках своей реализации. Это позволяет им планировать выполнение задач асинхронно, чтобы их методы могли возвращать результат до завершения работы. Это позволяет избежать блокирования общего выполнения приложения Node.js.
Node-API предоставляет стабильный ABI интерфейс для этих вспомогательных функций, охватывающий наиболее распространённые асинхронные случаи использования.
Node-API определяет структуру napi_async_work для управления асинхронными рабочими процессами. Экземпляры создаются/удаляются с помощью napi_create_async_work и napi_delete_async_work.
Обратные вызовы execute и complete — это функции, которые будут вызваны, когда исполняющий процесс готов к выполнению и при завершении задачи соответственно.
Функция execute должна избегать выполнения любых вызовов Node-API, которые могут привести к выполнению JavaScript или взаимодействию с объектами JavaScript. Чаще всего любой код, которому необходимо выполнять вызовы Node-API, должен быть выполнен в обратном вызове complete вместо этого. Избегайте использования параметра napi_env в обратном вызове выполнения, так как это, скорее всего, приведёт к выполнению JavaScript.
Эти функции реализуют следующие интерфейсы:
typedef void (*napi_async_execute_callback)(napi_env env,
void* data);
typedef void (*napi_async_complete_callback)(napi_env env,
napi_status status,
void* data); copy При вызове этих методов параметр data будет содержать данные, предоставленные дополнением void*, которые были переданы в вызов napi_create_async_work.
После создания асинхронный рабочий процесс может быть помещён в очередь на выполнение с помощью функции napi_queue_async_work:
napi_status napi_queue_async_work(node_api_nogc_env env,
napi_async_work work); copy napi_cancel_async_work может быть использована, если работу необходимо отменить до начала её выполнения.
После вызова napi_cancel_async_work обратный вызов complete будет вызван со значением статуса napi_cancelled. Работа не должна быть удалена до вызова обратного вызова complete, даже если она была отменена.
napi_create_async_work
napi_status napi_create_async_work(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
void* data,
napi_async_work* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемый для диагностической информации, раскрываемой APIasync_hooks. -
[in] execute: Нативная функция, которая должна вызываться для асинхронного выполнения логики. Эта функция вызывается из потока пула рабочих процессов и может выполняться параллельно главному потоку обработки событий. -
[in] complete: Нативная функция, которая вызывается при завершении асинхронной логики или при её отмене. Эта функция вызывается из главного потока обработки событий.napi_async_complete_callbackсодержит более подробную информацию. -
[in] data: Контекст данных, предоставленный пользователем. Он будет возвращён в функции выполнения и завершения. -
[out] result:napi_async_work*, который является дескриптором новой созданной асинхронной работы.
Возвращает napi_ok в случае успеха API.
Этот API выделяет объект работы, используемый для асинхронного выполнения логики. Он должен быть освобождён с помощью napi_delete_async_work, когда работа больше не требуется.
async_resource_name должен быть строкой, закодированной в UTF-8, с завершающим нулём.
Идентификатор async_resource_name предоставляется пользователем и должен отражать тип выполняемой асинхронной работы. Также рекомендуется применять именование в идентификаторе, например, включая имя модуля. См. async_hooks документацию для получения дополнительной информации.
napi_delete_async_work
napi_status napi_delete_async_work(napi_env env,
napi_async_work work); copy -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращённый вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API освобождает ранее выделенный объект работы.
Этот API может быть вызван даже при наличии ожидающей JavaScript ошибки.
napi_queue_async_work
napi_status napi_queue_async_work(node_api_nogc_env env,
napi_async_work work); copy -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращённый вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API запрашивает планирование ранее выделенной работы для выполнения. После успешного возврата этот API не должен вызываться снова с тем же элементом napi_async_work, в противном случае результат будет неопределённым.
napi_cancel_async_work
napi_status napi_cancel_async_work(node_api_nogc_env env,
napi_async_work work); copy -
[in] env: Среда, в которой вызывается API. -
[in] work: Дескриптор, возвращённый вызовомnapi_create_async_work.
Возвращает napi_ok в случае успеха API.
Этот API отменяет запланированную работу, если она ещё не начата. Если она уже начала выполняться, её отменить нельзя, и будет возвращено значение napi_generic_failure. В случае успеха обратный вызов complete будет вызван со значением статуса napi_cancelled. Работа не должна быть удалена до вызова обратного вызова complete, даже если она была успешно отменена.
Этот API может быть вызван даже при наличии ожидающей JavaScript ошибки.
Настраиваемые асинхронные операции
Простые асинхронные API-интерфейсы могут быть неприменимы для каждой ситуации. При использовании других асинхронных механизмов необходимы следующие API-интерфейсы, чтобы гарантировать, что асинхронная операция должным образом отслеживается исполняемой средой.
napi_async_init
napi_status napi_async_init(napi_env env,
napi_value async_resource,
napi_value async_resource_name,
napi_async_context* result) copy-
[in] env: Окружение, в котором вызывается API. -
[in] async_resource: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам и к которому можно получить доступ с помощьюasync_hooks.executionAsyncResource(). -
[in] async_resource_name: Идентификатор типа ресурса, предоставляемого для диагностической информации, представленной APIasync_hooks. -
[out] result: Инициализированный контекст асинхронной операции.
Возвращает napi_ok в случае успешного выполнения API.
Объект async_resource необходимо поддерживать до тех пор, пока не будет вызван napi_async_destroy, чтобы обеспечить корректную работу связанных с ним API-действий. Чтобы сохранить совместимость ABI с предыдущими версиями, API не поддерживают сильную ссылку на объекты async_resource, чтобы избежать утечки памяти. Однако, если объект async_resource будет собран сборщиком мусора JavaScript до уничтожения napi_async_context функцией napi_async_destroy, вызов связанных с napi_async_context API-интерфейсов, таких как napi_open_callback_scope и napi_make_callback, может привести к проблемам, таким как потеря контекста асинхронной операции при использовании API AsyncLocalStorage.
Чтобы сохранить совместимость ABI с предыдущими версиями, передача NULL в качестве async_resource не приводит к ошибке. Однако это не рекомендуется, так как это может привести к нежелательному поведению с хуками async_hooks init и async_hooks.executionAsyncResource(), поскольку ресурс теперь необходим для реализации async_hooks API, чтобы обеспечить связь между асинхронными обратными вызовами.
napi_async_destroy
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context); copy-
[in] env: Окружение, в котором вызывается API. -
[in] async_context: Контекст асинхронной операции, который необходимо уничтожить.
Возвращает napi_ok в случае успешного выполнения API.
Этот API можно вызывать, даже если в JavaScript есть ожидающее исключение.
napi_make_callback
NAPI_EXTERN napi_status napi_make_callback(napi_env env,
napi_async_context async_context,
napi_value recv,
napi_value func,
size_t argc,
const napi_value* argv,
napi_value* result); copy-
[in] env: Окружение, в котором вызывается API. -
[in] async_context: Контекст асинхронной операции, вызывающей обратный вызов. Обычно это значение, полученное ранее изnapi_async_init. Для сохранения совместимости ABI с предыдущими версиями, передачаNULLв качествеasync_contextне приводит к ошибке. Однако это приводит к неправильной работе асинхронных хуков. Возможные проблемы включают потерю контекста асинхронной операции при использовании APIAsyncLocalStorage. -
[in] recv: Значениеthis, переданное вызываемой функции. -
[in] func: Значениеnapi_value, представляющее функцию JavaScript, которая должна быть вызвана. -
[in] argc: Количество элементов в массивеargv. -
[in] argv: Массив значений JavaScript какnapi_value, представляющих аргументы функции. Еслиargcравно нулю, этот параметр может быть опущен, передавNULL. -
[out] result: Значениеnapi_value, представляющее возвращаемый объект JavaScript.
Возвращает napi_ok в случае успешного выполнения API.
Этот метод позволяет вызывать объект JavaScript-функции из нативного дополнения. Этот API похож на napi_call_function. Однако он используется для вызова из нативного кода обратно в JavaScript после возврата из асинхронной операции (когда в стеке нет другого скрипта). Это довольно простой обертка над node::MakeCallback.
Обратите внимание, что использование napi_make_callback не требуется внутри napi_async_complete_callback; в этом случае контекст асинхронного обратного вызова уже настроен, поэтому прямой вызов napi_call_function достаточен и уместен. Использование функции napi_make_callback может потребоваться при реализации пользовательского асинхронного поведения, которое не использует napi_create_async_work.
Любые process.nextTick или обещания, запланированные в очереди микрозадач JavaScript во время обратного вызова, выполняются перед возвратом в C/C++.
napi_open_callback_scope
NAPI_EXTERN napi_status napi_open_callback_scope(napi_env env,
napi_value resource_object,
napi_async_context context,
napi_callback_scope* result) copy-
[in] env: Окружение, в котором вызывается API. -
[in] resource_object: Объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. Этот параметр устарел и игнорируется во время выполнения. Вместо него используйте параметрasync_resourceвnapi_async_init. -
[in] context: Контекст асинхронной операции, вызывающей обратный вызов. Он должен быть значением, полученным ранее изnapi_async_init. -
[out] result: Созданный контекст.
Существуют случаи (например, разрешение обещаний), когда необходимо иметь эквивалент контекста, связанного с обратным вызовом, при выполнении определенных вызовов Node-API. Если в стеке нет другого скрипта, функции napi_open_callback_scope и napi_close_callback_scope могут использоваться для открытия/закрытия необходимого контекста.
napi_close_callback_scope
NAPI_EXTERN napi_status napi_close_callback_scope(napi_env env,
napi_callback_scope scope) copy-
[in] env: Окружение, в котором вызывается API. -
[in] scope: Контекст, который необходимо закрыть.
Этот API можно вызывать, даже если в JavaScript есть ожидающее исключение.
Управление версиями
napi_get_node_version
typedef struct {
uint32_t major;
uint32_t minor;
uint32_t patch;
const char* release;
} napi_node_version;
napi_status napi_get_node_version(node_api_nogc_env env,
const napi_node_version** version); copy-
[in] env: Окружение, в котором вызывается API. -
[out] version: Указатель на информацию о версии самого Node.js.
Возвращает napi_ok в случае успешного выполнения API.
Эта функция заполняет структуру version значениями основной, дополнительной и патчной версий Node.js, работающей в данный момент, и поле release значением из process.release.name.
Возвращаемый буфер статически выделяется и не требует освобождения.
napi_get_version
napi_status napi_get_version(node_api_nogc_env env,
uint32_t* result); copy-
[in] env: Окружение, в котором вызывается API. -
[out] result: Наивысшая поддерживаемая версия Node-API.
Возвращает napi_ok в случае успешного выполнения API.
Этот API возвращает наивысшую поддерживаемую версию Node-API в среде выполнения Node.js. Ожидается, что Node-API будет добавлять новые функции, поэтому более новые версии Node.js могут поддерживать дополнительные API-функции. Чтобы позволить дополнению использовать новую функцию при работе с версиями Node.js, которые ее поддерживают, при этом обеспечивая поведение по умолчанию при работе с версиями Node.js, которые ее не поддерживают:
- Вызовите
napi_get_version()для определения доступности API. - Если доступен, динамически загрузите указатель на функцию, используя
uv_dlsym(). - Используйте динамически загруженный указатель для вызова функции.
- Если функция недоступна, предоставьте альтернативную реализацию, которая не использует ее.
Управление памятью
napi_adjust_external_memory
NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_nogc_env env,
int64_t change_in_bytes,
int64_t* result); copy-
[in] env: Окружение, в котором вызывается API. -
[in] change_in_bytes: Изменение внешней выделенной памяти, поддерживаемой объектами JavaScript. -
[out] result: Изменённое значение
Возвращает napi_ok в случае успешного выполнения API.
Эта функция сообщает V8 о количестве внешней выделенной памяти, поддерживаемой объектами JavaScript (например, объект JavaScript, указывающий на свою память, выделенную нативным дополнением). Регистрация внешней выделенной памяти приведет к тому, что глобальные сборки мусора будут запускаться чаще, чем обычно.
Обещания
Node-API предоставляет средства для создания объектов Promise, как описано в разделе 25.4 спецификации ECMA. Он реализует обещания как пару объектов. При создании обещания функцией napi_create_promise(), создаётся объект "отложенный" и возвращается вместе с объектом Promise. Объект "отложенный" связан с созданным объектом Promise и является единственным способом разрешить или отклонить обещание Promise с помощью napi_resolve_deferred() или napi_reject_deferred(). Объект "отложенный", созданный функцией napi_create_promise(), освобождается функциями napi_resolve_deferred() или napi_reject_deferred(). Объект Promise может быть возвращён в JavaScript, где он может быть использован стандартным образом.
Например, чтобы создать обещание и передать его асинхронному работнику:
napi_deferred deferred; napi_value promise; napi_status status; // Create the promise. status = napi_create_promise(env, &deferred, &promise); if (status != napi_ok) return NULL; // Pass the deferred to a function that performs an asynchronous action. do_something_asynchronous(deferred); // Return the promise to JS return promise; copy
Функция do_something_asynchronous() выше выполнит своё асинхронное действие, а затем разрешит или отклонит отложенный объект, тем самым завершая обещание и освобождая отложенный объект:
napi_deferred deferred;
napi_value undefined;
napi_status status;
// Create a value with which to conclude the deferred.
status = napi_get_undefined(env, &undefined);
if (status != napi_ok) return NULL;
// Resolve or reject the promise associated with the deferred depending on
// whether the asynchronous action succeeded.
if (asynchronous_action_succeeded) {
status = napi_resolve_deferred(env, deferred, undefined);
} else {
status = napi_reject_deferred(env, deferred, undefined);
}
if (status != napi_ok) return NULL;
// At this point the deferred has been freed, so we should assign NULL to it.
deferred = NULL; copy
napi_create_promise
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise); copy -
[in] env: Среда, в которой вызывается API. -
[out] deferred: Новый созданный объект "отложенный", который позднее может быть передан в функцииnapi_resolve_deferred()илиnapi_reject_deferred()для разрешения соответственно отклонения связанного обещания. -
[out] promise: JavaScript-обещание, связанное с объектом "отложенный".
Возвращает napi_ok в случае успешного выполнения API.
Этот API создаёт объект "отложенный" и JavaScript-обещание.
napi_resolve_deferred
napi_status napi_resolve_deferred(napi_env env,
napi_deferred deferred,
napi_value resolution); copy -
[in] env: Среда, в которой вызывается API. -
[in] deferred: Объект "отложенный", связанное обещание которого необходимо разрешить. -
[in] resolution: Значение, используемое для разрешения обещания.
Этот API разрешает JavaScript-обещание с помощью связанного с ним объекта "отложенный". Таким образом, он может быть использован только для разрешения JavaScript-обещаний, для которых доступен соответствующий объект "отложенный". Это означает, что обещание должно быть создано с помощью napi_create_promise() и объект "отложенный", возвращённый из этого вызова, должен быть сохранён для передачи в этот API.
Объект "отложенный" освобождается при успешном завершении.
napi_reject_deferred
napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection); copy -
[in] env: Среда, в которой вызывается API. -
[in] deferred: Объект "отложенный", связанное обещание которого необходимо отклонить. -
[in] rejection: Значение, используемое для отклонения обещания.
Этот API отклоняет JavaScript-обещание с помощью связанного с ним объекта "отложенный". Таким образом, он может быть использован только для отклонения JavaScript-обещаний, для которых доступен соответствующий объект "отложенный". Это означает, что обещание должно быть создано с помощью napi_create_promise() и объект "отложенный", возвращённый из этого вызова, должен быть сохранён для передачи в этот API.
Объект "отложенный" освобождается при успешном завершении.
napi_is_promise
napi_status napi_is_promise(napi_env env,
napi_value value,
bool* is_promise); copy -
[in] env: Среда, в которой вызывается API. -
[in] value: Значение для проверки -
[out] is_promise: Флаг, указывающий, является лиpromiseобъектом нативного обещания (то есть объектом обещания, созданным базовым движком).
Выполнение скрипта
Node-API предоставляет API для выполнения строки JavaScript с помощью базового движка JavaScript.
napi_run_script
NAPI_EXTERN napi_status napi_run_script(napi_env env,
napi_value script,
napi_value* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] script: Строка JavaScript, содержащая скрипт для выполнения. -
[out] result: Значение, полученное в результате выполнения скрипта.
Эта функция выполняет строку кода JavaScript и возвращает её результат с учётом следующих особенностей:
- В отличие от
eval, эта функция не позволяет скрипту получить доступ к текущей лексической области видимости, а значит, также не позволяет получить доступ к области видимости модуля, что означает, что псевдоглобальные переменные, такие какrequire, недоступны. - Скрипт может получить доступ к глобальной области видимости. Объявления функций и
varв скрипте будут добавлены в объектglobal. - Объявления переменных, сделанные с помощью
letиconst, будут видимы глобально, но не будут добавлены в объектglobal. - Значение
thisвнутри скрипта равноglobal.
Цикл событий libuv
Node-API предоставляет функцию для получения текущего цикла событий, связанного с определённым napi_env.
napi_get_uv_event_loop
NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_nogc_env env,
struct uv_loop_s** loop); copy -
[in] env: Среда, в которой вызывается API. -
[out] loop: Текущая инстанция цикла libuv.
Асинхронные потокобезопасные вызовы функций
Функции JavaScript обычно могут вызываться только из основного потока нативного плагина. Если плагин создаёт дополнительные потоки, то функции Node-API, требующие napi_env, napi_value, или napi_ref, не должны вызываться из этих потоков.
Когда плагин имеет дополнительные потоки, а функции JavaScript необходимо вызывать на основе обработки, завершённой этими потоками, эти потоки должны взаимодействовать с основным потоком плагина, чтобы основной поток мог вызвать функцию JavaScript от их имени. Потокобезопасные функции API предоставляют лёгкий способ сделать это.
Эти API предоставляют тип napi_threadsafe_function, а также API для создания, уничтожения и вызова объектов этого типа. napi_create_threadsafe_function() создаёт постоянную ссылку на napi_value, содержащую функцию JavaScript, которая может вызываться из нескольких потоков. Вызовы происходят асинхронно. Это означает, что значения, с которыми должен вызываться обратный вызов JavaScript, будут помещены в очередь, и для каждого значения в очереди в конечном итоге будет выполнен вызов функции JavaScript.
При создании napi_threadsafe_function может быть предоставлен обратный вызов napi_finalize. Этот обратный вызов будет вызван в основном потоке, когда потокобезопасная функция будет уничтожена. Он получает контекст и данные завершения, предоставленные во время создания, и предоставляет возможность очистки после потоков, например, вызвав uv_thread_join(). Помимо основного потока цикла, никакие потоки не должны использовать потокобезопасную функцию после завершения обратного вызова завершения.
context, предоставленное во время вызова napi_create_threadsafe_function(), может быть получено из любого потока с помощью вызова napi_get_threadsafe_function_context().
Вызов потокобезопасной функции
napi_call_threadsafe_function() может использоваться для инициирования вызова в JavaScript. napi_call_threadsafe_function() принимает параметр, который контролирует, будет ли API работать в блокирующем режиме. Если он установлен в napi_tsfn_nonblocking, API работает в неблокирующем режиме, возвращая napi_queue_full, если очередь была полной, предотвращая успешное добавление данных в очередь. Если он установлен в napi_tsfn_blocking, API блокируется до тех пор, пока в очереди не освободится место. napi_call_threadsafe_function() никогда не блокирует, если потокобезопасная функция была создана с максимальным размером очереди 0.
napi_call_threadsafe_function() не следует вызывать с napi_tsfn_blocking из потока JavaScript, потому что, если очередь полная, это может привести к тупику в потоке JavaScript.
Фактический вызов в JavaScript контролируется обратным вызовом, предоставленным через параметр call_js_cb. call_js_cb вызывается в основном потоке один раз для каждого значения, которое было помещено в очередь успешным вызовом napi_call_threadsafe_function(). Если такой обратный вызов не задан, используется по умолчанию, и вызов JavaScript не будет иметь аргументов. Обратный вызов call_js_cb получает функцию JavaScript для вызова как napi_value в своих параметрах, а также указатель контекста void* , используемый при создании napi_threadsafe_function, и указатель следующих данных, созданный одним из вторичных потоков. Затем обратный вызов может использовать API, такой как napi_call_function(), для вызова JavaScript.
Обратный вызов также может быть вызван с env и call_js_cb, оба установленные в NULL, чтобы указать, что вызовы в JavaScript больше невозможны, в то время как в очереди остаются элементы, которые могут потребовать освобождения. Это обычно происходит, когда процесс Node.js завершается, в то время как потокобезопасная функция всё ещё активна.
Не нужно вызывать JavaScript через napi_make_callback(), потому что Node-API выполняет call_js_cb в контексте, подходящем для обратных вызовов.
В каждом цикле обработки событий может быть вызвано ноль или более элементов очереди. Приложения не должны полагаться на конкретное поведение, кроме того, что будут выполняться вызовы обратных функций и будут вызываться события по мере продвижения времени.
Обработка ссылок потокобезопасных функций
Потоки могут добавляться и удаляться из объекта napi_threadsafe_function в течение его существования. Таким образом, помимо указания начального количества потоков при создании, napi_acquire_threadsafe_function может быть вызвано для указания того, что новый поток начнёт использовать потокобезопасную функцию. Аналогично, napi_release_threadsafe_function может быть вызвано для указания того, что существующий поток перестанет использовать потокобезопасную функцию.
Объекты napi_threadsafe_function уничтожаются, когда каждый поток, использующий объект, вызвал napi_release_threadsafe_function() или получил состояние возврата napi_closing в ответ на вызов napi_call_threadsafe_function. Очередь очищается перед уничтожением napi_threadsafe_function. napi_release_threadsafe_function() должен быть последним вызовом API в сочетании с заданной napi_threadsafe_function, потому что после завершения вызова нет гарантии, что napi_threadsafe_function всё ещё выделен. По той же причине не используйте потокобезопасную функцию после получения возвращаемого значения napi_closing в ответ на вызов napi_call_threadsafe_function. Данные, связанные с napi_threadsafe_function, могут быть освобождены в его обратном вызове napi_finalize, который был передан napi_create_threadsafe_function(). Параметр initial_thread_count функции napi_create_threadsafe_function отмечает начальное число приобретений потокобезопасных функций вместо вызова napi_acquire_threadsafe_function несколько раз при создании.
Как только количество потоков, использующих napi_threadsafe_function, достигнет нуля, больше никаких потоков не смогут начать использовать её, вызвав napi_acquire_threadsafe_function(). На самом деле, все последующие вызовы API, связанные с ней, кроме napi_release_threadsafe_function(), вернут значение ошибки napi_closing.
Потокобезопасная функция может быть «прервана», присвоив значение napi_tsfn_abort параметру napi_release_threadsafe_function(). Это заставит все последующие API, связанные с потокобезопасной функцией, кроме napi_release_threadsafe_function(), возвращать napi_closing, даже прежде, чем счётчик ссылок достигнет нуля. В частности, napi_call_threadsafe_function() вернёт napi_closing, таким образом сообщив потокам, что больше невозможны асинхронные вызовы к потокобезопасной функции. Это можно использовать в качестве критерия для завершения потока. При получении возвращаемого значения napi_closing от napi_call_threadsafe_function() поток не должен больше использовать потокобезопасную функцию, так как она больше не гарантируется выделенной.
Решение о том, продолжать ли работу процесса
Аналогично ручкам libuv, потокобезопасные функции могут быть «ссылочными» и «ссылочно-независимыми». «Ссылочная» потокобезопасная функция заставит цикл событий в потоке, в котором она создана, оставаться активным до уничтожения потокобезопасной функции. Напротив, «ссылочно-независимая» потокобезопасная функция не помешает циклу событий завершиться. Для этой цели существуют API napi_ref_threadsafe_function и napi_unref_threadsafe_function.
Ни napi_unref_threadsafe_function не отмечает потокобезопасные функции как уничтожимые, ни napi_ref_threadsafe_function не предотвращает их уничтожения.
napi_create_threadsafe_function
NAPI_EXTERN napi_status
napi_create_threadsafe_function(napi_env env,
napi_value func,
napi_value async_resource,
napi_value async_resource_name,
size_t max_queue_size,
size_t initial_thread_count,
void* thread_finalize_data,
napi_finalize thread_finalize_cb,
void* context,
napi_threadsafe_function_call_js call_js_cb,
napi_threadsafe_function* result); copy -
[in] env: Среда, в которой вызывается API. -
[in] func: Необязательная функция JavaScript для вызова из другого потока. Она должна быть предоставлена, еслиNULLпередаётся вcall_js_cb. -
[in] async_resource: Необязательный объект, связанный с асинхронной работой, который будет передан возможнымasync_hooksinitхукам. -
[in] async_resource_name: Строка JavaScript для предоставления идентификатора типа ресурса, предоставляемого для диагностической информации, экспонируемой APIasync_hooks. -
[in] max_queue_size: Максимальный размер очереди.0для отсутствия ограничения. -
[in] initial_thread_count: Начальное количество приобретений, т. е. начальное количество потоков, включая основной поток, которые будут использовать эту функцию. -
[in] thread_finalize_data: Необязательные данные, которые будут переданы вthread_finalize_cb. -
[in] thread_finalize_cb: Необязательная функция для вызова, когдаnapi_threadsafe_functionуничтожается. -
[in] context: Необязательные данные для прикрепления к получившемусяnapi_threadsafe_function. -
[in] call_js_cb: Необязательный обратный вызов, который вызывает функцию JavaScript в ответ на вызов в другом потоке. Этот обратный вызов будет вызван в основном потоке. Если не задан, функция JavaScript будет вызвана без параметров и сundefinedв качестве значенияthis.napi_threadsafe_function_call_jsпредоставляет больше деталей. -
[out] result: Асинхронная потокобезопасная функция JavaScript.
История изменений:
-
Экспериментальное (
NAPI_EXPERIMENTALопределено):Необработанные исключения, возникающие в
call_js_cbобрабатываются событием'uncaughtException'вместо игнорирования.
napi_get_threadsafe_function_context
NAPI_EXTERN napi_status
napi_get_threadsafe_function_context(napi_threadsafe_function func,
void** result); copy -
[in] func: Потокобезопасная функция, для которой необходимо получить контекст. -
[out] result: Место для хранения контекста.
Этот API может быть вызван из любого потока, который использует func.
napi_call_threadsafe_function
NAPI_EXTERN napi_status
napi_call_threadsafe_function(napi_threadsafe_function func,
void* data,
napi_threadsafe_function_call_mode is_blocking); copy -
[in] func: Асинхронная потокобезопасная функция JavaScript для вызова. -
[in] data: Данные для отправки в JavaScript через обратный вызовcall_js_cb, предоставленный при создании потокобезопасной функции JavaScript. -
[in] is_blocking: Флаг, значение которого может быть либоnapi_tsfn_blockingдля указания блокировки вызова, если очередь заполнена, либоnapi_tsfn_nonblockingдля указания немедленного возврата с состояниемnapi_queue_fullпри заполнении очереди.
Этот API не следует вызывать из потока JavaScript, так как при заполнении очереди это может привести к тупику в потоке JavaScript.
Этот API вернёт napi_closing, если napi_release_threadsafe_function() был вызван с abort установленным в napi_tsfn_abort из любого потока. Значение добавляется в очередь только если API вернул napi_ok.
Этот API может быть вызван из любого потока, использующего func.
napi_acquire_threadsafe_function
NAPI_EXTERN napi_status napi_acquire_threadsafe_function(napi_threadsafe_function func); copy
-
[in] func: Асинхронная потокобезопасная функция JavaScript, для которой нужно начать использование.
Поток должен вызвать этот API перед передачей func в любые другие потокобезопасные API-функции, чтобы указать, что он будет использовать func. Это предотвращает уничтожение func, когда все другие потоки прекратят использование.
Этот API может быть вызван из любого потока, который начнёт использовать func.
napi_release_threadsafe_function
NAPI_EXTERN napi_status
napi_release_threadsafe_function(napi_threadsafe_function func,
napi_threadsafe_function_release_mode mode); copy -
[in] func: Асинхронная потокобезопасная функция JavaScript, счётчик ссылок которой нужно декрементировать. -
[in] mode: Флаг, значение которого может быть либоnapi_tsfn_releaseдля указания, что текущий поток больше не будет выполнять вызовы к потокобезопасной функции, илиnapi_tsfn_abortдля указания, что, помимо текущего потока, ни один другой поток не должен делать дальнейших вызовов к потокобезопасной функции. Если установлено значениеnapi_tsfn_abort, дальнейшие вызовы кnapi_call_threadsafe_function()вернутnapi_closing, и больше значений в очередь не будет помещено.
Поток должен вызвать этот API, когда он перестаёт использовать func. Передача func в любые потокобезопасные API после вызова этого API даёт неопределённые результаты, так как func может быть уничтожена.
Этот API может быть вызван из любого потока, который прекратит использование func.
napi_ref_threadsafe_function
NAPI_EXTERN napi_status napi_ref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func); copy
-
[in] env: Среда, в которой вызывается API. -
[in] func: Потокобезопасная функция для получения ссылки.
Этот API используется для указания, что цикл событий, работающий в основном потоке, не должен завершаться до уничтожения func. Аналогично uv_ref, он также идемпотентен.
Также napi_unref_threadsafe_function не отмечает потокобезопасные функции как уничтожаемые, и napi_ref_threadsafe_function не предотвращает их уничтожение. napi_acquire_threadsafe_function и napi_release_threadsafe_function предназначены для этой цели.
Этот API может быть вызван только из основного потока.
napi_unref_threadsafe_function
NAPI_EXTERN napi_status napi_unref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func); copy
-
[in] env: Среда, в которой вызывается API. -
[in] func: Потокобезопасная функция для удаления ссылки.
Этот API используется для указания, что цикл событий, работающий в основном потоке, может завершиться до уничтожения func. Аналогично uv_unref, он также идемпотентен.
Этот API может быть вызван только из основного потока.
Дополнительные утилиты
node_api_get_module_file_name
NAPI_EXTERN napi_status node_api_get_module_file_name(node_api_nogc_env env, const char** result); copy
-
[in] env: Среда, в которой вызывается API. -
[out] result: URL, содержащий абсолютный путь к месту загрузки плагина. Для файла на локальной файловой системе он будет начинаться сfile://. Строка имеет нуль-терминатор и принадлежитenv, поэтому её нельзя изменять или освобождать.
result может быть пустой строкой, если процесс загрузки плагина не смог определить имя файла плагина во время загрузки.
© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/api/n-api.html