From 5f0c11233f61257dfbf1291473b813a23407264e Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Wed, 29 Mar 2017 01:18:58 +0300 Subject: [PATCH 1/3] napi: create napi_env as a real structure tied to the isolate 1. We define struct napi_env__ to include the isolate, the last exception, and the info about the last error. 2. We instantiate one struct napi_env__ during module registration, but only if there isn't one already attached to the isolate, perhaps from the registration of a pervious module. 3. the last exception and the info about the last error are stored in the napi_env__ struct which is associated with the isolate via v8::Isolate::SetData(). Fixes https://github.com/nodejs/abi-stable-node/issues/198 Closes https://github.com/nodejs/abi-stable-node/pull/206 --- src/node_api.cc | 645 +++++++++--------- src/node_api.h | 3 +- test/addons-napi/3_callbacks/binding.c | 24 +- test/addons-napi/test_buffer/test_buffer.c | 12 +- .../test_conversions/test_conversions.c | 2 +- 5 files changed, 354 insertions(+), 332 deletions(-) diff --git a/src/node_api.cc b/src/node_api.cc index 63d755e614..06db2cb08a 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -8,7 +8,6 @@ * ******************************************************************************/ - #include #include #include @@ -17,16 +16,28 @@ #include #include "node_api.h" +napi_status napi_set_last_error(napi_env env, + napi_status error_code, + uint32_t engine_error_code = 0, + void* engine_reserved = nullptr); +void napi_clear_last_error(napi_env env); + +struct napi_env__ { + v8::Isolate* isolate; + v8::Persistent last_exception; + napi_extended_error_info last_error; +}; + namespace v8impl { //=== Conversion between V8 Isolate and napi_env ========================== napi_env JsEnvFromV8Isolate(v8::Isolate* isolate) { - return reinterpret_cast(isolate); + return static_cast(isolate->GetData(0)); } v8::Isolate* V8IsolateFromJsEnv(napi_env e) { - return reinterpret_cast(e); + return e->isolate; } class HandleScopeWrapper { @@ -252,24 +263,19 @@ class Reference : private Finalizer { class TryCatch : public v8::TryCatch { public: - explicit TryCatch(v8::Isolate* isolate) - : v8::TryCatch(isolate), _isolate(isolate) {} + explicit TryCatch(napi_env env) + : v8::TryCatch(env->isolate), _env(env) {} ~TryCatch() { if (HasCaught()) { - _the_exception.Reset(_isolate, Exception()); + _env->last_exception.Reset(_env->isolate, Exception()); } } - static v8::Persistent& LastException() { return _the_exception; } - private: - static v8::Persistent _the_exception; - v8::Isolate* _isolate; + napi_env _env; }; -v8::Persistent TryCatch::_the_exception; - //=== Function napi_callback wrapper ================================= static const int kDataIndex = 0; @@ -328,12 +334,16 @@ class CallbackWrapperBase : public CallbackWrapper { v8::Local::Cast( _cbdata->GetInternalField(kInternalFieldIndex))->Value()); v8::Isolate* isolate = _cbinfo.GetIsolate(); - cb(v8impl::JsEnvFromV8Isolate(isolate), cbinfo_wrapper); + napi_env env = v8impl::JsEnvFromV8Isolate(isolate); - if (!TryCatch::LastException().IsEmpty()) { + // Make sure any errors encountered last time we were in N-API are gone. + napi_clear_last_error(env); + cb(env, cbinfo_wrapper); + + if (!env->last_exception.IsEmpty()) { isolate->ThrowException( - v8::Local::New(isolate, TryCatch::LastException())); - TryCatch::LastException().Reset(); + v8::Local::New(isolate, env->last_exception)); + env->last_exception.Reset(); } } @@ -515,9 +525,22 @@ void napi_module_register_cb(v8::Local exports, v8::Local module, v8::Local context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); napi_module* mod = static_cast(priv); + + // Can we be absolutely sure that, if isolate->GetData() returns non-NULL, it + // means that the pointer returned is one of ours (i.e. a napi_env)? What if + // some other framework makes use of slot 0? There really seems to be a need + // for a more robust way of assigning arbitrary data to the isolate. + if (isolate->GetData(0) == nullptr) { + napi_env env = new napi_env__; + env->isolate = isolate; + napi_clear_last_error(env); + isolate->SetData(0, env); + } + mod->nm_register_func( - v8impl::JsEnvFromV8Isolate(context->GetIsolate()), + v8impl::JsEnvFromV8Isolate(isolate), v8impl::JsValueFromV8LocalValue(exports), v8impl::JsValueFromV8LocalValue(module), mod->nm_priv); @@ -557,65 +580,63 @@ void napi_module_register(napi_module* mod) { node::node_module_register(nm); } -#define RETURN_STATUS_IF_FALSE(condition, status) \ +#define RETURN_STATUS_IF_FALSE(env, condition, status) \ do { \ if (!(condition)) { \ - return napi_set_last_error((status)); \ + return napi_set_last_error((env), (status)); \ } \ } while (0) -#define CHECK_ARG(arg) RETURN_STATUS_IF_FALSE((arg), napi_invalid_arg) +#define CHECK_ARG(env, arg) \ + RETURN_STATUS_IF_FALSE((env), (arg), napi_invalid_arg) -#define CHECK_MAYBE_EMPTY(maybe, status) \ - RETURN_STATUS_IF_FALSE(!((maybe).IsEmpty()), (status)) +#define CHECK_MAYBE_EMPTY(env, maybe, status) \ + RETURN_STATUS_IF_FALSE((env), !((maybe).IsEmpty()), (status)) -#define CHECK_MAYBE_NOTHING(maybe, status) \ - RETURN_STATUS_IF_FALSE(!((maybe).IsNothing()), (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_ARG(env); \ - RETURN_STATUS_IF_FALSE(v8impl::TryCatch::LastException().IsEmpty(), \ + CHECK_ARG(env, env); \ + RETURN_STATUS_IF_FALSE(env, env->last_exception.IsEmpty(), \ napi_pending_exception); \ - napi_clear_last_error(); \ - v8impl::TryCatch try_catch(v8impl::V8IsolateFromJsEnv((env))) + napi_clear_last_error((env)); \ + v8impl::TryCatch try_catch((env)) -#define CHECK_TO_TYPE(type, context, result, src, status) \ +#define CHECK_TO_TYPE(env, type, context, result, src, status) \ do { \ auto maybe = v8impl::V8LocalValueFromJsValue((src))->To##type((context)); \ - CHECK_MAYBE_EMPTY(maybe, (status)); \ + CHECK_MAYBE_EMPTY(env, maybe, (status)); \ result = maybe.ToLocalChecked(); \ } while (0) -#define CHECK_TO_OBJECT(context, result, src) \ - CHECK_TO_TYPE(Object, context, result, src, napi_object_expected) +#define CHECK_TO_OBJECT(env, context, result, src) \ + CHECK_TO_TYPE(env, Object, context, result, src, napi_object_expected) -#define CHECK_TO_STRING(context, result, src) \ - CHECK_TO_TYPE(String, context, result, src, napi_string_expected) +#define CHECK_TO_STRING(env, context, result, src) \ + CHECK_TO_TYPE(env, String, context, result, src, napi_string_expected) -#define CHECK_TO_NUMBER(context, result, src) \ - CHECK_TO_TYPE(Number, context, result, src, napi_number_expected) +#define CHECK_TO_NUMBER(env, context, result, src) \ + CHECK_TO_TYPE(env, Number, context, result, src, napi_number_expected) -#define CHECK_TO_BOOL(context, result, src) \ - CHECK_TO_TYPE(Boolean, context, result, src, napi_boolean_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(isolate, result, str, len) \ +#define CHECK_NEW_FROM_UTF8_LEN(env, result, str, len) \ do { \ auto str_maybe = v8::String::NewFromUtf8( \ - (isolate), (str), v8::NewStringType::kInternalized, (len)); \ - CHECK_MAYBE_EMPTY(str_maybe, napi_generic_failure); \ + (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(isolate, result, str) \ - CHECK_NEW_FROM_UTF8_LEN((isolate), (result), (str), -1) +#define CHECK_NEW_FROM_UTF8(env, result, str) \ + CHECK_NEW_FROM_UTF8_LEN((env), (result), (str), -1) -#define GET_RETURN_STATUS() \ +#define GET_RETURN_STATUS(env) \ (!try_catch.HasCaught() ? napi_ok \ - : napi_set_last_error(napi_pending_exception)) - -// Static last error returned from napi_get_last_error_info -napi_extended_error_info static_last_error = { nullptr, nullptr, 0, napi_ok }; + : napi_set_last_error((env), napi_pending_exception)) // Warning: Keep in-sync with napi_status enum const char* error_messages[] = {nullptr, @@ -629,33 +650,34 @@ const char* error_messages[] = {nullptr, "Unknown failure", "An exception is pending"}; -void napi_clear_last_error() { - static_last_error.error_code = napi_ok; +void napi_clear_last_error(napi_env env) { + env->last_error.error_code = napi_ok; // TODO(boingoing): Should this be a callback? - static_last_error.engine_error_code = 0; - static_last_error.engine_reserved = nullptr; + env->last_error.engine_error_code = 0; + env->last_error.engine_reserved = nullptr; } -const napi_extended_error_info* napi_get_last_error_info() { +const napi_extended_error_info* napi_get_last_error_info(napi_env env) { static_assert(node::arraysize(error_messages) == napi_status_last, "Count of error messages must match count of error values"); - assert(static_last_error.error_code < napi_status_last); + assert(env->last_error.error_code < napi_status_last); // Wait until someone requests the last error information to fetch the error // message string - static_last_error.error_message = - error_messages[static_last_error.error_code]; + env->last_error.error_message = + error_messages[env->last_error.error_code]; - return &static_last_error; + return &(env->last_error); } -napi_status napi_set_last_error(napi_status error_code, - uint32_t engine_error_code = 0, - void* engine_reserved = nullptr) { - static_last_error.error_code = error_code; - static_last_error.engine_error_code = engine_error_code; - static_last_error.engine_reserved = engine_reserved; +napi_status napi_set_last_error(napi_env env, + napi_status error_code, + uint32_t engine_error_code, + void* engine_reserved) { + env->last_error.error_code = error_code; + env->last_error.engine_error_code = engine_error_code; + env->last_error.engine_reserved = engine_reserved; return error_code; } @@ -666,7 +688,7 @@ napi_status napi_create_function(napi_env env, void* callback_data, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local return_value; @@ -674,26 +696,26 @@ napi_status napi_create_function(napi_env env, v8::Local cbdata = v8impl::CreateFunctionCallbackData(env, cb, callback_data); - RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure); + RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure); v8::Local tpl = v8::FunctionTemplate::New( isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata); v8::Local context = isolate->GetCurrentContext(); v8::MaybeLocal maybe_function = tpl->GetFunction(context); - CHECK_MAYBE_EMPTY(maybe_function, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe_function, napi_generic_failure); return_value = scope.Escape(maybe_function.ToLocalChecked()); if (utf8name != nullptr) { v8::Local name_string; - CHECK_NEW_FROM_UTF8(isolate, name_string, utf8name); + CHECK_NEW_FROM_UTF8(env, name_string, utf8name); return_value->SetName(name_string); } *result = v8impl::JsValueFromV8LocalValue(return_value); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_define_class(napi_env env, @@ -704,7 +726,7 @@ napi_status napi_define_class(napi_env env, const napi_property_descriptor* properties, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -712,7 +734,7 @@ napi_status napi_define_class(napi_env env, v8::Local cbdata = v8impl::CreateFunctionCallbackData(env, constructor, callback_data); - RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure); + RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure); v8::Local tpl = v8::FunctionTemplate::New( isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata); @@ -721,7 +743,7 @@ napi_status napi_define_class(napi_env env, tpl->InstanceTemplate()->SetInternalFieldCount(1); v8::Local name_string; - CHECK_NEW_FROM_UTF8(isolate, name_string, utf8name); + CHECK_NEW_FROM_UTF8(env, name_string, utf8name); tpl->SetClassName(name_string); size_t static_property_count = 0; @@ -735,7 +757,7 @@ napi_status napi_define_class(napi_env env, } v8::Local property_name; - CHECK_NEW_FROM_UTF8(isolate, property_name, p->utf8name); + CHECK_NEW_FROM_UTF8(env, property_name, p->utf8name); v8::PropertyAttribute attributes = static_cast(p->attributes); @@ -746,7 +768,7 @@ napi_status napi_define_class(napi_env env, v8::Local cbdata = v8impl::CreateFunctionCallbackData(env, p->method, p->data); - RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure); + RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure); v8::Local t = v8::FunctionTemplate::New(isolate, @@ -794,7 +816,7 @@ napi_status napi_define_class(napi_env env, if (status != napi_ok) return status; } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_set_return_value(napi_env env, @@ -806,27 +828,27 @@ napi_status napi_set_return_value(napi_env env, reinterpret_cast(cbinfo); info->SetReturnValue(value); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_property_names(napi_env env, napi_value object, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); auto maybe_propertynames = obj->GetPropertyNames(context); - CHECK_MAYBE_EMPTY(maybe_propertynames, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe_propertynames, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue( maybe_propertynames.ToLocalChecked()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_set_property(napi_env env, @@ -839,15 +861,15 @@ napi_status napi_set_property(napi_env env, v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local k = v8impl::V8LocalValueFromJsValue(key); v8::Local val = v8impl::V8LocalValueFromJsValue(value); v8::Maybe set_maybe = obj->Set(context, k, val); - RETURN_STATUS_IF_FALSE(set_maybe.FromMaybe(false), napi_generic_failure); - return GET_RETURN_STATUS(); + RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure); + return GET_RETURN_STATUS(env); } napi_status napi_has_property(napi_env env, @@ -855,21 +877,21 @@ napi_status napi_has_property(napi_env env, napi_value key, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local k = v8impl::V8LocalValueFromJsValue(key); v8::Maybe has_maybe = obj->Has(context, k); - CHECK_MAYBE_NOTHING(has_maybe, napi_generic_failure); + CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure); *result = has_maybe.FromMaybe(false); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_property(napi_env env, @@ -877,22 +899,22 @@ napi_status napi_get_property(napi_env env, napi_value key, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local k = v8impl::V8LocalValueFromJsValue(key); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); auto get_maybe = obj->Get(context, k); - CHECK_MAYBE_EMPTY(get_maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure); v8::Local val = get_maybe.ToLocalChecked(); *result = v8impl::JsValueFromV8LocalValue(val); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_set_named_property(napi_env env, @@ -905,17 +927,17 @@ napi_status napi_set_named_property(napi_env env, v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local key; - CHECK_NEW_FROM_UTF8(isolate, key, utf8name); + CHECK_NEW_FROM_UTF8(env, key, utf8name); v8::Local val = v8impl::V8LocalValueFromJsValue(value); v8::Maybe set_maybe = obj->Set(context, key, val); - RETURN_STATUS_IF_FALSE(set_maybe.FromMaybe(false), napi_generic_failure); - return GET_RETURN_STATUS(); + RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure); + return GET_RETURN_STATUS(env); } napi_status napi_has_named_property(napi_env env, @@ -923,23 +945,23 @@ napi_status napi_has_named_property(napi_env env, const char* utf8name, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local key; - CHECK_NEW_FROM_UTF8(isolate, key, utf8name); + CHECK_NEW_FROM_UTF8(env, key, utf8name); v8::Maybe has_maybe = obj->Has(context, key); - CHECK_MAYBE_NOTHING(has_maybe, napi_generic_failure); + CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure); *result = has_maybe.FromMaybe(false); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_named_property(napi_env env, @@ -947,25 +969,25 @@ napi_status napi_get_named_property(napi_env env, const char* utf8name, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local key; - CHECK_NEW_FROM_UTF8(isolate, key, utf8name); + CHECK_NEW_FROM_UTF8(env, key, utf8name); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); auto get_maybe = obj->Get(context, key); - CHECK_MAYBE_EMPTY(get_maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure); v8::Local val = get_maybe.ToLocalChecked(); *result = v8impl::JsValueFromV8LocalValue(val); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_set_element(napi_env env, @@ -978,14 +1000,14 @@ napi_status napi_set_element(napi_env env, v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local val = v8impl::V8LocalValueFromJsValue(value); auto set_maybe = obj->Set(context, index, val); - RETURN_STATUS_IF_FALSE(set_maybe.FromMaybe(false), napi_generic_failure); + RETURN_STATUS_IF_FALSE(env, set_maybe.FromMaybe(false), napi_generic_failure); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_has_element(napi_env env, @@ -993,20 +1015,20 @@ napi_status napi_has_element(napi_env env, uint32_t index, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Maybe has_maybe = obj->Has(context, index); - CHECK_MAYBE_NOTHING(has_maybe, napi_generic_failure); + CHECK_MAYBE_NOTHING(env, has_maybe, napi_generic_failure); *result = has_maybe.FromMaybe(false); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_element(napi_env env, @@ -1014,20 +1036,20 @@ napi_status napi_get_element(napi_env env, uint32_t index, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); auto get_maybe = obj->Get(context, index); - CHECK_MAYBE_EMPTY(get_maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, get_maybe, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue(get_maybe.ToLocalChecked()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_define_properties(napi_env env, @@ -1045,7 +1067,7 @@ napi_status napi_define_properties(napi_env env, const napi_property_descriptor* p = &properties[i]; v8::Local name; - CHECK_NEW_FROM_UTF8(isolate, name, p->utf8name); + CHECK_NEW_FROM_UTF8(env, name, p->utf8name); v8::PropertyAttribute attributes = static_cast( p->attributes & ~napi_static_property); @@ -1054,7 +1076,7 @@ napi_status napi_define_properties(napi_env env, v8::Local cbdata = v8impl::CreateFunctionCallbackData(env, p->method, p->data); - RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure); + RETURN_STATUS_IF_FALSE(env, !cbdata.IsEmpty(), napi_generic_failure); v8::Local t = v8::FunctionTemplate::New( isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata); @@ -1063,7 +1085,7 @@ napi_status napi_define_properties(napi_env env, obj->DefineOwnProperty(context, name, t->GetFunction(), attributes); if (!define_maybe.FromMaybe(false)) { - return napi_set_last_error(napi_generic_failure); + return napi_set_last_error(env, napi_generic_failure); } } else if (p->getter || p->setter) { v8::Local cbdata = v8impl::CreateAccessorCallbackData( @@ -1082,7 +1104,7 @@ napi_status napi_define_properties(napi_env env, attributes); if (!set_maybe.FromMaybe(false)) { - return napi_set_last_error(napi_invalid_arg); + return napi_set_last_error(env, napi_invalid_arg); } } else { v8::Local value = v8impl::V8LocalValueFromJsValue(p->value); @@ -1091,37 +1113,37 @@ napi_status napi_define_properties(napi_env env, obj->DefineOwnProperty(context, name, value, attributes); if (!define_maybe.FromMaybe(false)) { - return napi_set_last_error(napi_invalid_arg); + return napi_set_last_error(env, napi_invalid_arg); } } } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_is_array(napi_env env, napi_value value, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); *result = val->IsArray(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_array_length(napi_env env, napi_value value, uint32_t* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsArray(), napi_array_expected); + RETURN_STATUS_IF_FALSE(env, val->IsArray(), napi_array_expected); v8::Local arr = val.As(); *result = arr->Length(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_strict_equals(napi_env env, @@ -1129,62 +1151,62 @@ napi_status napi_strict_equals(napi_env env, napi_value rhs, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local a = v8impl::V8LocalValueFromJsValue(lhs); v8::Local b = v8impl::V8LocalValueFromJsValue(rhs); *result = a->StrictEquals(b); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_prototype(napi_env env, napi_value object, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, object); + CHECK_TO_OBJECT(env, context, obj, object); v8::Local val = obj->GetPrototype(); *result = v8impl::JsValueFromV8LocalValue(val); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_object(napi_env env, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Object::New(v8impl::V8IsolateFromJsEnv(env))); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_array(napi_env env, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Array::New(v8impl::V8IsolateFromJsEnv(env))); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_array_with_length(napi_env env, size_t length, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Array::New(v8impl::V8IsolateFromJsEnv(env), length)); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_string_utf8(napi_env env, @@ -1192,14 +1214,13 @@ napi_status napi_create_string_utf8(napi_env env, size_t length, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); - auto isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local s; - CHECK_NEW_FROM_UTF8_LEN(isolate, s, str, length); + CHECK_NEW_FROM_UTF8_LEN(env, s, str, length); *result = v8impl::JsValueFromV8LocalValue(s); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_string_utf16(napi_env env, @@ -1207,7 +1228,7 @@ napi_status napi_create_string_utf16(napi_env env, size_t length, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); auto isolate = v8impl::V8IsolateFromJsEnv(env); auto str_maybe = @@ -1215,27 +1236,27 @@ napi_status napi_create_string_utf16(napi_env env, reinterpret_cast(str), v8::NewStringType::kInternalized, length); - CHECK_MAYBE_EMPTY(str_maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, str_maybe, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue(str_maybe.ToLocalChecked()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_number(napi_env env, double value, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Number::New(v8impl::V8IsolateFromJsEnv(env), value)); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_boolean(napi_env env, bool value, napi_value* result) { - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -1252,7 +1273,7 @@ napi_status napi_create_symbol(napi_env env, napi_value description, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -1260,58 +1281,58 @@ napi_status napi_create_symbol(napi_env env, *result = v8impl::JsValueFromV8LocalValue(v8::Symbol::New(isolate)); } else { v8::Local desc = v8impl::V8LocalValueFromJsValue(description); - RETURN_STATUS_IF_FALSE(desc->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, desc->IsString(), napi_string_expected); *result = v8impl::JsValueFromV8LocalValue( v8::Symbol::New(isolate, desc.As())); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_error(napi_env env, napi_value msg, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local message_value = v8impl::V8LocalValueFromJsValue(msg); - RETURN_STATUS_IF_FALSE(message_value->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected); *result = v8impl::JsValueFromV8LocalValue(v8::Exception::Error( message_value.As())); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_type_error(napi_env env, napi_value msg, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local message_value = v8impl::V8LocalValueFromJsValue(msg); - RETURN_STATUS_IF_FALSE(message_value->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected); *result = v8impl::JsValueFromV8LocalValue(v8::Exception::TypeError( message_value.As())); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_range_error(napi_env env, napi_value msg, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local message_value = v8impl::V8LocalValueFromJsValue(msg); - RETURN_STATUS_IF_FALSE(message_value->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected); *result = v8impl::JsValueFromV8LocalValue(v8::Exception::RangeError( message_value.As())); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_typeof(napi_env env, @@ -1319,7 +1340,7 @@ napi_status napi_typeof(napi_env env, napi_valuetype* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local v = v8impl::V8LocalValueFromJsValue(value); @@ -1345,15 +1366,15 @@ napi_status napi_typeof(napi_env env, *result = napi_external; } else { // Should not get here unless V8 has added some new kind of value. - return napi_set_last_error(napi_invalid_arg); + return napi_set_last_error(env, napi_invalid_arg); } return napi_ok; } napi_status napi_get_undefined(napi_env env, napi_value* result) { - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Undefined(v8impl::V8IsolateFromJsEnv(env))); @@ -1362,8 +1383,8 @@ napi_status napi_get_undefined(napi_env env, napi_value* result) { } napi_status napi_get_null(napi_env env, napi_value* result) { - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); *result = v8impl::JsValueFromV8LocalValue( v8::Null(v8impl::V8IsolateFromJsEnv(env))); @@ -1380,10 +1401,10 @@ napi_status napi_get_cb_info( napi_value* argv, // [out] Array of values napi_value* this_arg, // [out] Receives the JS 'this' arg for the call void** data) { // [out] Receives the data pointer for the callback. - CHECK_ARG(argc); - CHECK_ARG(argv); - CHECK_ARG(this_arg); - CHECK_ARG(data); + CHECK_ARG(env, argc); + CHECK_ARG(env, argv); + CHECK_ARG(env, this_arg); + CHECK_ARG(env, data); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1400,7 +1421,7 @@ 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_ARG(result); + CHECK_ARG(env, result); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1413,7 +1434,7 @@ napi_status napi_is_construct_call(napi_env env, napi_callback_info cbinfo, bool* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called. - CHECK_ARG(result); + CHECK_ARG(env, result); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1429,7 +1450,7 @@ napi_status napi_get_cb_args(napi_env env, napi_value* buf, size_t bufsize) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called. - CHECK_ARG(buf); + CHECK_ARG(env, buf); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1442,7 +1463,7 @@ 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_ARG(result); + CHECK_ARG(env, result); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1455,7 +1476,7 @@ 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_ARG(result); + CHECK_ARG(env, result); v8impl::CallbackWrapper* info = reinterpret_cast(cbinfo); @@ -1478,17 +1499,17 @@ napi_status napi_call_function(napi_env env, v8::Local v8recv = v8impl::V8LocalValueFromJsValue(recv); v8::Local v8value = v8impl::V8LocalValueFromJsValue(func); - RETURN_STATUS_IF_FALSE(v8value->IsFunction(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, v8value->IsFunction(), napi_invalid_arg); v8::Local v8func = v8value.As(); auto maybe = v8func->Call(context, v8recv, argc, reinterpret_cast*>(const_cast(argv))); if (try_catch.HasCaught()) { - return napi_set_last_error(napi_pending_exception); + return napi_set_last_error(env, napi_pending_exception); } else { if (result != nullptr) { - CHECK_MAYBE_EMPTY(maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked()); } return napi_ok; @@ -1496,8 +1517,8 @@ napi_status napi_call_function(napi_env env, } napi_status napi_get_global(napi_env env, napi_value* result) { - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); // TODO(ianhall): what if we need the global object from a different @@ -1525,7 +1546,7 @@ napi_status napi_throw_error(napi_env env, const char* msg) { v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local str; - CHECK_NEW_FROM_UTF8(isolate, str, msg); + CHECK_NEW_FROM_UTF8(env, str, msg); isolate->ThrowException(v8::Exception::Error(str)); // any VM calls after this point and before returning @@ -1538,7 +1559,7 @@ napi_status napi_throw_type_error(napi_env env, const char* msg) { v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local str; - CHECK_NEW_FROM_UTF8(isolate, str, msg); + CHECK_NEW_FROM_UTF8(env, str, msg); isolate->ThrowException(v8::Exception::TypeError(str)); // any VM calls after this point and before returning @@ -1551,7 +1572,7 @@ napi_status napi_throw_range_error(napi_env env, const char* msg) { v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local str; - CHECK_NEW_FROM_UTF8(isolate, str, msg); + CHECK_NEW_FROM_UTF8(env, str, msg); isolate->ThrowException(v8::Exception::RangeError(str)); // any VM calls after this point and before returning @@ -1562,7 +1583,7 @@ napi_status napi_throw_range_error(napi_env env, const char* msg) { napi_status napi_is_error(napi_env env, napi_value value, bool* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot // throw JS exceptions. - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); *result = val->IsNativeError(); @@ -1575,12 +1596,12 @@ napi_status napi_get_value_double(napi_env env, double* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(env); - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsNumber(), napi_number_expected); + RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected); *result = val.As()->Value(); @@ -1592,12 +1613,12 @@ napi_status napi_get_value_int32(napi_env env, int32_t* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(env); - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsNumber(), napi_number_expected); + RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); @@ -1611,12 +1632,12 @@ napi_status napi_get_value_uint32(napi_env env, uint32_t* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(env); - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsNumber(), napi_number_expected); + RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); @@ -1630,12 +1651,12 @@ napi_status napi_get_value_int64(napi_env env, int64_t* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(env); - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsNumber(), napi_number_expected); + RETURN_STATUS_IF_FALSE(env, val->IsNumber(), napi_number_expected); // v8::Value::IntegerValue() converts NaN to INT64_MIN, inconsistent with // v8::Value::Int32Value() that converts NaN to 0. So special-case NaN here. @@ -1654,11 +1675,11 @@ napi_status napi_get_value_int64(napi_env env, napi_status napi_get_value_bool(napi_env env, napi_value value, bool* result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsBoolean(), napi_boolean_expected); + RETURN_STATUS_IF_FALSE(env, val->IsBoolean(), napi_boolean_expected); *result = val.As()->Value(); @@ -1670,14 +1691,14 @@ napi_status napi_get_value_string_length(napi_env env, napi_value value, size_t* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected); *result = val.As()->Length(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Copies a JavaScript string into a UTF-8 string buffer. The result is the @@ -1694,10 +1715,10 @@ napi_status napi_get_value_string_utf8(napi_env env, NAPI_PREAMBLE(env); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected); if (!buf) { - CHECK_ARG(result); + CHECK_ARG(env, result); *result = val.As()->Utf8Length(); } else { int copied = val.As()->WriteUtf8( @@ -1708,7 +1729,7 @@ napi_status napi_get_value_string_utf8(napi_env env, } } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Copies a JavaScript string into a UTF-16 string buffer. The result is the @@ -1725,10 +1746,10 @@ napi_status napi_get_value_string_utf16(napi_env env, NAPI_PREAMBLE(env); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsString(), napi_string_expected); + RETURN_STATUS_IF_FALSE(env, val->IsString(), napi_string_expected); if (!buf) { - CHECK_ARG(result); + CHECK_ARG(env, result); // V8 assumes UTF-16 length is the same as the number of characters. *result = val.As()->Length(); } else { @@ -1740,70 +1761,70 @@ napi_status napi_get_value_string_utf16(napi_env env, } } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_coerce_to_object(napi_env env, napi_value value, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local obj; - CHECK_TO_OBJECT(context, obj, value); + CHECK_TO_OBJECT(env, context, obj, value); *result = v8impl::JsValueFromV8LocalValue(obj); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_coerce_to_bool(napi_env env, napi_value value, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local b; - CHECK_TO_BOOL(context, b, value); + CHECK_TO_BOOL(env, context, b, value); *result = v8impl::JsValueFromV8LocalValue(b); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_coerce_to_number(napi_env env, napi_value value, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local num; - CHECK_TO_NUMBER(context, num, value); + CHECK_TO_NUMBER(env, context, num, value); *result = v8impl::JsValueFromV8LocalValue(num); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_coerce_to_string(napi_env env, napi_value value, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local str; - CHECK_TO_STRING(context, str, value); + CHECK_TO_STRING(env, context, str, value); *result = v8impl::JsValueFromV8LocalValue(str); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_wrap(napi_env env, @@ -1813,7 +1834,7 @@ napi_status napi_wrap(napi_env env, void* finalize_hint, napi_ref* result) { NAPI_PREAMBLE(env); - CHECK_ARG(js_object); + CHECK_ARG(env, js_object); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local obj = @@ -1821,7 +1842,7 @@ napi_status napi_wrap(napi_env env, // Only objects that were created from a NAPI constructor's prototype // via napi_define_class() can be (un)wrapped. - RETURN_STATUS_IF_FALSE(obj->InternalFieldCount() > 0, napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, obj->InternalFieldCount() > 0, napi_invalid_arg); obj->SetInternalField(0, v8::External::New(isolate, native_object)); @@ -1830,7 +1851,7 @@ napi_status napi_wrap(napi_env env, // ONLY in response to the finalize callback invocation. (If it is deleted // before then, then the finalize callback will never be invoked.) // Therefore a finalize callback is required when returning a reference. - CHECK_ARG(finalize_cb); + CHECK_ARG(env, finalize_cb); v8impl::Reference* reference = v8impl::Reference::New( isolate, obj, 0, false, finalize_cb, native_object, finalize_hint); *result = reinterpret_cast(reference); @@ -1840,22 +1861,22 @@ napi_status napi_wrap(napi_env env, isolate, obj, 0, true, finalize_cb, native_object, finalize_hint); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_unwrap(napi_env env, napi_value js_object, void** result) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(js_object); - CHECK_ARG(result); + CHECK_ARG(env, js_object); + CHECK_ARG(env, result); v8::Local value = v8impl::V8LocalValueFromJsValue(js_object); - RETURN_STATUS_IF_FALSE(value->IsObject(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, value->IsObject(), napi_invalid_arg); v8::Local obj = value.As(); // Only objects that were created from a NAPI constructor's prototype // via napi_define_class() can be (un)wrapped. - RETURN_STATUS_IF_FALSE(obj->InternalFieldCount() > 0, napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, obj->InternalFieldCount() > 0, napi_invalid_arg); *result = v8::Local::Cast(obj->GetInternalField(0))->Value(); @@ -1868,7 +1889,7 @@ napi_status napi_create_external(napi_env env, void* finalize_hint, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -1886,23 +1907,23 @@ napi_status napi_create_external(napi_env env, *result = v8impl::JsValueFromV8LocalValue(external_value); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_value_external(napi_env env, napi_value value, void** result) { NAPI_PREAMBLE(env); - CHECK_ARG(value); - CHECK_ARG(result); + CHECK_ARG(env, value); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); - RETURN_STATUS_IF_FALSE(val->IsExternal(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, val->IsExternal(), napi_invalid_arg); v8::Local external_value = val.As(); *result = external_value->Value(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Set initial_refcount to 0 for a weak reference, >0 for a strong reference. @@ -1911,7 +1932,7 @@ napi_status napi_create_reference(napi_env env, uint32_t initial_refcount, napi_ref* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -1919,7 +1940,7 @@ napi_status napi_create_reference(napi_env env, isolate, v8impl::V8LocalValueFromJsValue(value), initial_refcount, false); *result = reinterpret_cast(reference); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Deletes a reference. The referenced value is released, and may be GC'd unless @@ -1927,7 +1948,7 @@ napi_status napi_create_reference(napi_env env, napi_status napi_delete_reference(napi_env env, napi_ref ref) { // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because V8 calls here cannot throw // JS exceptions. - CHECK_ARG(ref); + CHECK_ARG(env, ref); v8impl::Reference::Delete(reinterpret_cast(ref)); @@ -1941,7 +1962,7 @@ napi_status napi_delete_reference(napi_env env, napi_ref ref) { // results in an error. napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { NAPI_PREAMBLE(env); - CHECK_ARG(ref); + CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast(ref); uint32_t count = reference->Ref(); @@ -1950,7 +1971,7 @@ napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { *result = count; } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Decrements the reference count, optionally returning the resulting count. If @@ -1959,12 +1980,12 @@ napi_status napi_reference_ref(napi_env env, napi_ref ref, uint32_t* result) { // already 0 results in an error. napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { NAPI_PREAMBLE(env); - CHECK_ARG(ref); + CHECK_ARG(env, ref); v8impl::Reference* reference = reinterpret_cast(ref); if (reference->RefCount() == 0) { - return napi_set_last_error(napi_generic_failure); + return napi_set_last_error(env, napi_generic_failure); } uint32_t count = reference->Unref(); @@ -1973,7 +1994,7 @@ napi_status napi_reference_unref(napi_env env, napi_ref ref, uint32_t* result) { *result = count; } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Attempts to get a referenced value. If the reference is weak, the value might @@ -1983,51 +2004,51 @@ napi_status napi_get_reference_value(napi_env env, napi_ref ref, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(ref); - CHECK_ARG(result); + CHECK_ARG(env, ref); + CHECK_ARG(env, result); v8impl::Reference* reference = reinterpret_cast(ref); *result = v8impl::JsValueFromV8LocalValue(reference->Get()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_open_handle_scope(napi_env env, napi_handle_scope* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsHandleScopeFromV8HandleScope( new v8impl::HandleScopeWrapper(v8impl::V8IsolateFromJsEnv(env))); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_close_handle_scope(napi_env env, napi_handle_scope scope) { NAPI_PREAMBLE(env); - CHECK_ARG(scope); + CHECK_ARG(env, scope); delete v8impl::V8HandleScopeFromJsHandleScope(scope); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_open_escapable_handle_scope( napi_env env, napi_escapable_handle_scope* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = v8impl::JsEscapableHandleScopeFromV8EscapableHandleScope( new v8impl::EscapableHandleScopeWrapper(v8impl::V8IsolateFromJsEnv(env))); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_close_escapable_handle_scope( napi_env env, napi_escapable_handle_scope scope) { NAPI_PREAMBLE(env); - CHECK_ARG(scope); + CHECK_ARG(env, scope); delete v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_escape_handle(napi_env env, @@ -2035,14 +2056,14 @@ napi_status napi_escape_handle(napi_env env, napi_value escapee, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(scope); - CHECK_ARG(result); + CHECK_ARG(env, scope); + CHECK_ARG(env, result); v8impl::EscapableHandleScopeWrapper* s = v8impl::V8EscapableHandleScopeFromJsEscapableHandleScope(scope); *result = v8impl::JsValueFromV8LocalValue( s->Escape(v8impl::V8LocalValueFromJsValue(escapee))); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_new_instance(napi_env env, @@ -2051,23 +2072,23 @@ napi_status napi_new_instance(napi_env env, const napi_value* argv, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); v8::Local v8value = v8impl::V8LocalValueFromJsValue(constructor); - RETURN_STATUS_IF_FALSE(v8value->IsFunction(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, v8value->IsFunction(), napi_invalid_arg); v8::Local ctor = v8value.As(); auto maybe = ctor->NewInstance(context, argc, reinterpret_cast*>(const_cast(argv))); - CHECK_MAYBE_EMPTY(maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_instanceof(napi_env env, @@ -2075,7 +2096,7 @@ napi_status napi_instanceof(napi_env env, napi_value constructor, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = false; @@ -2083,12 +2104,12 @@ napi_status napi_instanceof(napi_env env, v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local context = isolate->GetCurrentContext(); - CHECK_TO_OBJECT(context, ctor, constructor); + CHECK_TO_OBJECT(env, context, ctor, constructor); if (!ctor->IsFunction()) { napi_throw_type_error(env, "constructor must be a function"); - return napi_set_last_error(napi_function_expected); + return napi_set_last_error(env, napi_function_expected); } napi_value value, js_result; @@ -2132,20 +2153,20 @@ napi_status napi_instanceof(napi_env env, // a traditional instanceof (early Node.js 6.x). v8::Local prototype_string; - CHECK_NEW_FROM_UTF8(isolate, prototype_string, "prototype"); + CHECK_NEW_FROM_UTF8(env, prototype_string, "prototype"); auto maybe_prototype = ctor->Get(context, prototype_string); - CHECK_MAYBE_EMPTY(maybe_prototype, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe_prototype, napi_generic_failure); v8::Local prototype_property = maybe_prototype.ToLocalChecked(); if (!prototype_property->IsObject()) { napi_throw_type_error(env, "constructor.prototype must be an object"); - return napi_set_last_error(napi_object_expected); + return napi_set_last_error(env, napi_object_expected); } auto maybe_ctor = prototype_property->ToObject(context); - CHECK_MAYBE_EMPTY(maybe_ctor, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe_ctor, napi_generic_failure); ctor = maybe_ctor.ToLocalChecked(); v8::Local current_obj = v8impl::V8LocalValueFromJsValue(object); @@ -2159,13 +2180,13 @@ napi_status napi_instanceof(napi_env env, break; } v8::Local obj; - CHECK_TO_OBJECT(context, obj, v8impl::JsValueFromV8LocalValue( + CHECK_TO_OBJECT(env, context, obj, v8impl::JsValueFromV8LocalValue( current_obj)); current_obj = obj->GetPrototype(); } } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_make_callback(napi_env env, @@ -2190,17 +2211,17 @@ napi_status napi_make_callback(napi_env env, *result = v8impl::JsValueFromV8LocalValue(callback_result); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } // Methods to support catching exceptions napi_status napi_is_exception_pending(napi_env env, bool* result) { // NAPI_PREAMBLE is not used here: this function must execute when there is a // pending exception. - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); - *result = !v8impl::TryCatch::LastException().IsEmpty(); + *result = !env->last_exception.IsEmpty(); return napi_ok; } @@ -2208,17 +2229,17 @@ napi_status napi_get_and_clear_last_exception(napi_env env, napi_value* result) { // NAPI_PREAMBLE is not used here: this function must execute when there is a // pending exception. - CHECK_ARG(env); - CHECK_ARG(result); + CHECK_ARG(env, env); + CHECK_ARG(env, result); // TODO(boingoing): Is there a chance that an exception will be thrown in // the process of attempting to retrieve the global static exception? - if (v8impl::TryCatch::LastException().IsEmpty()) { + if (env->last_exception.IsEmpty()) { return napi_get_undefined(env, result); } else { - *result = v8impl::JsValueFromV8LocalValue(v8::Local::New( - v8impl::V8IsolateFromJsEnv(env), v8impl::TryCatch::LastException())); - v8impl::TryCatch::LastException().Reset(); + *result = v8impl::JsValueFromV8LocalValue( + v8::Local::New(env->isolate, env->last_exception)); + env->last_exception.Reset(); } return napi_ok; @@ -2229,19 +2250,19 @@ napi_status napi_create_buffer(napi_env env, void** data, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(data); - CHECK_ARG(result); + CHECK_ARG(env, data); + CHECK_ARG(env, result); auto maybe = node::Buffer::New(v8impl::V8IsolateFromJsEnv(env), length); - CHECK_MAYBE_EMPTY(maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); v8::Local buffer = maybe.ToLocalChecked(); *result = v8impl::JsValueFromV8LocalValue(buffer); *data = node::Buffer::Data(buffer); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_external_buffer(napi_env env, @@ -2251,7 +2272,7 @@ napi_status napi_create_external_buffer(napi_env env, void* finalize_hint, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); @@ -2265,10 +2286,10 @@ napi_status napi_create_external_buffer(napi_env env, v8impl::Finalizer::FinalizeBufferCallback, finalizer); - CHECK_MAYBE_EMPTY(maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); *result = v8impl::JsValueFromV8LocalValue(maybe.ToLocalChecked()); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_buffer_copy(napi_env env, @@ -2277,12 +2298,12 @@ napi_status napi_create_buffer_copy(napi_env env, void** result_data, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); auto maybe = node::Buffer::Copy(v8impl::V8IsolateFromJsEnv(env), static_cast(data), length); - CHECK_MAYBE_EMPTY(maybe, napi_generic_failure); + CHECK_MAYBE_EMPTY(env, maybe, napi_generic_failure); v8::Local buffer = maybe.ToLocalChecked(); *result = v8impl::JsValueFromV8LocalValue(buffer); @@ -2291,15 +2312,15 @@ napi_status napi_create_buffer_copy(napi_env env, *result_data = node::Buffer::Data(buffer); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_is_buffer(napi_env env, napi_value value, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); *result = node::Buffer::HasInstance(v8impl::V8LocalValueFromJsValue(value)); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_buffer_info(napi_env env, @@ -2318,17 +2339,17 @@ napi_status napi_get_buffer_info(napi_env env, *length = node::Buffer::Length(buffer); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_is_arraybuffer(napi_env env, napi_value value, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); *result = val->IsArrayBuffer(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_arraybuffer(napi_env env, @@ -2336,7 +2357,7 @@ napi_status napi_create_arraybuffer(napi_env env, void** data, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local buffer = @@ -2349,7 +2370,7 @@ napi_status napi_create_arraybuffer(napi_env env, } *result = v8impl::JsValueFromV8LocalValue(buffer); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_external_arraybuffer(napi_env env, @@ -2359,7 +2380,7 @@ napi_status napi_create_external_arraybuffer(napi_env env, void* finalize_hint, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Isolate* isolate = v8impl::V8IsolateFromJsEnv(env); v8::Local buffer = @@ -2378,7 +2399,7 @@ napi_status napi_create_external_arraybuffer(napi_env env, } *result = v8impl::JsValueFromV8LocalValue(buffer); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_arraybuffer_info(napi_env env, @@ -2388,7 +2409,7 @@ napi_status napi_get_arraybuffer_info(napi_env env, NAPI_PREAMBLE(env); v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); - RETURN_STATUS_IF_FALSE(value->IsArrayBuffer(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg); v8::ArrayBuffer::Contents contents = value.As()->GetContents(); @@ -2401,17 +2422,17 @@ napi_status napi_get_arraybuffer_info(napi_env env, *byte_length = contents.ByteLength(); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_is_typedarray(napi_env env, napi_value value, bool* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local val = v8impl::V8LocalValueFromJsValue(value); *result = val->IsTypedArray(); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_create_typedarray(napi_env env, @@ -2421,10 +2442,10 @@ napi_status napi_create_typedarray(napi_env env, size_t byte_offset, napi_value* result) { NAPI_PREAMBLE(env); - CHECK_ARG(result); + CHECK_ARG(env, result); v8::Local value = v8impl::V8LocalValueFromJsValue(arraybuffer); - RETURN_STATUS_IF_FALSE(value->IsArrayBuffer(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, value->IsArrayBuffer(), napi_invalid_arg); v8::Local buffer = value.As(); v8::Local typedArray; @@ -2458,11 +2479,11 @@ napi_status napi_create_typedarray(napi_env env, typedArray = v8::Float64Array::New(buffer, byte_offset, length); break; default: - return napi_set_last_error(napi_invalid_arg); + return napi_set_last_error(env, napi_invalid_arg); } *result = v8impl::JsValueFromV8LocalValue(typedArray); - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } napi_status napi_get_typedarray_info(napi_env env, @@ -2475,7 +2496,7 @@ napi_status napi_get_typedarray_info(napi_env env, NAPI_PREAMBLE(env); v8::Local value = v8impl::V8LocalValueFromJsValue(typedarray); - RETURN_STATUS_IF_FALSE(value->IsTypedArray(), napi_invalid_arg); + RETURN_STATUS_IF_FALSE(env, value->IsTypedArray(), napi_invalid_arg); v8::Local array = value.As(); @@ -2519,5 +2540,5 @@ napi_status napi_get_typedarray_info(napi_env env, *byte_offset = array->ByteOffset(); } - return GET_RETURN_STATUS(); + return GET_RETURN_STATUS(env); } diff --git a/src/node_api.h b/src/node_api.h index 61372322a9..1e9b7f21f6 100644 --- a/src/node_api.h +++ b/src/node_api.h @@ -100,7 +100,8 @@ EXTERN_C_START NAPI_EXTERN void napi_module_register(napi_module* mod); -NAPI_EXTERN const napi_extended_error_info* napi_get_last_error_info(); +NAPI_EXTERN const napi_extended_error_info* napi_get_last_error_info( + napi_env env); // Getters for defined singletons NAPI_EXTERN napi_status napi_get_undefined(napi_env env, napi_value* result); diff --git a/test/addons-napi/3_callbacks/binding.c b/test/addons-napi/3_callbacks/binding.c index 7e2750a2a9..77da3e343b 100644 --- a/test/addons-napi/3_callbacks/binding.c +++ b/test/addons-napi/3_callbacks/binding.c @@ -1,36 +1,36 @@ #include -#define NAPI_CALL(theCall) \ - if (theCall != napi_ok) { \ - const char* errorMessage = napi_get_last_error_info()->error_message; \ - errorMessage = errorMessage ? errorMessage : "empty error message"; \ - napi_throw_error((env), errorMessage); \ - return; \ +#define NAPI_CALL(env, theCall) \ + if (theCall != napi_ok) { \ + const char* errorMessage = napi_get_last_error_info((env))->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_CALL(napi_get_cb_args(env, info, args, 1)); + NAPI_CALL(env, napi_get_cb_args(env, info, args, 1)); napi_value cb = args[0]; napi_value argv[1]; - NAPI_CALL(napi_create_string_utf8(env, "hello world", -1, argv)); + NAPI_CALL(env, napi_create_string_utf8(env, "hello world", -1, argv)); napi_value global; - NAPI_CALL(napi_get_global(env, &global)); + NAPI_CALL(env, napi_get_global(env, &global)); - NAPI_CALL(napi_call_function(env, global, cb, 1, argv, NULL)); + NAPI_CALL(env, napi_call_function(env, global, cb, 1, argv, NULL)); } void RunCallbackWithRecv(napi_env env, napi_callback_info info) { napi_value args[2]; - NAPI_CALL(napi_get_cb_args(env, info, args, 2)); + NAPI_CALL(env, napi_get_cb_args(env, info, args, 2)); napi_value cb = args[0]; napi_value recv = args[1]; - NAPI_CALL(napi_call_function(env, recv, cb, 0, NULL, NULL)); + NAPI_CALL(env, napi_call_function(env, recv, cb, 0, NULL, NULL)); } #define DECLARE_NAPI_METHOD(name, func) \ diff --git a/test/addons-napi/test_buffer/test_buffer.c b/test/addons-napi/test_buffer/test_buffer.c index d99ab45c42..76a57b2f3a 100644 --- a/test/addons-napi/test_buffer/test_buffer.c +++ b/test/addons-napi/test_buffer/test_buffer.c @@ -10,12 +10,12 @@ return; \ } -#define NAPI_CALL(env, theCall) \ - if (theCall != napi_ok) { \ - const char* errorMessage = napi_get_last_error_info()->error_message; \ - errorMessage = errorMessage ? errorMessage : "empty error message"; \ - napi_throw_error((env), errorMessage); \ - return; \ +#define NAPI_CALL(env, theCall) \ + if (theCall != napi_ok) { \ + const char* errorMessage = napi_get_last_error_info((env))->error_message; \ + errorMessage = errorMessage ? errorMessage : "empty error message"; \ + napi_throw_error((env), errorMessage); \ + return; \ } static const char theText[] = diff --git a/test/addons-napi/test_conversions/test_conversions.c b/test/addons-napi/test_conversions/test_conversions.c index 4902752761..d39ded0531 100644 --- a/test/addons-napi/test_conversions/test_conversions.c +++ b/test/addons-napi/test_conversions/test_conversions.c @@ -1,7 +1,7 @@ #include void ThrowLastError(napi_env env) { - const napi_extended_error_info* error_info = napi_get_last_error_info(); + const napi_extended_error_info* error_info = napi_get_last_error_info(env); if (error_info->error_code != napi_ok) { napi_throw_error(env, error_info->error_message); } From 72a2efbd77d81044d6d4655559f7d98b371b0f77 Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Wed, 29 Mar 2017 13:40:25 +0300 Subject: [PATCH 2/3] squash: address review comments --- src/node_api.cc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/node_api.cc b/src/node_api.cc index 06db2cb08a..6b4bc371c1 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -22,7 +22,12 @@ napi_status napi_set_last_error(napi_env env, void* engine_reserved = nullptr); void napi_clear_last_error(napi_env env); -struct napi_env__ { +class napi_env__ { + public: + explicit napi_env__(v8::Isolate* _isolate): isolate(_isolate), last_error() {} + ~napi_env__() { + last_exception.Reset(); + } v8::Isolate* isolate; v8::Persistent last_exception; napi_extended_error_info last_error; @@ -533,9 +538,7 @@ void napi_module_register_cb(v8::Local exports, // some other framework makes use of slot 0? There really seems to be a need // for a more robust way of assigning arbitrary data to the isolate. if (isolate->GetData(0) == nullptr) { - napi_env env = new napi_env__; - env->isolate = isolate; - napi_clear_last_error(env); + napi_env env = new napi_env__(isolate); isolate->SetData(0, env); } From dcada40982e9d8be5cc13a62a88968e038db7bae Mon Sep 17 00:00:00 2001 From: Gabriel Schulhof Date: Wed, 29 Mar 2017 15:49:36 +0300 Subject: [PATCH 3/3] squash: put brackets around macro arguments --- src/node_api.cc | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/node_api.cc b/src/node_api.cc index 6b4bc371c1..5ddae30e23 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -600,38 +600,39 @@ void napi_module_register(napi_module* mod) { 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_ARG(env, env); \ - RETURN_STATUS_IF_FALSE(env, env->last_exception.IsEmpty(), \ - napi_pending_exception); \ - napi_clear_last_error((env)); \ +#define NAPI_PREAMBLE(env) \ + CHECK_ARG((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(); \ + 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) + 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) + 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) + 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_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( \ +#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(); \ + CHECK_MAYBE_EMPTY((env), str_maybe, napi_generic_failure); \ + result = str_maybe.ToLocalChecked(); \ } while (0) #define CHECK_NEW_FROM_UTF8(env, result, str) \