n-api: change napi_callback to return napi_value

Change `napi_callback` to return `napi_value` directly instead of
requiring `napi_set_return_value`.

When we invoke the callback, we will check the return value and
call `SetReturnValue` ourselves. If the callback returns `NULL`,
we don't set the return value in v8 which would have the same
effect as previously if the callback didn't call
`napi_set_return_value`. Seems to be a more natural way
to handle return values from callbacks. As a consequence,
remove `napi_set_return_value`.

Add a `napi_value` to `napi_property_descriptor` to support string
values which couldn't be passed in the `utf8name` parameter or
symbols as property names. Class names, however, cannot be symbols
so this `napi_value` must be a string type in that case.

Remove all of the `napi_callback_info` helpers except for
`napi_get_cb_info` and make all the parameters to
`napi_get_cb_info` optional except for argc.

Update all the test collateral according to these changes.
Also add `test/addons-napi/common.h` to house some common macros
for wrapping N-API calls and error handling.

PR-URL: https://github.com/nodejs/node/pull/12248
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
Taylor Woll 2017-03-24 01:26:09 -07:00 committed by Anna Henningsen
parent b470a85f07
commit ca786c3734
No known key found for this signature in database
GPG Key ID: D8B9F5AEAE84E4CF
32 changed files with 934 additions and 1585 deletions

View File

