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; 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 { namespace v8impl {
// convert from n-api property attributes to v8::PropertyAttribute // convert from n-api property attributes to v8::PropertyAttribute
@ -127,6 +191,22 @@ v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
return local; 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. // Adapter for napi_finalize callbacks.
class Finalizer { class Finalizer {
protected: protected:
@ -361,13 +441,19 @@ class CallbackWrapperBase : public CallbackWrapper {
v8::Local<v8::External>::Cast( v8::Local<v8::External>::Cast(
_cbdata->GetInternalField(kInternalFieldIndex))->Value()); _cbdata->GetInternalField(kInternalFieldIndex))->Value());
v8::Isolate* isolate = _cbinfo.GetIsolate(); v8::Isolate* isolate = _cbinfo.GetIsolate();
napi_env env = static_cast<napi_env>( napi_env env = static_cast<napi_env>(
v8::Local<v8::External>::Cast( v8::Local<v8::External>::Cast(
_cbdata->GetInternalField(kEnvIndex))->Value()); _cbdata->GetInternalField(kEnvIndex))->Value());
// Make sure any errors encountered last time we were in N-API are gone. // Make sure any errors encountered last time we were in N-API are gone.
napi_clear_last_error(env); 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()) { if (!env->last_exception.IsEmpty()) {
isolate->ThrowException( isolate->ThrowException(
@ -608,75 +694,12 @@ void napi_module_register(napi_module* mod) {
node::node_module_register(nm); 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 // Warning: Keep in-sync with napi_status enum
const char* error_messages[] = {nullptr, const char* error_messages[] = {nullptr,
"Invalid pointer passed as argument", "Invalid pointer passed as argument",
"An object was expected", "An object was expected",
"A string was expected", "A string was expected",
"A string or symbol was expected",
"A function was expected", "A function was expected",
"A number was expected", "A number was expected",
"A boolean was expected", "A boolean was expected",
@ -793,8 +816,14 @@ napi_status napi_define_class(napi_env env,
continue; continue;
} }
v8::Local<v8::String> property_name; v8::Local<v8::Name> property_name;
CHECK_NEW_FROM_UTF8(env, property_name, p->utf8name); napi_status status =
v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
if (status != napi_ok) {
return napi_set_last_error(env, status);
}
v8::PropertyAttribute attributes = v8::PropertyAttribute attributes =
v8impl::V8PropertyAttributesFromDescriptor(p); v8impl::V8PropertyAttributesFromDescriptor(p);
@ -822,7 +851,6 @@ napi_status napi_define_class(napi_env env,
v8impl::FunctionCallbackWrapper::Invoke, v8impl::FunctionCallbackWrapper::Invoke,
cbdata, cbdata,
v8::Signature::New(isolate, tpl)); v8::Signature::New(isolate, tpl));
t->SetClassName(property_name);
tpl->PrototypeTemplate()->Set(property_name, t, attributes); tpl->PrototypeTemplate()->Set(property_name, t, attributes);
} else { } else {
@ -855,18 +883,6 @@ napi_status napi_define_class(napi_env env,
return GET_RETURN_STATUS(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_status napi_get_property_names(napi_env env,
napi_value object, napi_value object,
napi_value* result) { napi_value* result) {
@ -1102,11 +1118,16 @@ napi_status napi_define_properties(napi_env env,
for (size_t i = 0; i < property_count; i++) { for (size_t i = 0; i < property_count; i++) {
const napi_property_descriptor* p = &properties[i]; const napi_property_descriptor* p = &properties[i];
v8::Local<v8::Name> name; v8::Local<v8::Name> property_name;
CHECK_NEW_FROM_UTF8(env, name, p->utf8name); napi_status status =
v8impl::V8NameFromPropertyDescriptor(env, p, &property_name);
if (status != napi_ok) {
return napi_set_last_error(env, status);
}
v8::PropertyAttribute attributes = v8::PropertyAttribute attributes =
v8impl::V8PropertyAttributesFromDescriptor(p); v8impl::V8PropertyAttributesFromDescriptor(p);
if (p->getter != nullptr || p->setter != nullptr) { if (p->getter != nullptr || p->setter != nullptr) {
v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData( v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
@ -1117,7 +1138,7 @@ napi_status napi_define_properties(napi_env env,
auto set_maybe = obj->SetAccessor( auto set_maybe = obj->SetAccessor(
context, context,
name, property_name,
p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr, p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr,
p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr, p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
cbdata, cbdata,
@ -1136,8 +1157,8 @@ napi_status napi_define_properties(napi_env env,
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New( v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(
isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata); isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
auto define_maybe = auto define_maybe = obj->DefineOwnProperty(
obj->DefineOwnProperty(context, name, t->GetFunction(), attributes); context, property_name, t->GetFunction(), attributes);
if (!define_maybe.FromMaybe(false)) { if (!define_maybe.FromMaybe(false)) {
return napi_set_last_error(env, napi_generic_failure); 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); v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
auto define_maybe = auto define_maybe =
obj->DefineOwnProperty(context, name, value, attributes); obj->DefineOwnProperty(context, property_name, value, attributes);
if (!define_maybe.FromMaybe(false)) { if (!define_maybe.FromMaybe(false)) {
return napi_set_last_error(env, napi_invalid_arg); 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 napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
void** data) { // [out] Receives the data pointer for the callback. void** data) { // [out] Receives the data pointer for the callback.
CHECK_ENV(env); CHECK_ENV(env);
CHECK_ARG(env, argc);
CHECK_ARG(env, argv);
CHECK_ARG(env, this_arg);
CHECK_ARG(env, data);
v8impl::CallbackWrapper* info = v8impl::CallbackWrapper* info =
reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo); reinterpret_cast<v8impl::CallbackWrapper*>(cbinfo);
info->Args(argv, std::min(*argc, info->ArgsLength())); if (argv != nullptr) {
*argc = info->ArgsLength(); CHECK_ARG(env, argc);
*this_arg = info->This(); info->Args(argv, std::min(*argc, info->ArgsLength()));
*data = info->Data(); }
if (argc != nullptr) {
*argc = info->ArgsLength();
}
if (this_arg != nullptr) {
*this_arg = info->This();
}
if (data != nullptr) {
*data = info->Data();
}
return napi_ok; 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_status napi_is_construct_call(napi_env env,
napi_callback_info cbinfo, napi_callback_info cbinfo,
bool* result) { bool* result) {
@ -1483,51 +1495,6 @@ napi_status napi_is_construct_call(napi_env env,
return napi_ok; 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_status napi_call_function(napi_env env,
napi_value recv, napi_value recv,
napi_value func, 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 size_t* argc, // [in-out] Specifies the size of the provided argv array
// and receives the actual count of args. // and receives the actual count of args.
napi_value* argv, // [out] Array of values napi_value* argv, // [out] Array of values
napi_value* thisArg, // [out] Receives the JS 'this' arg for the call napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
void** data); // [out] Receives the data pointer for the callback. 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_EXTERN napi_status napi_is_construct_call(napi_env env,
napi_callback_info cbinfo, napi_callback_info cbinfo,
bool* result); 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_EXTERN napi_status
napi_define_class(napi_env env, napi_define_class(napi_env env,
const char* utf8name, 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_escapable_handle_scope__ *napi_escapable_handle_scope;
typedef struct napi_callback_info__ *napi_callback_info; typedef struct napi_callback_info__ *napi_callback_info;
typedef void (*napi_callback)(napi_env env, typedef napi_value (*napi_callback)(napi_env env,
napi_callback_info info); napi_callback_info info);
typedef void (*napi_finalize)(napi_env env, typedef void (*napi_finalize)(napi_env env,
void* finalize_data, void* finalize_data,
void* finalize_hint); void* finalize_hint);
@ -35,7 +35,9 @@ typedef enum {
} napi_property_attributes; } napi_property_attributes;
typedef struct { typedef struct {
// One of utf8name or name should be NULL.
const char* utf8name; const char* utf8name;
napi_value name;
napi_callback method; napi_callback method;
napi_callback getter; napi_callback getter;
@ -76,6 +78,7 @@ typedef enum {
napi_invalid_arg, napi_invalid_arg,
napi_object_expected, napi_object_expected,
napi_string_expected, napi_string_expected,
napi_name_expected,
napi_function_expected, napi_function_expected,
napi_number_expected, napi_number_expected,
napi_boolean_expected, napi_boolean_expected,

View File

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

View File

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

View File

@ -1,51 +1,43 @@
#include <node_api.h> #include <node_api.h>
#include "../common.h"
#include <string.h>
#define NAPI_CALL(env, theCall) \ napi_value RunCallback(napi_env env, napi_callback_info info) {
if ((theCall) != napi_ok) { \ size_t argc = 1;
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 args[1]; napi_value args[1];
NAPI_CALL(env, napi_get_cb_args(env, info, args, 1)); NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value cb = args[0];
napi_value argv[1]; 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_value global;
NAPI_CALL(env, napi_get_global(env, &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)); 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_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 cb = args[0];
napi_value recv = args[1]; napi_value recv = args[1];
NAPI_CALL(env, napi_call_function(env, recv, cb, 0, NULL, NULL)); 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) { void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor desc[2] = { napi_property_descriptor desc[2] = {
DECLARE_NAPI_METHOD("RunCallback", RunCallback), DECLARE_NAPI_PROPERTY("RunCallback", RunCallback),
DECLARE_NAPI_METHOD("RunCallbackWithRecv", RunCallbackWithRecv), DECLARE_NAPI_PROPERTY("RunCallbackWithRecv", RunCallbackWithRecv),
}; };
status = napi_define_properties(env, exports, 2, desc); NAPI_CALL_RETURN_VOID(env, napi_define_properties(env, exports, 2, desc));
if (status != napi_ok) return;
} }
NAPI_MODULE(addon, Init) NAPI_MODULE(addon, Init)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,8 +16,8 @@ class MyObject {
~MyObject(); ~MyObject();
static napi_ref constructor; 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);
static void PlusOne(napi_env env, napi_callback_info info); static napi_value PlusOne(napi_env env, napi_callback_info info);
double counter_; double counter_;
napi_env env_; napi_env env_;
napi_ref wrapper_; napi_ref wrapper_;

View File

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

View File

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

View File

@ -17,7 +17,7 @@ class MyObject {
~MyObject(); ~MyObject();
static napi_ref constructor; 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_; double val_;
napi_env env_; napi_env env_;
napi_ref wrapper_; 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 <node_api.h>
#include <string.h> #include <string.h>
#include "../common.h"
void Test(napi_env env, napi_callback_info info) { napi_value Test(napi_env env, napi_callback_info info) {
napi_status status; size_t argc = 2;
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 args[2]; napi_value args[2];
status = napi_get_cb_args(env, info, args, 2); NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
if (status != napi_ok) return;
NAPI_ASSERT(env, argc >= 2, "Wrong number of arguments");
napi_valuetype valuetype0; napi_valuetype valuetype0;
status = napi_typeof(env, args[0], &valuetype0); NAPI_CALL(env, napi_typeof(env, args[0], &valuetype0));
if (status != napi_ok) return;
if (valuetype0 != napi_object) { NAPI_ASSERT(env, valuetype0 == napi_object,
napi_throw_type_error( "Wrong type of arguments. Expects an array as first argument.");
env, "Wrong type of argments. Expects an array as first argument.");
return;
}
napi_valuetype valuetype1; napi_valuetype valuetype1;
status = napi_typeof(env, args[1], &valuetype1); NAPI_CALL(env, napi_typeof(env, args[1], &valuetype1));
if (status != napi_ok) return;
if (valuetype1 != napi_number) { NAPI_ASSERT(env, valuetype1 == napi_number,
napi_throw_type_error( "Wrong type of arguments. Expects an integer as second argument.");
env, "Wrong type of argments. Expects an integer as second argument.");
return;
}
napi_value array = args[0]; napi_value array = args[0];
int index; int32_t index;
status = napi_get_value_int32(env, args[1], &index); NAPI_CALL(env, napi_get_value_int32(env, args[1], &index));
if (status != napi_ok) return;
NAPI_ASSERT(env, index >= 0, "Invalid index. Expects a positive integer.");
bool isarray; bool isarray;
status = napi_is_array(env, array, &isarray); NAPI_CALL(env, napi_is_array(env, array, &isarray));
if (status != napi_ok) return;
if (isarray) { if (!isarray) {
uint32_t size; return NULL;
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;
} }
napi_value args[1]; uint32_t length;
status = napi_get_cb_args(env, info, args, 1); NAPI_CALL(env, napi_get_array_length(env, array, &length));
if (status != napi_ok) return;
napi_valuetype valuetype; if ((uint32_t)index >= length) {
status = napi_typeof(env, args[0], &valuetype); napi_value str;
if (status != napi_ok) return; 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) { return str;
napi_throw_type_error(
env, "Wrong type of argments. Expects an array as first argument.");
return;
} }
napi_value ret; napi_value ret;
status = napi_create_array(env, &ret); NAPI_CALL(env, napi_get_element(env, array, index, &ret));
if (status != napi_ok) return;
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; uint32_t i, length;
status = napi_get_array_length(env, args[0], &length); NAPI_CALL(env, napi_get_array_length(env, args[0], &length));
if (status != napi_ok) return;
for (i = 0; i < length; i++) { for (i = 0; i < length; i++) {
napi_value e; napi_value e;
status = napi_get_element(env, args[0], i, &e); NAPI_CALL(env, napi_get_element(env, args[0], i, &e));
if (status != napi_ok) return; NAPI_CALL(env, napi_set_element(env, ret, i, e));
status = napi_set_element(env, ret, i, e);
if (status != napi_ok) return;
} }
status = napi_set_return_value(env, info, ret); return ret;
if (status != napi_ok) return;
} }
#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) { void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_status status;
napi_property_descriptor descriptors[] = { napi_property_descriptor descriptors[] = {
DECLARE_NAPI_METHOD("Test", Test), DECLARE_NAPI_PROPERTY("Test", Test),
DECLARE_NAPI_METHOD("New", New), DECLARE_NAPI_PROPERTY("New", New),
}; };
status = napi_define_properties( NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors); env, exports, sizeof(descriptors) / sizeof(*descriptors), descriptors));
if (status != napi_ok) return;
} }
NAPI_MODULE(addon, Init) NAPI_MODULE(addon, Init)

View File

@ -1,43 +1,26 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <node_api.h> #include <node_api.h>
#include "../common.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; \
}
static const char theText[] = static const char theText[] =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit."; "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
static int deleterCallCount = 0; static int deleterCallCount = 0;
static void deleteTheText(napi_env env, void* data, void* finalize_hint) { 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; (void)finalize_hint;
free(data); free(data);
deleterCallCount++; deleterCallCount++;
} }
static void noopDeleter(napi_env env, void* data, void* finalize_hint) { 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; (void)finalize_hint;
deleterCallCount++; deleterCallCount++;
} }
void newBuffer(napi_env env, napi_callback_info info) { napi_value newBuffer(napi_env env, napi_callback_info info) {
napi_value theBuffer; napi_value theBuffer;
char* theCopy; char* theCopy;
const unsigned int kBufferSize = sizeof(theText); const unsigned int kBufferSize = sizeof(theText);
@ -48,15 +31,16 @@ void newBuffer(napi_env env, napi_callback_info info) {
sizeof(theText), sizeof(theText),
(void**)(&theCopy), (void**)(&theCopy),
&theBuffer)); &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); 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; napi_value theBuffer;
char* theCopy = strdup(theText); 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_CALL(env,
napi_create_external_buffer( napi_create_external_buffer(
env, env,
@ -65,48 +49,50 @@ void newExternalBuffer(napi_env env, napi_callback_info info) {
deleteTheText, deleteTheText,
NULL, // finalize_hint NULL, // finalize_hint
&theBuffer)); &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_value callCount;
NAPI_CALL(env, napi_create_number(env, deleterCallCount, &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_value theBuffer;
NAPI_CALL(env, napi_create_buffer_copy( NAPI_CALL(env, napi_create_buffer_copy(
env, sizeof(theText), theText, NULL, &theBuffer)); 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) { napi_value bufferHasInstance(napi_env env, napi_callback_info info) {
size_t argc; size_t argc = 1;
NAPI_CALL(env, napi_get_cb_args_length(env, info, &argc)); napi_value args[1];
JS_ASSERT(env, argc == 1, "Wrong number of arguments"); NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value theBuffer; NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
NAPI_CALL(env, napi_get_cb_args(env, info, &theBuffer, 1)); napi_value theBuffer = args[0];
bool hasInstance; bool hasInstance;
napi_valuetype theType; napi_valuetype theType;
NAPI_CALL(env, napi_typeof(env, theBuffer, &theType)); NAPI_CALL(env, napi_typeof(env, theBuffer, &theType));
JS_ASSERT(env, NAPI_ASSERT(env,
theType == napi_object, theType == napi_object,
"bufferHasInstance: instance is not an object"); "bufferHasInstance: instance is not an object");
NAPI_CALL(env, napi_is_buffer(env, theBuffer, &hasInstance)); 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_value returnValue;
NAPI_CALL(env, napi_get_boolean(env, hasInstance, &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) { napi_value bufferInfo(napi_env env, napi_callback_info info) {
size_t argc; size_t argc = 1;
NAPI_CALL(env, napi_get_cb_args_length(env, info, &argc)); napi_value args[1];
JS_ASSERT(env, argc == 1, "Wrong number of arguments"); NAPI_CALL(env, napi_get_cb_info(env, info, &argc, args, NULL, NULL));
napi_value theBuffer, returnValue; NAPI_ASSERT(env, argc == 1, "Wrong number of arguments");
NAPI_CALL(env, napi_get_cb_args(env, info, &theBuffer, 1)); napi_value theBuffer = args[0];
char* bufferData; char *bufferData;
napi_value returnValue;
size_t bufferLength; size_t bufferLength;
NAPI_CALL(env, NAPI_CALL(env,
napi_get_buffer_info( napi_get_buffer_info(
@ -117,10 +103,10 @@ void bufferInfo(napi_env env, napi_callback_info info) {
NAPI_CALL(env, napi_get_boolean(env, NAPI_CALL(env, napi_get_boolean(env,
!strcmp(bufferData, theText) && bufferLength == sizeof(theText), !strcmp(bufferData, theText) && bufferLength == sizeof(theText),
&returnValue)); &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_value theBuffer;
NAPI_CALL( NAPI_CALL(
env, env,
@ -130,31 +116,29 @@ void staticBuffer(napi_env env, napi_callback_info info) {
noopDeleter, noopDeleter,
NULL, // finalize_hint NULL, // finalize_hint
&theBuffer)); &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) { void Init(napi_env env, napi_value exports, napi_value module, void* priv) {
napi_value theValue; napi_value theValue;
NAPI_CALL(env, napi_create_string_utf8(env, NAPI_CALL_RETURN_VOID(env,
theText, sizeof(theText), &theValue)); 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_set_named_property(env, exports, "theText", theValue));
napi_property_descriptor methods[] = { napi_property_descriptor methods[] = {
DECLARE_NAPI_METHOD("newBuffer", newBuffer), DECLARE_NAPI_PROPERTY("newBuffer", newBuffer),
DECLARE_NAPI_METHOD("newExternalBuffer", newExternalBuffer), DECLARE_NAPI_PROPERTY("newExternalBuffer", newExternalBuffer),
DECLARE_NAPI_METHOD("getDeleterCallCount", getDeleterCallCount), DECLARE_NAPI_PROPERTY("getDeleterCallCount", getDeleterCallCount),
DECLARE_NAPI_METHOD("copyBuffer", copyBuffer), DECLARE_NAPI_PROPERTY("copyBuffer", copyBuffer),
DECLARE_NAPI_METHOD("bufferHasInstance", bufferHasInstance), DECLARE_NAPI_PROPERTY("bufferHasInstance", bufferHasInstance),
DECLARE_NAPI_METHOD("bufferInfo", bufferInfo), DECLARE_NAPI_PROPERTY("bufferInfo", bufferInfo),
DECLARE_NAPI_METHOD("staticBuffer", staticBuffer), DECLARE_NAPI_PROPERTY("staticBuffer", staticBuffer),
}; };
NAPI_CALL(env,
napi_define_properties( NAPI_CALL_RETURN_VOID(env, napi_define_properties(
env, exports, sizeof(methods) / sizeof(methods[0]), methods)); env, exports, sizeof(methods) / sizeof(methods[0]), methods));
} }
NAPI_MODULE(addon, Init) NAPI_MODULE(addon, Init)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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