From c10ac7f3ed33795296ed7647cf289d7fc62175c3 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Mon, 3 Apr 2017 15:06:08 -0700 Subject: [PATCH 1/2] Updates for N-API async changes --- napi-inl.h | 116 ++++++++++++++++++++++++++++------------------------- napi.h | 21 +++++----- 2 files changed, 73 insertions(+), 64 deletions(-) diff --git a/napi-inl.h b/napi-inl.h index 33db79ef2..dea659635 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -1102,37 +1102,43 @@ inline void Buffer::EnsureInfo() const { //////////////////////////////////////////////////////////////////////////////// inline Error Error::New(napi_env env) { + napi_status status; napi_value error = nullptr; if (Napi::Env(env).IsExceptionPending()) { - napi_get_and_clear_last_exception(env, &error); + status = napi_get_and_clear_last_exception(env, &error); + assert(status == napi_ok); } else { // No JS exception is pending, so check for NAPI error info. - const napi_extended_error_info* info = napi_get_last_error_info(); - - const char* error_message = info->error_message != nullptr ? - info->error_message : "Error in native callback"; - napi_value message; - napi_status status = napi_create_string_utf8( - env, - error_message, - strlen(error_message), - &message); + const napi_extended_error_info* info; + status = napi_get_last_error_info(env, &info); assert(status == napi_ok); if (status == napi_ok) { - switch (info->error_code) { - case napi_object_expected: - case napi_string_expected: - case napi_boolean_expected: - case napi_number_expected: - status = napi_create_type_error(env, message, &error); - break; - default: - status = napi_create_error(env, message, &error); - break; - } + const char* error_message = info->error_message != nullptr ? + info->error_message : "Error in native callback"; + napi_value message; + status = napi_create_string_utf8( + env, + error_message, + strlen(error_message), + &message); assert(status == napi_ok); + + if (status == napi_ok) { + switch (info->error_code) { + case napi_object_expected: + case napi_string_expected: + case napi_boolean_expected: + case napi_number_expected: + status = napi_create_type_error(env, message, &error); + break; + default: + status = napi_create_error(env, message, &error); + break; + } + assert(status == napi_ok); + } } } @@ -1316,7 +1322,7 @@ inline T Reference::Value() const { template inline int Reference::Ref() { - int result; + uint32_t result; napi_status status = napi_reference_ref(_env, _ref, &result); if (status != napi_ok) throw Error::New(_env); return result; @@ -1324,7 +1330,7 @@ inline int Reference::Ref() { template inline int Reference::Unref() { - int result; + uint32_t result; napi_status status = napi_reference_unref(_env, _ref, &result); if (status != napi_ok) throw Error::New(_env); return result; @@ -2117,12 +2123,14 @@ inline AsyncWorker::AsyncWorker(const Function& callback) : _callback(Napi::Persistent(callback)), _persistent(Napi::Persistent(Object::New(callback.Env()))), _env(callback.Env()) { - _work = napi_create_async_work(); + napi_status status = napi_create_async_work( + _env, OnExecute, OnWorkComplete, this, &_work); + if (status != napi_ok) throw Error::New(_env); } inline AsyncWorker::~AsyncWorker() { if (_work != nullptr) { - napi_delete_async_work(_work); + napi_delete_async_work(_env, _work); _work = nullptr; } } @@ -2133,7 +2141,7 @@ inline AsyncWorker::AsyncWorker(AsyncWorker&& other) { _work = other._work; other._work = nullptr; _persistent = std::move(other._persistent); - _errmsg = std::move(other._errmsg); + _error = std::move(other._error); } inline AsyncWorker& AsyncWorker::operator =(AsyncWorker&& other) { @@ -2142,11 +2150,11 @@ inline AsyncWorker& AsyncWorker::operator =(AsyncWorker&& other) { _work = other._work; other._work = nullptr; _persistent = std::move(other._persistent); - _errmsg = std::move(other._errmsg); + _error = std::move(other._error); return *this; } -inline AsyncWorker::operator napi_work() const { +inline AsyncWorker::operator napi_async_work() const { return _work; } @@ -2155,20 +2163,22 @@ inline Env AsyncWorker::Env() const { } inline void AsyncWorker::Queue() { - napi_async_set_data(_work, static_cast(this)); - napi_async_set_execute(_work, OnExecute); - napi_async_set_complete(_work, OnWorkComplete); - napi_async_set_destroy(_work, OnDestroy); - napi_async_queue_worker(_work); + napi_status status = napi_queue_async_work(_env, _work); + if (status != napi_ok) throw Error::New(_env); +} + +inline void AsyncWorker::Cancel() { + napi_status status = napi_cancel_async_work(_env, _work); + if (status != napi_ok) throw Error::New(_env); } inline void AsyncWorker::WorkComplete() { HandleScope scope(_env); - if (_errmsg.size() == 0) { + if (_error.IsEmpty()) { OnOK(); } else { - OnError(); + OnError(_error.Value()); } } @@ -2180,32 +2190,30 @@ inline void AsyncWorker::OnOK() { _callback.MakeCallback(Env().Global(), std::vector()); } -inline void AsyncWorker::OnError() { - _callback.MakeCallback(Env().Global(), std::vector({ - Error::New(Env(), _errmsg), - })); +inline void AsyncWorker::OnError(Error e) { + _callback.MakeCallback(Env().Global(), std::vector({ e })); } -inline void AsyncWorker::SetErrorMessage(const std::string& msg) { - _errmsg = msg; +inline void AsyncWorker::SetError(Error error) { + _error.Reset(error, 1); } -inline const std::string& AsyncWorker::ErrorMessage() const { - return _errmsg; -} - -inline void AsyncWorker::OnExecute(void* this_pointer) { - AsyncWorker* self = static_cast(this_pointer); - self->Execute(); -} - -inline void AsyncWorker::OnWorkComplete(void* this_pointer) { +inline void AsyncWorker::OnExecute(napi_env env, void* this_pointer) { AsyncWorker* self = static_cast(this_pointer); - self->WorkComplete(); + try { + self->Execute(); + } + catch (const Error& e) { + self->SetError(e); + } } -inline void AsyncWorker::OnDestroy(void* this_pointer) { +inline void AsyncWorker::OnWorkComplete( + napi_env env, napi_status status, void* this_pointer) { AsyncWorker* self = static_cast(this_pointer); + if (status != napi_cancelled) { + self->WorkComplete(); + } delete self; } diff --git a/napi.h b/napi.h index 5dc37ab96..6f17ba2dd 100644 --- a/napi.h +++ b/napi.h @@ -10,7 +10,6 @@ //////////////////////////////////////////////////////////////////////////////// #include "node_api.h" -#include "node_api_async.h" #include #include #include @@ -821,11 +820,13 @@ namespace Napi { AsyncWorker(const AsyncWorker&) = delete; AsyncWorker& operator =(AsyncWorker&) = delete; - operator napi_work() const; + operator napi_async_work() const; Env Env() const; void Queue(); + void Cancel(); + virtual void Execute() = 0; virtual void WorkComplete(); @@ -835,22 +836,22 @@ namespace Napi { explicit AsyncWorker(const Function& callback); virtual void OnOK(); - virtual void OnError(); + virtual void OnError(Error e); - void SetErrorMessage(const std::string& msg); - const std::string& ErrorMessage() const; + void SetError(Error error); FunctionReference _callback; ObjectReference _persistent; private: - static void OnExecute(void* this_pointer); - static void OnWorkComplete(void* this_pointer); - static void OnDestroy(void* this_pointer); + static void OnExecute(napi_env env, void* this_pointer); + static void OnWorkComplete(napi_env env, + napi_status status, + void* this_pointer); napi_env _env; - napi_work _work; - std::string _errmsg; + napi_async_work _work; + Reference _error; }; } // namespace Napi From 89479e6fc2ec28793bd03f46daf25fe60e0ebe85 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Tue, 4 Apr 2017 09:19:17 -0700 Subject: [PATCH 2/2] Update refcount to uint32_t in more places --- napi-inl.h | 8 ++++---- napi.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/napi-inl.h b/napi-inl.h index dea659635..91dfd8b55 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -1229,7 +1229,7 @@ inline RangeError::RangeError(napi_env env, napi_value value) : Error(env, value //////////////////////////////////////////////////////////////////////////////// template -inline Reference Reference::New(const T& value, int initialRefcount) { +inline Reference Reference::New(const T& value, uint32_t initialRefcount) { napi_env env = value.Env(); napi_value val = value; @@ -1321,7 +1321,7 @@ inline T Reference::Value() const { } template -inline int Reference::Ref() { +inline uint32_t Reference::Ref() { uint32_t result; napi_status status = napi_reference_ref(_env, _ref, &result); if (status != napi_ok) throw Error::New(_env); @@ -1329,7 +1329,7 @@ inline int Reference::Ref() { } template -inline int Reference::Unref() { +inline uint32_t Reference::Unref() { uint32_t result; napi_status status = napi_reference_unref(_env, _ref, &result); if (status != napi_ok) throw Error::New(_env); @@ -1346,7 +1346,7 @@ inline void Reference::Reset() { } template -inline void Reference::Reset(const T& value, int refcount) { +inline void Reference::Reset(const T& value, uint32_t refcount) { Reset(); _env = value.Env(); diff --git a/napi.h b/napi.h index 6f17ba2dd..332f9de92 100644 --- a/napi.h +++ b/napi.h @@ -491,7 +491,7 @@ namespace Napi { template class Reference { public: - static Reference New(const T& value, int initialRefcount = 0); + static Reference New(const T& value, uint32_t initialRefcount = 0); Reference(); Reference(napi_env env, napi_ref ref); @@ -514,10 +514,10 @@ namespace Napi { // within a HandleScope so that the value handle gets cleaned up efficiently. T Value() const; - int Ref(); - int Unref(); + uint32_t Ref(); + uint32_t Unref(); void Reset(); - void Reset(const T& value, int refcount = 0); + void Reset(const T& value, uint32_t refcount = 0); // Call this on a reference that is declared as static data, to prevent its destructor // from running at program shutdown time, which would attempt to reset the reference when