@ -36,6 +36,70 @@ class napi_env__ {
napi_extended_error_info last_error;
};
#define RETURN_STATUS_IF_FALSE(env, condition, status) \
do { \
if (!(condition)) { \
return napi_set_last_error((env), (status)); \
} \
} while (0)
#define CHECK_ENV(env) \
if ((env) == nullptr) { \
node::FatalError(__func__, "environment(env) must not be null"); \
}
#define CHECK_ARG(env, arg) \
RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
#define CHECK_MAYBE_EMPTY(env, maybe, status) \
RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status))
#define CHECK_MAYBE_NOTHING(env, maybe, status) \
RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
// NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
#define NAPI_PREAMBLE(env) \
CHECK_ENV((env)); \
RETURN_STATUS_IF_FALSE((env), (env)->last_exception.IsEmpty(), \
napi_pending_exception); \
napi_clear_last_error((env)); \
v8impl::TryCatch try_catch((env))
#define CHECK_TO_TYPE(env, type, context, result, src, status) \
do { \
auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \
CHECK_MAYBE_EMPTY((env), maybe, (status)); \
(result) = maybe.ToLocalChecked(); \
} while (0)
#define CHECK_TO_OBJECT(env, context, result, src) \
CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)
#define CHECK_TO_STRING(env, context, result, src) \
CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected)
#define CHECK_TO_NUMBER(env, context, result, src) \
CHECK_TO_TYPE((env), Number, (context), (result), (src), napi_number_expected)
#define CHECK_TO_BOOL(env, context, result, src) \
CHECK_TO_TYPE((env), Boolean, (context), (result), (src), \
napi_boolean_expected)
#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len) \
do { \
auto str_maybe = v8::String::NewFromUtf8( \
(env)->isolate, (str), v8::NewStringType::kInternalized, (len)); \
CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure); \
(result) = str_maybe.ToLocalChecked(); \
} while (0)
#define CHECK_NEW_FROM_UTF8(env, result, str) \
CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), -1)
#define GET_RETURN_STATUS(env) \
(!try_catch.HasCaught() ? napi_ok \
: napi_set_last_error((env), napi_pending_exception))
namespace v8impl {
// convert from n-api property attributes to v8::PropertyAttribute
@ -127,6 +191,22 @@ v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
return local;
}
static inline napi_status V8NameFromPropertyDescriptor(napi_env env,
const napi_property_descriptor* p,
v8::Local<v8::Name>* result) {
if (p->utf8name != nullptr) {
CHECK_NEW_FROM_UTF8(env, *result, p->utf8name);
} else {
v8::Local<v8::Value> property_value =
v8impl::V8LocalValueFromJsValue(p->name);
RETURN_STATUS_IF_FALSE(env, property_value->IsName(), napi_name_expected);
*result = property_value.As<v8::Name>();
}
return napi_ok;
}
// Adapter for napi_finalize callbacks.
class Finalizer {
protected:
@ -361,13 +441,19 @@ class CallbackWrapperBase : public CallbackWrapper {
v8::Local<v8::External>::Cast(
_cbdata->GetInternalField(kInternalFieldIndex))->Value());
v8::Isolate* isolate = _cbinfo.GetIsolate();
napi_env env = static_cast<napi_env>(
v8::Local<v8::External>::Cast(
_cbdata->GetInternalField(kEnvIndex))->Value());
// Make sure any errors encountered last time we were in N-API are gone.
napi_clear_last_error(env);
cb(env, cbinfo_wrapper);
napi_value result = cb(env, cbinfo_wrapper);
if (result != nullptr) {
this->SetReturnValue(result);
}
if (!env->last_exception.IsEmpty()) {
isolate->ThrowException(
@ -608,75 +694,12 @@ void napi_module_register(napi_module* mod) {
node::node_module_register(nm);
}
#define RETURN_STATUS_IF_FALSE(env, condition, status) \
do { \
if (!(condition)) { \
return napi_set_last_error((env), (status)); \
} \
} while (0)
#define CHECK_ENV(env) \
if ((env) == nullptr) { \
node::FatalError(__func__, "environment(env) must not be null"); \
}
#define CHECK_ARG(env, arg) \
RETURN_STATUS_IF_FALSE((env), ((arg) != nullptr), napi_invalid_arg)
#define CHECK_MAYBE_EMPTY(env, maybe, status) \
RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status))
#define CHECK_MAYBE_NOTHING(env, maybe, status) \
RETURN_STATUS_IF_FALSE((env), !((maybe).IsNothing()), (status))
// NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
#define NAPI_PREAMBLE(env) \
CHECK_ENV((env)); \
RETURN_STATUS_IF_FALSE((env), (env)->last_exception.IsEmpty(), \
napi_pending_exception); \
napi_clear_last_error((env)); \
v8impl::TryCatch try_catch((env))
#define CHECK_TO_TYPE(env, type, context, result, src, status) \
do { \
auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \
CHECK_MAYBE_EMPTY((env), maybe, (status)); \
(result) = maybe.ToLocalChecked(); \
} while (0)
#define CHECK_TO_OBJECT(env, context, result, src) \
CHECK_TO_TYPE((env), Object, (context), (result), (src), napi_object_expected)
#define CHECK_TO_STRING(env, context, result, src) \
CHECK_TO_TYPE((env), String, (context), (result), (src), napi_string_expected)
#define CHECK_TO_NUMBER(env, context, result, src) \
CHECK_TO_TYPE((env), Number, (context), (result), (src), napi_number_expected)
#define CHECK_TO_BOOL(env, context, result, src) \
CHECK_TO_TYPE((env), Boolean, (context), (result), (src), \
napi_boolean_expected)
#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len) \
do { \
auto str_maybe = v8::String::NewFromUtf8( \
(env)->isolate, (str), v8::NewStringType::kInternalized, (len)); \
CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure); \
result = str_maybe.ToLocalChecked(); \
} while (0)
#define CHECK_NEW_FROM_UTF8(env, result, str) \
CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), -1)
#define GET_RETURN_STATUS(env) \
(!try_catch.HasCaught() ? napi_ok \
: napi_set_last_error((env), napi_pending_exception))
// Warning: Keep in-sync with napi_status enum
const char* error_messages[] = {nullptr,
"Invalid pointer passed as argument",
"An object was expected",
"A string was expected",
"A string or symbol was expected",
"A function was expected",
"A number was expected",
"A boolean was expected",
@ -793,8 +816,14 @@ napi_status napi_define_class(napi_env env,
continue;
}
v8::Local<v8::String> property_name;
CHECK_NEW_FROM_UTF8(env, property_name, p->utf8name);
v8::Local<v8::Name> property_name;
napi_status status =
v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
if (status != napi_ok) {
return napi_set_last_error(env, status);
}
v8::PropertyAttribute attributes =
v8impl::V8PropertyAttributesFromDescriptor(p);
@ -822,7 +851,6 @@ napi_status napi_define_class(napi_env env,
v8impl::FunctionCallbackWrapper::Invoke,
cbdata,
v8::Signature::New(isolate, tpl));
t->SetClassName(property_name);
tpl->PrototypeTemplate()->Set(property_name, t, attributes);
} else {
@ -855,18 +883,6 @@ napi_status napi_define_class(napi_env env,
return GET_RETURN_STATUS(env);
}
napi_status napi_set_return_value(napi_env env,
napi_callback_info cbinfo,
napi_value value) {
NAPI_PREAMBLE(env);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
info->SetReturnValue(value);
return GET_RETURN_STATUS(env);
}
napi_status napi_get_property_names(napi_env env,
napi_value object,
napi_value* result) {
@ -1102,11 +1118,16 @@ napi_status napi_define_properties(napi_env env,
for (size_t i = 0; i < property_count; i++) {
const napi_property_descriptor* p = &properties[i];
v8::Local<v8::Name> name;
CHECK_NEW_FROM_UTF8(env, name, p->utf8name);
v8::Local<v8::Name> property_name;
napi_status status =
v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
if (status != napi_ok) {
return napi_set_last_error(env, status);
}
v8::PropertyAttribute attributes =
v8impl::V8PropertyAttributesFromDescriptor(p);
v8impl::V8PropertyAttributesFromDescriptor(p);
if (p->getter != nullptr || p->setter != nullptr) {
v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
@ -1117,7 +1138,7 @@ napi_status napi_define_properties(napi_env env,
auto set_maybe = obj->SetAccessor(
context,
name,
property_name,
p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
cbdata,
@ -1136,8 +1157,8 @@ napi_status napi_define_properties(napi_env env,
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(
isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
auto define_maybe =
obj->DefineOwnProperty(context, name, t->GetFunction(), attributes);
auto define_maybe = obj->DefineOwnProperty(
context, property_name, t->GetFunction(), attributes);
if (!define_maybe.FromMaybe(false)) {
return napi_set_last_error(env, napi_generic_failure);
@ -1146,7 +1167,7 @@ napi_status napi_define_properties(napi_env env,
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
auto define_maybe =
obj->DefineOwnProperty(context, name, value, attributes);
obj->DefineOwnProperty(context, property_name, value, attributes);
if (!define_maybe.FromMaybe(false)) {
return napi_set_last_error(env, napi_invalid_arg);
@ -1439,36 +1460,27 @@ napi_status napi_get_cb_info(
napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
void** data) { // [out] Receives the data pointer for the callback.
CHECK_ENV(env);
CHECK_ARG(env, argc);
CHECK_ARG(env, argv);
CHECK_ARG(env, this_arg);
CHECK_ARG(env, data);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
info->Args(argv, std::min(*argc, info->ArgsLength()));
*argc = info->ArgsLength();
*this_arg = info->This();
*data = info->Data();
if (argv != nullptr) {
CHECK_ARG(env, argc);
info->Args(argv, std::min(*argc, info->ArgsLength()));
}
if (argc != nullptr) {
*argc = info->ArgsLength();
}
if (this_arg != nullptr) {
*this_arg = info->This();
}
if (data != nullptr) {
*data = info->Data();
}
return napi_ok;
}
napi_status napi_get_cb_args_length(napi_env env,
napi_callback_info cbinfo,
size_t* result) {
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
CHECK_ENV(env);
CHECK_ARG(env, result);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
*result = info->ArgsLength();
return napi_ok;
}
napi_status napi_is_construct_call(napi_env env,
napi_callback_info cbinfo,
bool* result) {
@ -1483,51 +1495,6 @@ napi_status napi_is_construct_call(napi_env env,
return napi_ok;
}
// copy encoded arguments into provided buffer or return direct pointer to
// encoded arguments array?
napi_status napi_get_cb_args(napi_env env,
napi_callback_info cbinfo,
napi_value* buf,
size_t bufsize) {
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
CHECK_ENV(env);
CHECK_ARG(env, buf);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
info->Args(buf, bufsize);
return napi_ok;
}
napi_status napi_get_cb_this(napi_env env,
napi_callback_info cbinfo,
napi_value* result) {
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
CHECK_ENV(env);
CHECK_ARG(env, result);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
*result = info->This();
return napi_ok;
}
napi_status napi_get_cb_data(napi_env env,
napi_callback_info cbinfo,
void** result) {
// Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
CHECK_ENV(env);
CHECK_ARG(env, result);
v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
*result = info->Data();
return napi_ok;
}
napi_status napi_call_function(napi_env env,
napi_value recv,
napi_value func,

View File

@ -298,29 +298,12 @@ NAPI_EXTERN napi_status napi_get_cb_info(
size_t* argc, // [in-out] Specifies the size of the provided argv array
// and receives the actual count of args.
napi_value* argv, // [out] Array of values
napi_value* thisArg, // [out] Receives the JS 'this' arg for the call
void** data); // [out] Receives the data pointer for the callback.
napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
void** data); // [out] Receives the data pointer for the callback.
NAPI_EXTERN napi_status napi_get_cb_args_length(napi_env env,
napi_callback_info cbinfo,
size_t* result);
NAPI_EXTERN napi_status napi_get_cb_args(napi_env env,
napi_callback_info cbinfo,
napi_value* buf,
size_t bufsize);
NAPI_EXTERN napi_status napi_get_cb_this(napi_env env,
napi_callback_info cbinfo,
napi_value* result);
NAPI_EXTERN napi_status napi_get_cb_data(napi_env env,
napi_callback_info cbinfo,
void** result);
NAPI_EXTERN napi_status napi_is_construct_call(napi_env env,
napi_callback_info cbinfo,
bool* result);
NAPI_EXTERN napi_status napi_set_return_value(napi_env env,
napi_callback_info cbinfo,
napi_value value);
NAPI_EXTERN napi_status
napi_define_class(napi_env env,
const char* utf8name,

View File

@ -17,8 +17,8 @@ typedef struct napi_handle_scope__ *napi_handle_scope;
typedef struct napi_escapable_handle_scope__ *napi_escapable_handle_scope;
typedef struct napi_callback_info__ *napi_callback_info;
typedef void (*napi_callback)(napi_env env,
napi_callback_info info);
typedef napi_value (*napi_callback)(napi_env env,
napi_callback_info info);
typedef void (*napi_finalize)(napi_env env,
void* finalize_data,
void* finalize_hint);
@ -35,7 +35,9 @@ typedef enum {
} napi_property_attributes;
typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name;
napi_value name;
napi_callback method;
napi_callback getter;
@ -76,6 +78,7 @@ typedef enum {
napi_invalid_arg,
napi_object_expected,
napi_string_expected,
napi_name_expected,
napi_function_expected,
napi_number_expected,
napi_boolean_expected,

View File

@ -1,22 +1,18 @@
#include <node_api.h>
#include "../common.h"
#include <string.h>
void Method(napi_env env, napi_callback_info info) {
napi_status status;
napi_value Method(napi_env env, napi_callback_info info) {
napi_value world;
status = napi_create_string_utf8(env, "world", -1, &world);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, world);
if (status != napi_ok) return;
const char* str = "world";
size_t str_len = strlen(str);
NAPI_CALL(env, napi_create_string_utf8(env, str, str_len, &world));
return world;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor desc = DECLARE_NAPI_METHOD("hello", Method);
status = napi_define_properties(env, exports, 1, &desc);
if (status != napi_ok) return;
napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("hello", Method);
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,58 +1,37 @@
#include <node_api.h>
#include "../common.h"
void Add(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 2) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype0 != napi_number || valuetype1 != napi_number) {
napi_throw_type_error(env, "Wrong arguments");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_number && valuetype1 == napi_number,
"Wrong argument type. Numbers expected.");
double value0;
status = napi_get_value_double(env, args[0], &value0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &value0));
double value1;
status = napi_get_value_double(env, args[1], &value1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[1], &value1));
napi_value sum;
status = napi_create_number(env, value0 + value1, &sum);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, value0 + value1, &sum));
status = napi_set_return_value(env, info, sum);
if (status != napi_ok) return;
return sum;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor addDescriptor = DECLARE_NAPI_METHOD("add", Add);
status = napi_define_properties(env, exports, 1, &addDescriptor);
if (status != napi_ok) return;
napi_property_descriptor desc = DECLARE_NAPI_PROPERTY("add", Add);
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 1, &desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,51 +1,43 @@
#include <node_api.h>
#include "../common.h"
#include <string.h>
#define NAPI_CALL(env, theCall) \
if ((theCall) != napi_ok) { \
const napi_extended_error_info* error; \
napi_get_last_error_info((env), &error); \
const char* errorMessage = error->error_message; \
errorMessage = errorMessage ? errorMessage : "empty error message"; \
napi_throw_error((env), errorMessage); \
return; \
}
void RunCallback(napi_env env, napi_callback_info info) {
napi_value RunCallback(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_args(env, info, args, 1));
napi_value cb = args[0];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value argv[1];
NAPI_CALL(env, napi_create_string_utf8(env, "hello world", -1, argv));
const char* str = "hello world";
size_t str_len = strlen(str);
NAPI_CALL(env, napi_create_string_utf8(env, str, str_len, argv));
napi_value global;
NAPI_CALL(env, napi_get_global(env, &global));
napi_value cb = args[0];
NAPI_CALL(env, napi_call_function(env, global, cb, 1, argv, NULL));
return NULL;
}
void RunCallbackWithRecv(napi_env env, napi_callback_info info) {
napi_value RunCallbackWithRecv(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NAPI_CALL(env, napi_get_cb_args(env, info, args, 2));
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value cb = args[0];
napi_value recv = args[1];
NAPI_CALL(env, napi_call_function(env, recv, cb, 0, NULL, NULL));
return NULL;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor desc[2] = {
DECLARE_NAPI_METHOD("RunCallback", RunCallback),
DECLARE_NAPI_METHOD("RunCallbackWithRecv", RunCallbackWithRecv),
DECLARE_NAPI_PROPERTY("RunCallback", RunCallback),
DECLARE_NAPI_PROPERTY("RunCallbackWithRecv", RunCallbackWithRecv),
};
status = napi_define_properties(env, exports, 2, desc);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 2, desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,31 +1,23 @@
#include <node_api.h>
#include "../common.h"
void CreateObject(napi_env env, napi_callback_info info) {
napi_status status;
napi_value CreateObject(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value obj;
status = napi_create_object(env, &obj);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_object(env, &obj));
status = napi_set_named_property(env, obj, "msg", args[0]);
if (status != napi_ok) return;
NAPI_CALL(env, napi_set_named_property(env, obj, "msg", args[0]));
status = napi_set_return_value(env, info, obj);
if (status != napi_ok) return;
return obj;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor desc = DECLARE_NAPI_METHOD("exports", CreateObject);
status = napi_define_properties(env, module, 1, &desc);
if (status != napi_ok) return;
napi_property_descriptor desc =
DECLARE_NAPI_PROPERTY("exports", CreateObject);
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,36 +1,25 @@
#include <node_api.h>
#include "../common.h"
void MyFunction(napi_env env, napi_callback_info info) {
napi_status status;
napi_value MyFunction(napi_env env, napi_callback_info info) {
napi_value str;
status = napi_create_string_utf8(env, "hello world", -1, &str);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_string_utf8(env, "hello world", -1, &str));
status = napi_set_return_value(env, info, str);
if (status != napi_ok) return;
return str;
}
void CreateFunction(napi_env env, napi_callback_info info) {
napi_status status;
napi_value CreateFunction(napi_env env, napi_callback_info info) {
napi_value fn;
status = napi_create_function(env, "theFunction", MyFunction, NULL, &fn);
if (status != napi_ok) return;
NAPI_CALL(env,
napi_create_function(env, "theFunction", MyFunction, NULL, &fn));
status = napi_set_return_value(env, info, fn);
if (status != napi_ok) return;
return fn;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor desc =
DECLARE_NAPI_METHOD("exports", CreateFunction);
status = napi_define_properties(env, module, 1, &desc);
if (status != napi_ok) return;
DECLARE_NAPI_PROPERTY("exports", CreateFunction);
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,4 +1,5 @@
#include "myobject.h"
#include "../common.h"
napi_ref MyObject::constructor;
@ -13,189 +14,136 @@ void MyObject::Destructor(
delete obj;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void MyObject::Init(napi_env env, napi_value exports) {
napi_status status;
napi_property_descriptor properties[] = {
{ "value", nullptr, GetValue, SetValue, 0, napi_default, 0 },
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_METHOD("multiply", Multiply),
{ "value", nullptr, nullptr, GetValue, SetValue, 0, napi_default, 0 },
DECLARE_NAPI_PROPERTY("plusOne", PlusOne),
DECLARE_NAPI_PROPERTY("multiply", Multiply),
};
napi_value cons;
status =
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env,
napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons));
status = napi_create_reference(env, cons, 1, &constructor);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_create_reference(env, cons, 1, &constructor));
status = napi_set_named_property(env, exports, "MyObject", cons);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env,
napi_set_named_property(env, exports, "MyObject", cons));
}
void MyObject::New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value MyObject::New(napi_env env, napi_callback_info info) {
bool is_constructor;
status = napi_is_construct_call(env, info, &is_constructor);
if (status != napi_ok) return;
NAPI_CALL(env, napi_is_construct_call(env, info, &is_constructor));
size_t argc = 1;
napi_value args[1];
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr));
if (is_constructor) {
// Invoked as constructor: `new MyObject(...)`
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
double value = 0;
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_undefined) {
status = napi_get_value_double(env, args[0], &value);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &value));
}
MyObject* obj = new MyObject(value);
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
obj->env_ = env;
status = napi_wrap(env,
jsthis,
obj,
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_wrap(env,
_this,
obj,
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_));
status = napi_set_return_value(env, info, jsthis);
if (status != napi_ok) return;
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
const int argc = 1;
napi_value argv[argc] = {args[0]};
napi_value cons;
status = napi_get_reference_value(env, constructor, &cons);
if (status != napi_ok) return;
napi_value instance;
status = napi_new_instance(env, cons, argc, argv, &instance);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, instance);
if (status != napi_ok) return;
return _this;
}
// Invoked as plain function `MyObject(...)`, turn into construct call.
argc = 1;
napi_value argv[1] = {args[0]};
napi_value cons;
NAPI_CALL(env, napi_get_reference_value(env, constructor, &cons));
napi_value instance;
NAPI_CALL(env, napi_new_instance(env, cons, argc, argv, &instance));
return instance;
}
void MyObject::GetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
napi_value MyObject::GetValue(napi_env env, napi_callback_info info) {
napi_value _this;
NAPI_CALL(env,
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
napi_value num;
status = napi_create_number(env, obj->value_, &num);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, obj->value_, &num));
status = napi_set_return_value(env, info, num);
if (status != napi_ok) return;
return num;
}
void MyObject::SetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value value;
status = napi_get_cb_args(env, info, &value, 1);
if (status != napi_ok) return;
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
napi_value MyObject::SetValue(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr));
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
status = napi_get_value_double(env, value, &obj->value_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &obj->value_));
return nullptr;
}
void MyObject::PlusOne(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
napi_value _this;
NAPI_CALL(env,
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
obj->value_ += 1;
napi_value num;
status = napi_create_number(env, obj->value_, &num);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, obj->value_, &num));
status = napi_set_return_value(env, info, num);
if (status != napi_ok) return;
return num;
}
void MyObject::Multiply(napi_env env, napi_callback_info info) {
napi_status status;
napi_value MyObject::Multiply(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr));
double multiple = 1;
if (valuetype != napi_undefined) {
status = napi_get_value_double(env, args[0], &multiple);
if (status != napi_ok) return;
if (argc >= 1) {
NAPI_CALL(env, napi_get_value_double(env, args[0], &multiple));
}
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
napi_value cons;
status = napi_get_reference_value(env, constructor, &cons);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_reference_value(env, constructor, &cons));
const int kArgCount = 1;
napi_value argv[kArgCount];
status = napi_create_number(env, obj->value_ * multiple, argv);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, obj->value_ * multiple, argv));
napi_value instance;
status = napi_new_instance(env, cons, kArgCount, argv, &instance);
if (status != napi_ok) return;
NAPI_CALL(env, napi_new_instance(env, cons, kArgCount, argv, &instance));
status = napi_set_return_value(env, info, instance);
if (status != napi_ok) return;
return instance;
}

View File

@ -12,11 +12,11 @@ class MyObject {
explicit MyObject(double value_ = 0);
~MyObject();
static void New(napi_env env, napi_callback_info info);
static void GetValue(napi_env env, napi_callback_info info);
static void SetValue(napi_env env, napi_callback_info info);
static void PlusOne(napi_env env, napi_callback_info info);
static void Multiply(napi_env env, napi_callback_info info);
static napi_value New(napi_env env, napi_callback_info info);
static napi_value GetValue(napi_env env, napi_callback_info info);
static napi_value SetValue(napi_env env, napi_callback_info info);
static napi_value PlusOne(napi_env env, napi_callback_info info);
static napi_value Multiply(napi_env env, napi_callback_info info);
static napi_ref constructor;
double value_;
napi_env env_;

View File

@ -1,32 +1,23 @@
#include "myobject.h"
#include "../common.h"
void CreateObject(napi_env env, napi_callback_info info) {
napi_status status;
napi_value CreateObject(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
napi_value instance;
status = MyObject::NewInstance(env, args[0], &instance);
if (status != napi_ok) return;
NAPI_CALL(env, MyObject::NewInstance(env, args[0], &instance));
status = napi_set_return_value(env, info, instance);
if (status != napi_ok) return;
return instance;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
NAPI_CALL_RETURN_VOID(env, MyObject::Init(env));
status = MyObject::Init(env);
if (status != napi_ok) return;
napi_property_descriptor desc = DECLARE_NAPI_METHOD("exports", CreateObject);
status = napi_define_properties(env, module, 1, &desc);
if (status != napi_ok) return;
napi_property_descriptor desc =
DECLARE_NAPI_PROPERTY("exports", CreateObject);
NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, module, 1, &desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,4 +1,5 @@
#include "myobject.h"
#include "../common.h"
MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}
@ -11,15 +12,12 @@ void MyObject::Destructor(napi_env env,
delete obj;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
napi_ref MyObject::constructor;
napi_status MyObject::Init(napi_env env) {
napi_status status;
napi_property_descriptor properties[] = {
DECLARE_NAPI_METHOD("plusOne", PlusOne),
DECLARE_NAPI_PROPERTY("plusOne", PlusOne),
};
napi_value cons;
@ -33,41 +31,32 @@ napi_status MyObject::Init(napi_env env) {
return napi_ok;
}
void MyObject::New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value MyObject::New(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr));
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
MyObject* obj = new MyObject();
if (valuetype == napi_undefined) {
obj->counter_ = 0;
} else {
status = napi_get_value_double(env, args[0], &obj->counter_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &obj->counter_));
}
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
obj->env_ = env;
status = napi_wrap(env,
jsthis,
obj,
MyObject::Destructor,
nullptr, /* finalize_hint */
&obj->wrapper_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_wrap(env,
_this,
obj,
MyObject::Destructor,
nullptr, /* finalize_hint */
&obj->wrapper_));
status = napi_set_return_value(env, info, jsthis);
if (status != napi_ok) return;
return _this;
}
napi_status MyObject::NewInstance(napi_env env,
@ -88,23 +77,18 @@ napi_status MyObject::NewInstance(napi_env env,
return napi_ok;
}
void MyObject::PlusOne(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
napi_value MyObject::PlusOne(napi_env env, napi_callback_info info) {
napi_value _this;
NAPI_CALL(env,
napi_get_cb_info(env, info, nullptr, nullptr, &_this, nullptr));
MyObject* obj;
status = napi_unwrap(env, jsthis, reinterpret_cast<void**>(&obj));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, _this, reinterpret_cast<void**>(&obj)));
obj->counter_ += 1;
napi_value num;
status = napi_create_number(env, obj->counter_, &num);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, obj->counter_, &num));
status = napi_set_return_value(env, info, num);
if (status != napi_ok) return;
return num;
}

View File

@ -16,8 +16,8 @@ class MyObject {
~MyObject();
static napi_ref constructor;
static void New(napi_env env, napi_callback_info info);
static void PlusOne(napi_env env, napi_callback_info info);
static napi_value New(napi_env env, napi_callback_info info);
static napi_value PlusOne(napi_env env, napi_callback_info info);
double counter_;
napi_env env_;
napi_ref wrapper_;

View File

@ -1,57 +1,44 @@
#include "myobject.h"
#include "../common.h"
void CreateObject(napi_env env, napi_callback_info info) {
napi_status status;
napi_value CreateObject(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
napi_value instance;
status = MyObject::NewInstance(env, args[0], &instance);
NAPI_CALL(env, MyObject::NewInstance(env, args[0], &instance));
status = napi_set_return_value(env, info, instance);
if (status != napi_ok) return;
return instance;
}
void Add(napi_env env, napi_callback_info info) {
napi_status status;
napi_value Add(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
MyObject* obj1;
status = napi_unwrap(env, args[0], reinterpret_cast<void**>(&obj1));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, args[0], reinterpret_cast<void**>(&obj1)));
MyObject* obj2;
status = napi_unwrap(env, args[1], reinterpret_cast<void**>(&obj2));
if (status != napi_ok) return;
NAPI_CALL(env, napi_unwrap(env, args[1], reinterpret_cast<void**>(&obj2)));
napi_value sum;
status = napi_create_number(env, obj1->Val() + obj2->Val(), &sum);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, obj1->Val() + obj2->Val(), &sum));
status = napi_set_return_value(env, info, sum);
if (status != napi_ok) return;
return sum;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
MyObject::Init(env);
napi_property_descriptor desc[] = {
DECLARE_NAPI_METHOD("createObject", CreateObject),
DECLARE_NAPI_METHOD("add", Add),
DECLARE_NAPI_PROPERTY("createObject", CreateObject),
DECLARE_NAPI_PROPERTY("add", Add),
};
status =
napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env,
napi_define_properties(env, exports, sizeof(desc) / sizeof(*desc), desc));
}
NAPI_MODULE(addon, Init)

View File

@ -1,4 +1,5 @@
#include "myobject.h"
#include "../common.h"
MyObject::MyObject() : env_(nullptr), wrapper_(nullptr) {}
@ -25,41 +26,32 @@ napi_status MyObject::Init(napi_env env) {
return napi_ok;
}
void MyObject::New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value MyObject::New(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, &_this, nullptr));
MyObject* obj = new MyObject();
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype == napi_undefined) {
obj->val_ = 0;
} else {
status = napi_get_value_double(env, args[0], &obj->val_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &obj->val_));
}
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
obj->env_ = env;
status = napi_wrap(env,
jsthis,
obj,
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_);
if (status != napi_ok) return;
NAPI_CALL(env, napi_wrap(env,
_this,
obj,
MyObject::Destructor,
nullptr, // finalize_hint
&obj->wrapper_));
status = napi_set_return_value(env, info, jsthis);
if (status != napi_ok) return;
return _this;
}
napi_status MyObject::NewInstance(napi_env env,

View File

@ -17,7 +17,7 @@ class MyObject {
~MyObject();
static napi_ref constructor;
static void New(napi_env env, napi_callback_info info);
static napi_value New(napi_env env, napi_callback_info info);
double val_;
napi_env env_;
napi_ref wrapper_;

52
test/addons-napi/common.h Normal file
View File

@ -0,0 +1,52 @@
// Empty value so that macros here are able to return NULL or void
#define NAPI_RETVAL_NOTHING // Intentionally blank #define
#define GET_AND_THROW_LAST_ERROR(env) \
do { \
bool is_pending; \
napi_is_exception_pending((env), &is_pending); \
/* If an exception is already pending, don't rethrow it */ \
if (!is_pending) { \
const napi_extended_error_info* error_info; \
napi_get_last_error_info((env), &error_info); \
const char* error_message = error_info->error_message != NULL ? \
error_info->error_message : \
"empty error message"; \
napi_throw_error((env), error_message); \
} \
} while(0);
#define NAPI_ASSERT_BASE(env, assertion, message, ret_val) \
if (!(assertion)) { \
napi_throw_error( \
(env), \
"assertion (" #assertion ") failed: " message); \
return ret_val; \
}
// Returns NULL on failed assertion.
// This is meant to be used inside napi_callback methods.
#define NAPI_ASSERT(env, assertion, message) \
NAPI_ASSERT_BASE(env, assertion, message, NULL)
// Returns empty on failed assertion.
// This is meant to be used inside functions with void return type.
#define NAPI_ASSERT_RETURN_VOID(env, assertion, message) \
NAPI_ASSERT_BASE(env, assertion, message, NAPI_RETVAL_NOTHING)
#define NAPI_CALL_BASE(env, the_call, ret_val) \
if ((the_call) != napi_ok) { \
GET_AND_THROW_LAST_ERROR((env)); \
return ret_val; \
}
// Returns NULL if the_call doesn't return napi_ok.
#define NAPI_CALL(env, the_call) \
NAPI_CALL_BASE(env, the_call, NULL)
// Returns empty if the_call doesn't return napi_ok.
#define NAPI_CALL_RETURN_VOID(env, the_call) \
NAPI_CALL_BASE(env, the_call, NAPI_RETVAL_NOTHING)
#define DECLARE_NAPI_PROPERTY(name, func) \
{ (name), 0, (func), 0, 0, 0, napi_default, 0 }

View File

@ -1,137 +1,93 @@
#include <node_api.h>
#include <string.h>
#include "../common.h"
void Test(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 2) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (valuetype0 != napi_object) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an array as first argument.");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an array as first argument.");
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype1 != napi_number) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an integer as second argument.");
return;
}
NAPI_ASSERT(env, valuetype1 == napi_number,
"Wrong type of arguments. Expects an integer as second argument.");
napi_value array = args[0];
int index;
status = napi_get_value_int32(env, args[1], &index);
if (status != napi_ok) return;
int32_t index;
NAPI_CALL(env, napi_get_value_int32(env, args[1], &index));
NAPI_ASSERT(env, index >= 0, "Invalid index. Expects a positive integer.");
bool isarray;
status = napi_is_array(env, array, &isarray);
if (status != napi_ok) return;
NAPI_CALL(env, napi_is_array(env, array, &isarray));
if (isarray) {
uint32_t size;
status = napi_get_array_length(env, array, &size);
if (status != napi_ok) return;
if (index >= (int)(size)) {
napi_value str;
status = napi_create_string_utf8(env, "Index out of bound!", -1, &str);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, str);
if (status != napi_ok) return;
} else if (index < 0) {
napi_throw_type_error(env, "Invalid index. Expects a positive integer.");
} else {
napi_value ret;
status = napi_get_element(env, array, index, &ret);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, ret);
if (status != napi_ok) return;
}
}
}
void New(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
if (!isarray) {
return NULL;
}
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
uint32_t length;
NAPI_CALL(env, napi_get_array_length(env, array, &length));
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
if ((uint32_t)index >= length) {
napi_value str;
const char* str_val = "Index out of bound!";
size_t str_len = strlen(str_val);
NAPI_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str));
if (valuetype != napi_object) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an array as first argument.");
return;
return str;
}
napi_value ret;
status = napi_create_array(env, &ret);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_element(env, array, index, &ret));
return ret;
}
napi_value New(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valuetype0;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an array as first argument.");
napi_value ret;
NAPI_CALL(env, napi_create_array(env, &ret));
uint32_t i, length;
status = napi_get_array_length(env, args[0], &length);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_array_length(env, args[0], &length));
for (i = 0; i < length; i++) {
napi_value e;
status = napi_get_element(env, args[0], i, &e);
if (status != napi_ok) return;
status = napi_set_element(env, ret, i, e);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_element(env, args[0], i, &e));
NAPI_CALL(env, napi_set_element(env, ret, i, e));
}
status = napi_set_return_value(env, info, ret);
if (status != napi_ok) return;
return ret;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("Test", Test),
DECLARE_NAPI_METHOD("New", New),
DECLARE_NAPI_PROPERTY("Test", Test),
DECLARE_NAPI_PROPERTY("New", New),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,43 +1,26 @@
#include <stdlib.h>
#include <string.h>
#include <node_api.h>
#define JS_ASSERT(env, assertion, message) \
if (!(assertion)) { \
napi_throw_error( \
(env), \
"assertion (" #assertion ") failed: " message); \
return; \
}
#define NAPI_CALL(env, theCall) \
if ((theCall) != napi_ok) { \
const napi_extended_error_info* error; \
napi_get_last_error_info((env), &error); \
const char* errorMessage = error->error_message; \
errorMessage = errorMessage ? errorMessage : "empty error message"; \
napi_throw_error((env), errorMessage); \
return; \
}
#include "../common.h"
static const char theText[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
static int deleterCallCount = 0;
static void deleteTheText(napi_env env, void* data, void* finalize_hint) {
JS_ASSERT(env, data != NULL && strcmp(data, theText) == 0, "invalid data");
NAPI_ASSERT_RETURN_VOID(env, data != NULL && strcmp(data, theText) == 0, "invalid data");
(void)finalize_hint;
free(data);
deleterCallCount++;
}
static void noopDeleter(napi_env env, void* data, void* finalize_hint) {
JS_ASSERT(env, data != NULL && strcmp(data, theText) == 0, "invalid data");
NAPI_ASSERT_RETURN_VOID(env, data != NULL && strcmp(data, theText) == 0, "invalid data");
(void)finalize_hint;
deleterCallCount++;
}
void newBuffer(napi_env env, napi_callback_info info) {
napi_value newBuffer(napi_env env, napi_callback_info info) {
napi_value theBuffer;
char* theCopy;
const unsigned int kBufferSize = sizeof(theText);
@ -48,15 +31,16 @@ void newBuffer(napi_env env, napi_callback_info info) {
sizeof(theText),
(void**)(&theCopy),
&theBuffer));
JS_ASSERT(env, theCopy, "Failed to copy static text for newBuffer");
NAPI_ASSERT(env, theCopy, "Failed to copy static text for newBuffer");
memcpy(theCopy, theText, kBufferSize);
NAPI_CALL(env, napi_set_return_value(env, info, theBuffer));
return theBuffer;
}
void newExternalBuffer(napi_env env, napi_callback_info info) {
napi_value newExternalBuffer(napi_env env, napi_callback_info info) {
napi_value theBuffer;
char* theCopy = strdup(theText);
JS_ASSERT(env, theCopy, "Failed to copy static text for newExternalBuffer");
NAPI_ASSERT(env, theCopy, "Failed to copy static text for newExternalBuffer");
NAPI_CALL(env,
napi_create_external_buffer(
env,
@ -65,48 +49,50 @@ void newExternalBuffer(napi_env env, napi_callback_info info) {
deleteTheText,
NULL, // finalize_hint
&theBuffer));
NAPI_CALL(env, napi_set_return_value(env, info, theBuffer));
return theBuffer;
}
void getDeleterCallCount(napi_env env, napi_callback_info info) {
napi_value getDeleterCallCount(napi_env env, napi_callback_info info) {
napi_value callCount;
NAPI_CALL(env, napi_create_number(env, deleterCallCount, &callCount));
NAPI_CALL(env, napi_set_return_value(env, info, callCount));
return callCount;
}
void copyBuffer(napi_env env, napi_callback_info info) {
napi_value copyBuffer(napi_env env, napi_callback_info info) {
napi_value theBuffer;
NAPI_CALL(env, napi_create_buffer_copy(
env, sizeof(theText), theText, NULL, &theBuffer));
NAPI_CALL(env, napi_set_return_value(env, info, theBuffer));
return theBuffer;
}
void bufferHasInstance(napi_env env, napi_callback_info info) {
size_t argc;
NAPI_CALL(env, napi_get_cb_args_length(env, info, &argc));
JS_ASSERT(env, argc == 1, "Wrong number of arguments");
napi_value theBuffer;
NAPI_CALL(env, napi_get_cb_args(env, info, &theBuffer, 1));
napi_value bufferHasInstance(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
napi_value theBuffer = args[0];
bool hasInstance;
napi_valuetype theType;
NAPI_CALL(env, napi_typeof(env, theBuffer, &theType));
JS_ASSERT(env,
NAPI_ASSERT(env,
theType == napi_object,
"bufferHasInstance: instance is not an object");
NAPI_CALL(env, napi_is_buffer(env, theBuffer, &hasInstance));
JS_ASSERT(env, hasInstance, "bufferHasInstance: instance is not a buffer");
NAPI_ASSERT(env, hasInstance, "bufferHasInstance: instance is not a buffer");
napi_value returnValue;
NAPI_CALL(env, napi_get_boolean(env, hasInstance, &returnValue));
NAPI_CALL(env, napi_set_return_value(env, info, returnValue));
return returnValue;
}
void bufferInfo(napi_env env, napi_callback_info info) {
size_t argc;
NAPI_CALL(env, napi_get_cb_args_length(env, info, &argc));
JS_ASSERT(env, argc == 1, "Wrong number of arguments");
napi_value theBuffer, returnValue;
NAPI_CALL(env, napi_get_cb_args(env, info, &theBuffer, 1));
char* bufferData;
napi_value bufferInfo(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
napi_value theBuffer = args[0];
char *bufferData;
napi_value returnValue;
size_t bufferLength;
NAPI_CALL(env,
napi_get_buffer_info(
@ -117,10 +103,10 @@ void bufferInfo(napi_env env, napi_callback_info info) {
NAPI_CALL(env, napi_get_boolean(env,
!strcmp(bufferData, theText) && bufferLength == sizeof(theText),
&returnValue));
NAPI_CALL(env, napi_set_return_value(env, info, returnValue));
return returnValue;
}
void staticBuffer(napi_env env, napi_callback_info info) {
napi_value staticBuffer(napi_env env, napi_callback_info info) {
napi_value theBuffer;
NAPI_CALL(
env,
@ -130,31 +116,29 @@ void staticBuffer(napi_env env, napi_callback_info info) {
noopDeleter,
NULL, // finalize_hint
&theBuffer));
NAPI_CALL(env, napi_set_return_value(env, info, theBuffer));
return theBuffer;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_value theValue;
NAPI_CALL(env, napi_create_string_utf8(env,
theText, sizeof(theText), &theValue));
NAPI_CALL(env, napi_set_named_property(env, exports, "theText", theValue));
NAPI_CALL_RETURN_VOID(env,
napi_create_string_utf8(env, theText, sizeof(theText), &theValue));
NAPI_CALL_RETURN_VOID(env,
napi_set_named_property(env, exports, "theText", theValue));
napi_property_descriptor methods[] = {
DECLARE_NAPI_METHOD("newBuffer", newBuffer),
DECLARE_NAPI_METHOD("newExternalBuffer", newExternalBuffer),
DECLARE_NAPI_METHOD("getDeleterCallCount", getDeleterCallCount),
DECLARE_NAPI_METHOD("copyBuffer", copyBuffer),
DECLARE_NAPI_METHOD("bufferHasInstance", bufferHasInstance),
DECLARE_NAPI_METHOD("bufferInfo", bufferInfo),
DECLARE_NAPI_METHOD("staticBuffer", staticBuffer),
DECLARE_NAPI_PROPERTY("newBuffer", newBuffer),
DECLARE_NAPI_PROPERTY("newExternalBuffer", newExternalBuffer),
DECLARE_NAPI_PROPERTY("getDeleterCallCount", getDeleterCallCount),
DECLARE_NAPI_PROPERTY("copyBuffer", copyBuffer),
DECLARE_NAPI_PROPERTY("bufferHasInstance", bufferHasInstance),
DECLARE_NAPI_PROPERTY("bufferInfo", bufferInfo),
DECLARE_NAPI_PROPERTY("staticBuffer", staticBuffer),
};
NAPI_CALL(env,
napi_define_properties(
env, exports, sizeof(methods) / sizeof(methods[0]), methods));
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(methods) / sizeof(methods[0]), methods));
}
NAPI_MODULE(addon, Init)

View File

@ -1,107 +1,74 @@
#include <node_api.h>
#include "../common.h"
static double value_ = 1;
napi_ref constructor_;
void GetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value GetValue(napi_env env, napi_callback_info info) {
size_t argc = 0;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc != 0) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
NAPI_ASSERT(env, argc == 0, "Wrong number of arguments");
napi_value number;
status = napi_create_number(env, value_, &number);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, value_, &number));
status = napi_set_return_value(env, info, number);
if (status != napi_ok) return;
return number;
}
void SetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value SetValue(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
if (argc != 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
NAPI_CALL(env, napi_get_value_double(env, args[0], &value_));
napi_value arg;
status = napi_get_cb_args(env, info, &arg, 1);
if (status != napi_ok) return;
status = napi_get_value_double(env, arg, &value_);
if (status != napi_ok) return;
return NULL;
}
void Echo(napi_env env, napi_callback_info info) {
napi_status status;
napi_value Echo(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
if (argc != 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value arg;
status = napi_get_cb_args(env, info, &arg, 1);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, arg);
if (status != napi_ok) return;
return args[0];
}
void New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value New(napi_env env, napi_callback_info info) {
napi_value _this;
NAPI_CALL(env, napi_get_cb_info(env, info, NULL, NULL, NULL, &_this));
napi_value jsthis;
status = napi_get_cb_this(env, info, &jsthis);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, jsthis);
if (status != napi_ok) return;
return _this;
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_value number;
status = napi_create_number(env, value_, &number);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_create_number(env, value_, &number));
napi_property_descriptor properties[] = {
{ "echo", Echo, 0, 0, 0, napi_enumerable, 0 },
{ "readwriteValue", 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
{ "readonlyValue", 0, 0, 0, number, napi_enumerable, 0},
{ "hiddenValue", 0, 0, 0, number, napi_default, 0},
{ "readwriteAccessor1", 0, GetValue, SetValue, 0, napi_default, 0},
{ "readwriteAccessor2", 0, GetValue, SetValue, 0, napi_writable, 0},
{ "readonlyAccessor1", 0, GetValue, NULL, 0, napi_default, 0},
{ "readonlyAccessor2", 0, GetValue, NULL, 0, napi_writable, 0},
{ "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 },
{ "readwriteValue", 0, 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
{ "readonlyValue", 0, 0, 0, 0, number, napi_enumerable, 0},
{ "hiddenValue", 0, 0, 0, 0, number, napi_default, 0},
{ "readwriteAccessor1", 0, 0, GetValue, SetValue, 0, napi_default, 0},
{ "readwriteAccessor2", 0, 0, GetValue, SetValue, 0, napi_writable, 0},
{ "readonlyAccessor1", 0, 0, GetValue, NULL, 0, napi_default, 0},
{ "readonlyAccessor2", 0, 0, GetValue, NULL, 0, napi_writable, 0},
};
napi_value cons;
status = napi_define_class(env, "MyObject", New,
NULL, sizeof(properties)/sizeof(*properties), properties, &cons);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_class(env, "MyObject", New,
NULL, sizeof(properties)/sizeof(*properties), properties, &cons));
status = napi_set_named_property(env, module, "exports", cons);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env,
napi_set_named_property(env, module, "exports", cons));
status = napi_create_reference(env, cons, 1, &constructor_);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env,
napi_create_reference(env, cons, 1, &constructor_));
}
NAPI_MODULE(addon, Init)

View File

@ -1,237 +1,151 @@
#include <node_api.h>
#include "../common.h"
void ThrowLastError(napi_env env) {
const napi_extended_error_info* error_info;
napi_get_last_error_info(env, &error_info);
if (error_info->error_code != napi_ok) {
napi_throw_error(env, error_info->error_message);
}
}
void AsBool(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsBool(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
bool value;
status = napi_get_value_bool(env, input, &value);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_value_bool(env, args[0], &value));
napi_value output;
status = napi_get_boolean(env, value, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_boolean(env, value, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void AsInt32(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsInt32(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
int32_t value;
status = napi_get_value_int32(env, input, &value);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_value_int32(env, args[0], &value));
napi_value output;
status = napi_create_number(env, value, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_create_number(env, value, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void AsUInt32(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsUInt32(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
uint32_t value;
status = napi_get_value_uint32(env, input, &value);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_value_uint32(env, args[0], &value));
napi_value output;
status = napi_create_number(env, value, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_create_number(env, value, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void AsInt64(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsInt64(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
int64_t value;
status = napi_get_value_int64(env, input, &value);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_value_int64(env, args[0], &value));
napi_value output;
status = napi_create_number(env, (double)value, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_create_number(env, (double)value, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void AsDouble(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsDouble(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
double value;
status = napi_get_value_double(env, input, &value);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_get_value_double(env, args[0], &value));
napi_value output;
status = napi_create_number(env, value, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_create_number(env, value, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void AsString(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value AsString(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
char value[100];
status = napi_get_value_string_utf8(env, input, value, sizeof(value), NULL);
if (status != napi_ok) goto done;
NAPI_CALL(env,
napi_get_value_string_utf8(env, args[0], value, sizeof(value), NULL));
napi_value output;
status = napi_create_string_utf8(env, value, -1, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_create_string_utf8(env, value, -1, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void ToBool(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value ToBool(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value output;
status = napi_coerce_to_bool(env, input, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_coerce_to_bool(env, args[0], &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void ToNumber(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value ToNumber(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value output;
status = napi_coerce_to_number(env, input, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_coerce_to_number(env, args[0], &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void ToObject(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value ToObject(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value output;
status = napi_coerce_to_object(env, input, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_coerce_to_object(env, args[0], &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
void ToString(napi_env env, napi_callback_info info) {
napi_status status;
napi_value input;
status = napi_get_cb_args(env, info, &input, 1);
if (status != napi_ok) goto done;
napi_value ToString(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value output;
status = napi_coerce_to_string(env, input, &output);
if (status != napi_ok) goto done;
NAPI_CALL(env, napi_coerce_to_string(env, args[0], &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) goto done;
done:
if (status != napi_ok) ThrowLastError(env);
return output;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("asBool", AsBool),
DECLARE_NAPI_METHOD("asInt32", AsInt32),
DECLARE_NAPI_METHOD("asUInt32", AsUInt32),
DECLARE_NAPI_METHOD("asInt64", AsInt64),
DECLARE_NAPI_METHOD("asDouble", AsDouble),
DECLARE_NAPI_METHOD("asString", AsString),
DECLARE_NAPI_METHOD("toBool", ToBool),
DECLARE_NAPI_METHOD("toNumber", ToNumber),
DECLARE_NAPI_METHOD("toObject", ToObject),
DECLARE_NAPI_METHOD("toString", ToString),
DECLARE_NAPI_PROPERTY("asBool", AsBool),
DECLARE_NAPI_PROPERTY("asInt32", AsInt32),
DECLARE_NAPI_PROPERTY("asUInt32", AsUInt32),
DECLARE_NAPI_PROPERTY("asInt64", AsInt64),
DECLARE_NAPI_PROPERTY("asDouble", AsDouble),
DECLARE_NAPI_PROPERTY("asString", AsString),
DECLARE_NAPI_PROPERTY("toBool", ToBool),
DECLARE_NAPI_PROPERTY("toNumber", ToNumber),
DECLARE_NAPI_PROPERTY("toObject", ToObject),
DECLARE_NAPI_PROPERTY("toString", ToString),
};
napi_status status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,37 +1,27 @@
#include <node_api.h>
#include "../common.h"
void checkError(napi_env e, napi_callback_info info) {
napi_status status;
napi_value jsError;
status = napi_get_cb_args(e, info, &jsError, 1);
if (status != napi_ok) return;
napi_value checkError(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, nullptr, nullptr));
bool r;
status = napi_is_error(e, jsError, &r);
if (status != napi_ok) return;
NAPI_CALL(env, napi_is_error(env, args[0], &r));
napi_value result;
status = napi_get_boolean(e, r, &result);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_boolean(env, r, &result));
status = napi_set_return_value(e, info, result);
if (status != napi_ok) return;
return result;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("checkError", checkError),
DECLARE_NAPI_PROPERTY("checkError", checkError),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,75 +1,59 @@
#include <node_api.h>
#include "../common.h"
static bool exceptionWasPending = false;
void returnException(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsFunction;
status = napi_get_cb_args(env, info, &jsFunction, 1);
if (status != napi_ok) return;
napi_value returnException(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value global;
status = napi_get_global(env, &global);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_global(env, &global));
napi_value result;
status = napi_call_function(env, global, jsFunction, 0, 0, &result);
if (status == napi_pending_exception) {
napi_status status = napi_call_function(env, global, args[0], 0, 0, &result);
if (status == napi_pending_exception) {
napi_value ex;
status = napi_get_and_clear_last_exception(env, &ex);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, ex);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_and_clear_last_exception(env, &ex));
return ex;
}
return NULL;
}
void allowException(napi_env env, napi_callback_info info) {
napi_status status;
napi_value jsFunction;
status = napi_get_cb_args(env, info, &jsFunction, 1);
if (status != napi_ok) return;
napi_value allowException(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value global;
status = napi_get_global(env, &global);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_global(env, &global));
napi_value result;
status = napi_call_function(env, global, jsFunction, 0, 0, &result);
napi_call_function(env, global, args[0], 0, 0, &result);
// Ignore status and check napi_is_exception_pending() instead.
status = napi_is_exception_pending(env, &exceptionWasPending);
if (status != napi_ok) return;
NAPI_CALL(env, napi_is_exception_pending(env, &exceptionWasPending));
return NULL;
}
void wasPending(napi_env env, napi_callback_info info) {
napi_status status;
napi_value wasPending(napi_env env, napi_callback_info info) {
napi_value result;
status = napi_get_boolean(env, exceptionWasPending, &result);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_boolean(env, exceptionWasPending, &result));
status = napi_set_return_value(env, info, result);
if (status != napi_ok) return;
return result;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("returnException", returnException),
DECLARE_NAPI_METHOD("allowException", allowException),
DECLARE_NAPI_METHOD("wasPending", wasPending),
DECLARE_NAPI_PROPERTY("returnException", returnException),
DECLARE_NAPI_PROPERTY("allowException", allowException),
DECLARE_NAPI_PROPERTY("wasPending", wasPending),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,55 +1,35 @@
#include <node_api.h>
#include "../common.h"
void Test(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 10;
napi_value args[10];
status = napi_get_cb_args(env, info, args, 10);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc > 0, "Wrong number of arguments");
if (valuetype != napi_function) {
napi_throw_type_error(env, "Wrong type of argments. Expects a function.");
return;
}
napi_valuetype valuetype0;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
NAPI_ASSERT(env, valuetype0 == napi_function,
"Wrong type of arguments. Expects a number as first argument.");
napi_value function = args[0];
napi_value* argv = args + 1;
argc = argc - 1;
napi_value global;
status = napi_get_global(env, &global);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_global(env, &global));
napi_value result;
status = napi_call_function(env, global, function, argc, argv, &result);
if (status != napi_ok) return;
NAPI_CALL(env, napi_call_function(env, global, args[0], argc, argv, &result));
status = napi_set_return_value(env, info, result);
if (status != napi_ok) return;
return result;
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_value fn;
status = napi_create_function(env, NULL, Test, NULL, &fn);
if (status != napi_ok) return;
status = napi_set_named_property(env, exports, "Test", fn);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_create_function(env, NULL, Test, NULL, &fn));
NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, exports, "Test", fn));
}
NAPI_MODULE(addon, Init)

View File

@ -1,39 +1,28 @@
#include <node_api.h>
#include <stdio.h>
#include "../common.h"
void doInstanceOf(napi_env env, napi_callback_info info) {
napi_status status;
napi_value arguments[2];
status = napi_get_cb_args(env, info, arguments, 2);
if (status != napi_ok) return;
napi_value doInstanceOf(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
bool instanceof;
status = napi_instanceof(env, arguments[0], arguments[1], &instanceof);
if (status != napi_ok) return;
NAPI_CALL(env, napi_instanceof(env, args[0], args[1], &instanceof));
napi_value result;
status = napi_get_boolean(env, instanceof, &result);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_boolean(env, instanceof, &result));
status = napi_set_return_value(env, info, result);
if (status != napi_ok) return;
return result;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("doInstanceOf", doInstanceOf),
DECLARE_NAPI_PROPERTY("doInstanceOf", doInstanceOf),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,47 +1,37 @@
#include <node_api.h>
#include "../common.h"
#define DECLARE_NAPI_METHOD(func) \
{ #func, func, 0, 0, 0, napi_default, 0 }
void createNapiError(napi_env env, napi_callback_info info) {
napi_status status;
napi_value createNapiError(napi_env env, napi_callback_info info) {
napi_value value;
NAPI_CALL(env, napi_create_string_utf8(env, "xyz", 3, &value));
double double_value;
napi_status status = napi_get_value_double(env, value, &double_value);
status = napi_create_string_utf8(env, "xyz", 3, &value);
if (status != napi_ok) return;
NAPI_ASSERT(env, status != napi_ok, "Failed to produce error condition");
status = napi_get_value_double(env, value, &double_value);
if (status == napi_ok) {
napi_throw_error(env, "Failed to produce error condition");
}
return nullptr;
}
void testNapiErrorCleanup(napi_env env, napi_callback_info info) {
napi_status status;
napi_value testNapiErrorCleanup(napi_env env, napi_callback_info info) {
const napi_extended_error_info *error_info = 0;
NAPI_CALL(env, napi_get_last_error_info(env, &error_info));
napi_value result;
bool is_ok = error_info->error_code == napi_ok;
NAPI_CALL(env, napi_get_boolean(env, is_ok, &result));
status = napi_get_last_error_info(env, &error_info);
if (status != napi_ok) return;
status = napi_get_boolean(env, (error_info->error_code == napi_ok), &result);
if (status != napi_ok) return;
napi_set_return_value(env, info, result);
return result;
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD(createNapiError),
DECLARE_NAPI_METHOD(testNapiErrorCleanup)
DECLARE_NAPI_PROPERTY("createNapiError", createNapiError),
DECLARE_NAPI_PROPERTY("testNapiErrorCleanup", testNapiErrorCleanup),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,55 +1,35 @@
#include <node_api.h>
#include "../common.h"
void Test(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
if (valuetype != napi_number) {
napi_throw_type_error(env, "Wrong type of argments. Expects a number.");
return;
}
napi_valuetype valuetype0;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
NAPI_ASSERT(env, valuetype0 == napi_number,
"Wrong type of arguments. Expects a number as first argument.");
double input;
status = napi_get_value_double(env, args[0], &input);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[0], &input));
napi_value output;
status = napi_create_number(env, input, &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, input, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("Test", Test),
DECLARE_NAPI_PROPERTY("Test", Test),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,246 +1,154 @@
#include <node_api.h>
#include "../common.h"
#include <string.h>
void Get(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 2) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Get(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (valuetype0 != napi_object) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an object as first argument.");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype1 != napi_string && valuetype1 != napi_symbol) {
napi_throw_type_error(env,
"Wrong type of argments. Expects a string or symbol as second.");
return;
}
NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
napi_value object = args[0];
napi_value output;
status = napi_get_property(env, object, args[1], &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_property(env, object, args[1], &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
void Set(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 3) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Set(napi_env env, napi_callback_info info) {
size_t argc = 3;
napi_value args[3];
status = napi_get_cb_args(env, info, args, 3);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 3, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (valuetype0 != napi_object) {
napi_throw_type_error(env,
"Wrong type of argments. Expects an object as first argument.");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype1 != napi_string && valuetype1 != napi_symbol) {
napi_throw_type_error(env,
"Wrong type of argments. Expects a string or symbol as second.");
return;
}
NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
napi_value object = args[0];
status = napi_set_property(env, object, args[1], args[2]);
if (status != napi_ok) return;
NAPI_CALL(env, napi_set_property(env, args[0], args[1], args[2]));
napi_value valuetrue;
status = napi_get_boolean(env, true, &valuetrue);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_boolean(env, true, &valuetrue))
status = napi_set_return_value(env, info, valuetrue);
if (status != napi_ok) return;
return valuetrue;
}
void Has(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 2) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Has(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (valuetype0 != napi_object) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an object as first argument.");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype1 != napi_string && valuetype1 != napi_symbol) {
napi_throw_type_error(env,
"Wrong type of argments. Expects a string or symbol as second.");
return;
}
NAPI_ASSERT(env, valuetype1 == napi_string || valuetype1 == napi_symbol,
"Wrong type of arguments. Expects a string or symbol as second.");
napi_value obj = args[0];
bool has_property;
status = napi_has_property(env, obj, args[1], &has_property);
if (status != napi_ok) return;
NAPI_CALL(env, napi_has_property(env, args[0], args[1], &has_property));
napi_value ret;
status = napi_get_boolean(env, has_property, &ret);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_boolean(env, has_property, &ret));
status = napi_set_return_value(env, info, ret);
if (status != napi_ok) return;
return ret;
}
void New(napi_env env, napi_callback_info info) {
napi_status status;
napi_value New(napi_env env, napi_callback_info info) {
napi_value ret;
status = napi_create_object(env, &ret);
NAPI_CALL(env, napi_create_object(env, &ret));
napi_value num;
status = napi_create_number(env, 987654321, &num);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, 987654321, &num));
status = napi_set_named_property(env, ret, "test_number", num);
if (status != napi_ok) return;
NAPI_CALL(env, napi_set_named_property(env, ret, "test_number", num));
napi_value str;
status = napi_create_string_utf8(env, "test string", -1, &str);
if (status != napi_ok) return;
const char* str_val = "test string";
size_t str_len = strlen(str_val);
NAPI_CALL(env, napi_create_string_utf8(env, str_val, str_len, &str));
status = napi_set_named_property(env, ret, "test_string", str);
if (status != napi_ok) return;
NAPI_CALL(env, napi_set_named_property(env, ret, "test_string", str));
status = napi_set_return_value(env, info, ret);
if (status != napi_ok) return;
return ret;
}
void Inflate(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Inflate(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
if (valuetype != napi_object) {
napi_throw_type_error(
env, "Wrong type of argments. Expects an object as first argument.");
return;
}
napi_valuetype valuetype0;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of arguments. Expects an object as first argument.");
napi_value obj = args[0];
napi_value propertynames;
status = napi_get_property_names(env, obj, &propertynames);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_property_names(env, obj, &propertynames));
uint32_t i, length;
status = napi_get_array_length(env, propertynames, &length);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_array_length(env, propertynames, &length));
for (i = 0; i < length; i++) {
napi_value property_str;
status = napi_get_element(env, propertynames, i, &property_str);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_element(env, propertynames, i, &property_str));
napi_value value;
status = napi_get_property(env, obj, property_str, &value);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_property(env, obj, property_str, &value));
double double_val;
status = napi_get_value_double(env, value, &double_val);
if (status != napi_ok) return;
status = napi_create_number(env, double_val + 1, &value);
if (status != napi_ok) return;
status = napi_set_property(env, obj, property_str, value);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, value, &double_val));
NAPI_CALL(env, napi_create_number(env, double_val + 1, &value));
NAPI_CALL(env, napi_set_property(env, obj, property_str, value));
}
status = napi_set_return_value(env, info, obj);
return obj;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("Get", Get),
DECLARE_NAPI_METHOD("Set", Set),
DECLARE_NAPI_METHOD("Has", Has),
DECLARE_NAPI_METHOD("New", New),
DECLARE_NAPI_METHOD("Inflate", Inflate),
DECLARE_NAPI_PROPERTY("Get", Get),
DECLARE_NAPI_PROPERTY("Set", Set),
DECLARE_NAPI_PROPERTY("Has", Has),
DECLARE_NAPI_PROPERTY("New", New),
DECLARE_NAPI_PROPERTY("Inflate", Inflate),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)

View File

@ -1,88 +1,59 @@
#include <node_api.h>
#include "../common.h"
static double value_ = 1;
void GetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value GetValue(napi_env env, napi_callback_info info) {
size_t argc = 0;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, NULL, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc != 0) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
NAPI_ASSERT(env, argc == 0, "Wrong number of arguments");
napi_value number;
status = napi_create_number(env, value_, &number);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, value_, &number));
status = napi_set_return_value(env, info, number);
if (status != napi_ok) return;
return number;
}
void SetValue(napi_env env, napi_callback_info info) {
napi_status status;
napi_value SetValue(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
if (argc != 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
NAPI_CALL(env, napi_get_value_double(env, args[0], &value_));
napi_value arg;
status = napi_get_cb_args(env, info, &arg, 1);
if (status != napi_ok) return;
status = napi_get_value_double(env, arg, &value_);
if (status != napi_ok) return;
return NULL;
}
void Echo(napi_env env, napi_callback_info info) {
napi_status status;
napi_value Echo(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
if (argc != 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value arg;
status = napi_get_cb_args(env, info, &arg, 1);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, arg);
if (status != napi_ok) return;
return args[0];
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_value number;
status = napi_create_number(env, value_, &number);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_create_number(env, value_, &number));
napi_property_descriptor properties[] = {
{ "echo", Echo, 0, 0, 0, napi_enumerable, 0 },
{ "readwriteValue", 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
{ "readonlyValue", 0, 0, 0, number, napi_enumerable, 0},
{ "hiddenValue", 0, 0, 0, number, napi_default, 0},
{ "readwriteAccessor1", 0, GetValue, SetValue, 0, napi_default, 0},
{ "readwriteAccessor2", 0, GetValue, SetValue, 0, napi_writable, 0},
{ "readonlyAccessor1", 0, GetValue, NULL, 0, napi_default, 0},
{ "readonlyAccessor2", 0, GetValue, NULL, 0, napi_writable, 0},
{ "echo", 0, Echo, 0, 0, 0, napi_enumerable, 0 },
{ "readwriteValue", 0, 0, 0, 0, number, napi_enumerable | napi_writable, 0 },
{ "readonlyValue", 0, 0, 0, 0, number, napi_enumerable, 0},
{ "hiddenValue", 0, 0, 0, 0, number, napi_default, 0},
{ "readwriteAccessor1", 0, 0, GetValue, SetValue, 0, napi_default, 0},
{ "readwriteAccessor2", 0, 0, GetValue, SetValue, 0, napi_writable, 0},
{ "readonlyAccessor1", 0, 0, GetValue, NULL, 0, napi_default, 0},
{ "readonlyAccessor2", 0, 0, GetValue, NULL, 0, napi_writable, 0},
};
status = napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));
}
NAPI_MODULE(addon, Init)

View File

@ -1,134 +1,85 @@
#include <node_api.h>
#include "../common.h"
void Copy(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Copy(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_string) {
napi_throw_type_error(env, "Wrong type of argments. Expects a string.");
return;
}
NAPI_ASSERT(env, valuetype == napi_string,
"Wrong type of argment. Expects a string.");
char buffer[128];
int buffer_size = 128;
size_t buffer_size = 128;
size_t copied;
status =
napi_get_value_string_utf8(env, args[0], buffer, buffer_size, NULL);
if (status != napi_ok) return;
NAPI_CALL(env,
napi_get_value_string_utf8(env, args[0], buffer, buffer_size, &copied));
napi_value output;
status = napi_create_string_utf8(env, buffer, -1, &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_string_utf8(env, buffer, copied-1, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
void Length(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Length(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_string) {
napi_throw_type_error(env, "Wrong type of argments. Expects a string.");
return;
}
NAPI_ASSERT(env, valuetype == napi_string,
"Wrong type of argment. Expects a string.");
size_t length;
status = napi_get_value_string_length(env, args[0], &length);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_string_length(env, args[0], &length));
napi_value output;
status = napi_create_number(env, (double)length, &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, (double)length, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
void Utf8Length(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Utf8Length(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_string) {
napi_throw_type_error(env, "Wrong type of argments. Expects a string.");
return;
}
NAPI_ASSERT(env, valuetype == napi_string,
"Wrong type of argment. Expects a string.");
size_t length;
status = napi_get_value_string_utf8(env, args[0], NULL, 0, &length);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_string_utf8(env, args[0], NULL, 0, &length));
napi_value output;
status = napi_create_number(env, (double)length, &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_number(env, (double)length, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor properties[] = {
DECLARE_NAPI_METHOD("Copy", Copy),
DECLARE_NAPI_METHOD("Length", Length),
DECLARE_NAPI_METHOD("Utf8Length", Utf8Length),
DECLARE_NAPI_PROPERTY("Copy", Copy),
DECLARE_NAPI_PROPERTY("Length", Length),
DECLARE_NAPI_PROPERTY("Utf8Length", Utf8Length),
};
status = napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));
}
NAPI_MODULE(addon, Init)

View File

@ -1,94 +1,60 @@
#include <node_api.h>
#include "../common.h"
void Test(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc < 1) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Test(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
status = napi_get_cb_args(env, info, args, 1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc >= 1, "Wrong number of arguments");
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_symbol) {
napi_throw_type_error(env, "Wrong type of argments. Expects a symbol.");
return;
}
NAPI_ASSERT(env, valuetype == napi_symbol,
"Wrong type of argments. Expects a symbol.");
char buffer[128];
int buffer_size = 128;
size_t buffer_size = 128;
status =
napi_get_value_string_utf8(env, args[0], buffer, buffer_size, NULL);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_string_utf8(
env, args[0], buffer, buffer_size, NULL));
napi_value output;
status = napi_create_string_utf8(env, buffer, -1, &output);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_string_utf8(env, buffer, buffer_size, &output));
status = napi_set_return_value(env, info, output);
if (status != napi_ok) return;
return output;
}
void New(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
napi_value New(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1];
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value description = NULL;
if (argc >= 1) {
napi_value args[1];
napi_get_cb_args(env, info, args, 1);
napi_valuetype valuetype;
status = napi_typeof(env, args[0], &valuetype);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype));
if (valuetype != napi_string) {
napi_throw_type_error(env, "Wrong type of argments. Expects a string.");
return;
}
NAPI_ASSERT(env, valuetype == napi_string,
"Wrong type of arguments. Expects a string.");
napi_value symbol;
status = napi_create_symbol(env, args[0], &symbol);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, symbol);
if (status != napi_ok) return;
} else {
napi_value symbol;
status = napi_create_symbol(env, NULL, &symbol);
if (status != napi_ok) return;
status = napi_set_return_value(env, info, symbol);
if (status != napi_ok) return;
description = args[0];
}
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
napi_value symbol;
NAPI_CALL(env, napi_create_symbol(env, description, &symbol));
return symbol;
}
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor properties[] = {
DECLARE_NAPI_METHOD("New", New),
DECLARE_NAPI_PROPERTY("New", New),
};
status = napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(properties) / sizeof(*properties), properties));
}
NAPI_MODULE(addon, Init)

View File

@ -1,82 +1,56 @@
#include <node_api.h>
#include <string.h>
#include "../common.h"
void Multiply(napi_env env, napi_callback_info info) {
napi_status status;
size_t argc;
status = napi_get_cb_args_length(env, info, &argc);
if (status != napi_ok) return;
if (argc != 2) {
napi_throw_type_error(env, "Wrong number of arguments");
return;
}
napi_value Multiply(napi_env env, napi_callback_info info) {
size_t argc = 2;
napi_value args[2];
status = napi_get_cb_args(env, info, args, 2);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
NAPI_ASSERT(env, argc == 2, "Wrong number of arguments");
napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (valuetype0 != napi_object) {
napi_throw_type_error(
env,
"Wrong type of argments. Expects a typed array as first argument.");
return;
}
NAPI_ASSERT(env, valuetype0 == napi_object,
"Wrong type of argments. Expects a typed array as first argument.");
napi_value input_array = args[0];
bool istypedarray;
status = napi_is_typedarray(env, input_array, &istypedarray);
if (status != napi_ok) return;
bool is_typedarray;
NAPI_CALL(env, napi_is_typedarray(env, input_array, &is_typedarray));
if (!istypedarray) {
napi_throw_type_error(
env,
"Wrong type of argments. Expects a typed array as first argument.");
return;
}
NAPI_ASSERT(env, is_typedarray,
"Wrong type of argments. Expects a typed array as first argument.");
napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1);
if (status != napi_ok) return;
NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (valuetype1 != napi_number) {
napi_throw_type_error(
env, "Wrong type of argments. Expects a number as second argument.");
return;
}
NAPI_ASSERT(env, valuetype1 == napi_number,
"Wrong type of argments. Expects a number as second argument.");
double multiplier;
status = napi_get_value_double(env, args[1], &multiplier);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_value_double(env, args[1], &multiplier));
napi_typedarray_type type;
napi_value input_buffer;
size_t byte_offset;
size_t i, length;
status = napi_get_typedarray_info(
env, input_array, &type, &length, NULL, &input_buffer, &byte_offset);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_typedarray_info(
env, input_array, &type, &length, NULL, &input_buffer, &byte_offset));
void* data;
size_t byte_length;
status = napi_get_arraybuffer_info(env, input_buffer, &data, &byte_length);
if (status != napi_ok) return;
NAPI_CALL(env, napi_get_arraybuffer_info(
env, input_buffer, &data, &byte_length));
napi_value output_buffer;
void* output_ptr = NULL;
status =
napi_create_arraybuffer(env, byte_length, &output_ptr, &output_buffer);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_arraybuffer(
env, byte_length, &output_ptr, &output_buffer));
napi_value output_array;
status = napi_create_typedarray(
env, type, length, output_buffer, byte_offset, &output_array);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_typedarray(
env, type, length, output_buffer, byte_offset, &output_array));
if (type == napi_uint8_array) {
uint8_t* input_bytes = (uint8_t*)(data) + byte_offset;
@ -92,53 +66,43 @@ void Multiply(napi_env env, napi_callback_info info) {
}
} else {
napi_throw_error(env, "Typed array was of a type not expected by test.");
return;
return NULL;
}
status = napi_set_return_value(env, info, output_array);
if (status != napi_ok) return;
return output_array;
}
void External(napi_env env, napi_callback_info info) {
napi_value External(napi_env env, napi_callback_info info) {
static int8_t externalData[] = {0, 1, 2};
napi_value output_buffer;
napi_status status = napi_create_external_arraybuffer(
env,
externalData,
sizeof(externalData),
NULL, // finalize_callback
NULL, // finalize_hint
&output_buffer);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_external_arraybuffer(
env,
externalData,
sizeof(externalData),
NULL, // finalize_callback
NULL, // finalize_hint
&output_buffer));
napi_value output_array;
status = napi_create_typedarray(env,
napi_int8_array,
sizeof(externalData) / sizeof(uint8_t),
output_buffer,
0,
&output_array);
if (status != napi_ok) return;
NAPI_CALL(env, napi_create_typedarray(env,
napi_int8_array,
sizeof(externalData) / sizeof(int8_t),
output_buffer,
0,
&output_array));
status = napi_set_return_value(env, info, output_array);
if (status != napi_ok) return;
return output_array;
}
#define DECLARE_NAPI_METHOD(name, func) \
{ name, func, 0, 0, 0, napi_default, 0 }
void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("Multiply", Multiply),
DECLARE_NAPI_METHOD("External", External),
DECLARE_NAPI_PROPERTY("Multiply", Multiply),
DECLARE_NAPI_PROPERTY("External", External),
};
status = napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors);
if (status != napi_ok) return;
NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
}
NAPI_MODULE(addon, Init)