diff --git a/include/napi-inl.h b/include/napi-inl.h index 0052788..0680660 100644 --- a/include/napi-inl.h +++ b/include/napi-inl.h @@ -24,213 +24,322 @@ namespace Napi { #ifdef NAPI_CPP_CUSTOM_NAMESPACE - namespace NAPI_CPP_CUSTOM_NAMESPACE { +namespace NAPI_CPP_CUSTOM_NAMESPACE { #endif // Helpers to handle functions exposed from C++ and internal constants. - namespace details { +namespace details { // New napi_status constants not yet available in all supported versions of // Node.js releases. Only necessary when they are used in napi.h and napi-inl.h. - constexpr int napi_no_external_buffers_allowed = 22; - -#if (defined(NAPI_EXPERIMENTAL) && \ - defined(NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER)) - template -inline void PostFinalizerWrapper(node_api_nogc_env nogc_env, - void* data, - void* hint) { - napi_status status = node_api_post_finalizer(nogc_env, finalizer, data, hint); - NAPI_FATAL_IF_FAILED( - status, "PostFinalizerWrapper", "node_api_post_finalizer failed"); -} -#else - template - inline void PostFinalizerWrapper(napi_env env, void* data, void* hint) { - finalizer(env, data, hint); - } -#endif +constexpr int napi_no_external_buffers_allowed = 22; - template - inline void default_finalizer(napi_env /*env*/, void* data, void* /*hint*/) { - delete static_cast(data); - } +template +inline void default_basic_finalizer(node_addon_api_basic_env /*env*/, + void* data, + void* /*hint*/) { + delete static_cast(data); +} // Attach a data item to an object and delete it when the object gets // garbage-collected. // TODO: Replace this code with `napi_add_finalizer()` whenever it becomes // available on all supported versions of Node.js. - template > - inline napi_status AttachData(napi_env env, - napi_value obj, - FreeType* data, - void* hint = nullptr) { - napi_status status; +template < + typename FreeType, + node_addon_api_basic_finalize finalizer = default_basic_finalizer> +inline napi_status AttachData(napi_env env, + napi_value obj, + FreeType* data, + void* hint = nullptr) { + napi_status status; #if (NAPI_VERSION < 5) - #ifndef OHOS - napi_value symbol, external; - status = napi_create_symbol(env, nullptr, &symbol); - if (status == napi_ok) { - status = napi_create_external(env, data, finalizer, hint, &external); - if (status == napi_ok) { - napi_property_descriptor desc = {nullptr, - symbol, - nullptr, - nullptr, - nullptr, - external, - napi_default, - nullptr}; - status = napi_define_properties(env, obj, 1, &desc); - } - } - #endif + #ifndef OHOS + napi_value symbol, external; + status = napi_create_symbol(env, nullptr, &symbol); + if (status == napi_ok) { + status = napi_create_external(env, data, finalizer, hint, &external); + if (status == napi_ok) { + napi_property_descriptor desc = {nullptr, + symbol, + nullptr, + nullptr, + nullptr, + external, + napi_default, + nullptr}; + status = napi_define_properties(env, obj, 1, &desc); + } + } + #endif #else // NAPI_VERSION >= 5 - status = napi_add_finalizer( - env, obj, data, details::PostFinalizerWrapper, hint, nullptr); + status = napi_add_finalizer(env, obj, data, finalizer, hint, nullptr); #endif - return status; - } + return status; +} // For use in JS to C++ callback wrappers to catch any Napi::Error exceptions // and rethrow them as JavaScript exceptions before returning from the callback. - template - inline napi_value WrapCallback(Callable callback) { -#ifdef NAPI_CPP_EXCEPTIONS - try { +template +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL +inline napi_value WrapCallback(napi_env env, Callable callback) { +#else +inline napi_value WrapCallback(napi_env, Callable callback) { +#endif +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + try { return callback(); } catch (const Error& e) { e.ThrowAsJavaScriptException(); return nullptr; } -#else // NAPI_CPP_EXCEPTIONS - // When C++ exceptions are disabled, errors are immediately thrown as JS - // exceptions, so there is no need to catch and rethrow them here. - return callback(); -#endif // NAPI_CPP_EXCEPTIONS - } +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL + catch (const std::exception& e) { + Napi::Error::New(env, e.what()).ThrowAsJavaScriptException(); + return nullptr; + } catch (...) { + Napi::Error::New(env, "A native exception was thrown") + .ThrowAsJavaScriptException(); + return nullptr; + } +#endif // NODE_ADDON_API_CPP_EXCEPTIONS_ALL +#else // NODE_ADDON_API_CPP_EXCEPTIONS + // When C++ exceptions are disabled, errors are immediately thrown as JS + // exceptions, so there is no need to catch and rethrow them here. + return callback(); +#endif // NODE_ADDON_API_CPP_EXCEPTIONS +} // For use in JS to C++ void callback wrappers to catch any Napi::Error // exceptions and rethrow them as JavaScript exceptions before returning from // the callback. - template - inline void WrapVoidCallback(Callable callback) { -#ifdef NAPI_CPP_EXCEPTIONS - try { +template +inline void WrapVoidCallback(Callable callback) { +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + try { callback(); } catch (const Error& e) { e.ThrowAsJavaScriptException(); } #else // NAPI_CPP_EXCEPTIONS - // When C++ exceptions are disabled, errors are immediately thrown as JS - // exceptions, so there is no need to catch and rethrow them here. - callback(); + // When C++ exceptions are disabled, errors are immediately thrown as JS + // exceptions, so there is no need to catch and rethrow them here. + callback(); #endif // NAPI_CPP_EXCEPTIONS - } +} + +// For use in JS to C++ void callback wrappers to catch _any_ thrown exception +// and rethrow them as JavaScript exceptions before returning from the callback, +// wrapping in an Napi::Error as needed. +template +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL +inline void WrapVoidCallback(napi_env env, Callable callback) { +#else +inline void WrapVoidCallback(napi_env, Callable callback) { +#endif +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + try { + callback(); + } catch (const Error& e) { + e.ThrowAsJavaScriptException(); + } +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS_ALL + catch (const std::exception& e) { + Napi::Error::New(env, e.what()).ThrowAsJavaScriptException(); + } catch (...) { + Napi::Error::New(env, "A native exception was thrown") + .ThrowAsJavaScriptException(); + } +#endif // NODE_ADDON_API_CPP_EXCEPTIONS_ALL +#else + // When C++ exceptions are disabled, there is no need to catch and rethrow C++ + // exceptions. JS errors should be thrown with + // `Error::ThrowAsJavaScriptException`. + callback(); +#endif // NODE_ADDON_API_CPP_EXCEPTIONS +} + +template +struct CallbackData { + static inline napi_value Wrapper(napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + CallbackData* callbackData = + static_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + return callbackData->callback(callbackInfo); + }); + } + + Callable callback; + void* data; +}; - template - struct CallbackData { - static inline napi_value Wrapper(napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - CallbackData* callbackData = - static_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - return callbackData->callback(callbackInfo); - }); - } - - Callable callback; - void* data; - }; - - template - struct CallbackData { - static inline napi_value Wrapper(napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - CallbackData* callbackData = - static_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - callbackData->callback(callbackInfo); - return nullptr; - }); - } - - Callable callback; - void* data; - }; - - template - napi_value TemplatedVoidCallback(napi_env env, - napi_callback_info info) NAPI_NOEXCEPT { - return details::WrapCallback([&] { - CallbackInfo cbInfo(env, info); - Callback(cbInfo); - return nullptr; +template +struct CallbackData { + static inline napi_value Wrapper(napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + CallbackData* callbackData = + static_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + callbackData->callback(callbackInfo); + return nullptr; }); + } + + Callable callback; + void* data; +}; + +template +napi_value TemplatedVoidCallback(napi_env env, + napi_callback_info info) NAPI_NOEXCEPT { + return details::WrapCallback(env, [&] { + CallbackInfo cbInfo(env, info); + Callback(cbInfo); + return nullptr; + }); } template napi_value TemplatedCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT { -return details::WrapCallback([&] { -CallbackInfo cbInfo(env, info); -// MSVC requires to copy 'Callback' function pointer to a local variable -// before invoking it. -auto callback = Callback; -return callback(cbInfo); -}); + return details::WrapCallback(env, [&] { + CallbackInfo cbInfo(env, info); + // MSVC requires to copy 'Callback' function pointer to a local variable + // before invoking it. + auto callback = Callback; + return callback(cbInfo); + }); } template + Napi::Value (T::*UnwrapCallback)(const CallbackInfo& info)> napi_value TemplatedInstanceCallback(napi_env env, napi_callback_info info) NAPI_NOEXCEPT { -return details::WrapCallback([&] { -CallbackInfo cbInfo(env, info); -T* instance = T::Unwrap(cbInfo.This().As()); -return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value(); -}); + return details::WrapCallback(env, [&] { + CallbackInfo cbInfo(env, info); + T* instance = T::Unwrap(cbInfo.This().As()); + return instance ? (instance->*UnwrapCallback)(cbInfo) : Napi::Value(); + }); } template napi_value TemplatedInstanceVoidCallback(napi_env env, napi_callback_info info) -NAPI_NOEXCEPT { -return details::WrapCallback([&] { -CallbackInfo cbInfo(env, info); -T* instance = T::Unwrap(cbInfo.This().As()); -if (instance) (instance->*UnwrapCallback)(cbInfo); -return nullptr; -}); + NAPI_NOEXCEPT { + return details::WrapCallback(env, [&] { + CallbackInfo cbInfo(env, info); + T* instance = T::Unwrap(cbInfo.This().As()); + if (instance) (instance->*UnwrapCallback)(cbInfo); + return nullptr; + }); } template struct FinalizeData { - static inline void Wrapper(napi_env env, +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + template >> +#endif + static inline void Wrapper(node_addon_api_basic_env env, + void* data, + void* finalizeHint) NAPI_NOEXCEPT { + WrapVoidCallback([&] { + FinalizeData* finalizeData = static_cast(finalizeHint); + finalizeData->callback(env, static_cast(data)); + delete finalizeData; + }); + } + +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + template >, + typename = void> + static inline void Wrapper(node_addon_api_basic_env env, + void* data, + void* finalizeHint) NAPI_NOEXCEPT { +#ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS + static_assert(false, + "NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS defined: Finalizer " + "must be basic."); +#endif + napi_status status = + node_api_post_finalizer(env, WrapperGC, data, finalizeHint); + NAPI_FATAL_IF_FAILED( + status, "FinalizeData::Wrapper", "node_api_post_finalizer failed"); + } +#endif + +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + template >> +#endif + static inline void WrapperWithHint(node_addon_api_basic_env env, + void* data, + void* finalizeHint) NAPI_NOEXCEPT { + WrapVoidCallback([&] { + FinalizeData* finalizeData = static_cast(finalizeHint); + finalizeData->callback(env, static_cast(data), finalizeData->hint); + delete finalizeData; + }); + } + +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + template >, + typename = void> + static inline void WrapperWithHint(node_addon_api_basic_env env, + void* data, + void* finalizeHint) NAPI_NOEXCEPT { +#ifdef NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS + static_assert(false, + "NODE_ADDON_API_REQUIRE_BASIC_FINALIZERS defined: Finalizer " + "must be basic."); +#endif + napi_status status = + node_api_post_finalizer(env, WrapperGCWithHint, data, finalizeHint); + NAPI_FATAL_IF_FAILED( + status, "FinalizeData::Wrapper", "node_api_post_finalizer failed"); + } +#endif + + static inline void WrapperGCWithoutData(napi_env env, + void* /*data*/, + void* finalizeHint) NAPI_NOEXCEPT { + WrapVoidCallback(env, [&] { + FinalizeData* finalizeData = static_cast(finalizeHint); + finalizeData->callback(env); + delete finalizeData; + }); + } + + static inline void WrapperGC(napi_env env, void* data, void* finalizeHint) NAPI_NOEXCEPT { - WrapVoidCallback([&] { - FinalizeData* finalizeData = static_cast(finalizeHint); - finalizeData->callback(Env(env), static_cast(data)); - delete finalizeData; - }); - } + WrapVoidCallback(env, [&] { + FinalizeData* finalizeData = static_cast(finalizeHint); + finalizeData->callback(env, static_cast(data)); + delete finalizeData; + }); + } - static inline void WrapperWithHint(napi_env env, + static inline void WrapperGCWithHint(napi_env env, void* data, void* finalizeHint) NAPI_NOEXCEPT { - WrapVoidCallback([&] { - FinalizeData* finalizeData = static_cast(finalizeHint); - finalizeData->callback( - Env(env), static_cast(data), finalizeData->hint); - delete finalizeData; - }); - } + WrapVoidCallback(env, [&] { + FinalizeData* finalizeData = static_cast(finalizeHint); + finalizeData->callback(env, static_cast(data), finalizeData->hint); + delete finalizeData; + }); + } - Finalizer callback; - Hint* hint; + Finalizer callback; + Hint* hint; }; #if (NAPI_VERSION > 3 && NAPI_HAS_THREADS) @@ -289,7 +398,7 @@ struct ThreadSafeFinalize { template inline typename std::enable_if(nullptr)>::type CallJsWrapper(napi_env env, napi_value jsCallback, void* context, void* data) { - details::WrapVoidCallback([&]() { + details::WrapVoidCallback(env, [&]() { call(env, Function(env, jsCallback), static_cast(context), @@ -303,7 +412,7 @@ CallJsWrapper(napi_env env, napi_value jsCallback, void* /*context*/, void* /*data*/) { - details::WrapVoidCallback([&]() { + details::WrapVoidCallback(env, [&]() { if (jsCallback != nullptr) { Function(env, jsCallback).Call(0, nullptr); } @@ -335,46 +444,74 @@ napi_value DefaultCallbackWrapper(napi_env env, Napi::Function cb) { template struct AccessorCallbackData { - static inline napi_value GetterWrapper(napi_env env, - napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - AccessorCallbackData* callbackData = - static_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - return callbackData->getterCallback(callbackInfo); - }); - } + static inline napi_value GetterWrapper(napi_env env, + napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + AccessorCallbackData* callbackData = + static_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + return callbackData->getterCallback(callbackInfo); + }); + } - static inline napi_value SetterWrapper(napi_env env, - napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - AccessorCallbackData* callbackData = - static_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - callbackData->setterCallback(callbackInfo); - return nullptr; - }); - } + static inline napi_value SetterWrapper(napi_env env, + napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + AccessorCallbackData* callbackData = + static_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + callbackData->setterCallback(callbackInfo); + return nullptr; + }); + } - Getter getterCallback; - Setter setterCallback; - void* data; + Getter getterCallback; + Setter setterCallback; + void* data; }; // Debugging-purpose C++-style variant of sprintf(). inline std::string StringFormat(const char* format, ...) { - std::string result; - va_list args; - va_start(args, format); - int len = vsnprintf(nullptr, 0, format, args); - result.resize(len); - vsnprintf(&result[0], len + 1, format, args); - va_end(args); - return result; + std::string result; + va_list args; + va_start(args, format); + int len = vsnprintf(nullptr, 0, format, args); + result.resize(len); + vsnprintf(&result[0], len + 1, format, args); + va_end(args); + return result; } +template +class HasExtendedFinalizer { + private: + template + struct SFINAE {}; + template + static char test(SFINAE*); + template + static int test(...); + + public: + static constexpr bool value = sizeof(test(0)) == sizeof(char); +}; + +template +class HasBasicFinalizer { + private: + template + struct SFINAE {}; + template + static char test(SFINAE*); + template + static int test(...); + + public: + static constexpr bool value = sizeof(test(0)) == sizeof(char); +}; + } // namespace details #ifndef NODE_ADDON_API_DISABLE_DEPRECATED @@ -408,176 +545,187 @@ inline std::string StringFormat(const char* format, ...) { // Adapt the NAPI_MODULE registration function: // - Wrap the arguments in NAPI wrappers. // - Catch any NAPI errors and rethrow as JS exceptions. - inline napi_value RegisterModule(napi_env env, - napi_value exports, - ModuleRegisterCallback registerCallback) { - return details::WrapCallback([&] { - return napi_value( - registerCallback(Napi::Env(env), Napi::Object(env, exports))); - }); - } +inline napi_value RegisterModule(napi_env env, + napi_value exports, + ModuleRegisterCallback registerCallback) { + return details::WrapCallback(env, [&] { + return napi_value( + registerCallback(Napi::Env(env), Napi::Object(env, exports))); + }); +} //////////////////////////////////////////////////////////////////////////////// // Maybe class //////////////////////////////////////////////////////////////////////////////// - template - bool Maybe::IsNothing() const { - return !_has_value; - } +template +bool Maybe::IsNothing() const { + return !_has_value; +} - template - bool Maybe::IsJust() const { - return _has_value; - } +template +bool Maybe::IsJust() const { + return _has_value; +} - template - void Maybe::Check() const { - NAPI_CHECK(IsJust(), "Napi::Maybe::Check", "Maybe value is Nothing."); - } +template +void Maybe::Check() const { + NAPI_CHECK(IsJust(), "Napi::Maybe::Check", "Maybe value is Nothing."); +} - template - T Maybe::Unwrap() const { - NAPI_CHECK(IsJust(), "Napi::Maybe::Unwrap", "Maybe value is Nothing."); - return _value; - } +template +T Maybe::Unwrap() const { + NAPI_CHECK(IsJust(), "Napi::Maybe::Unwrap", "Maybe value is Nothing."); + return _value; +} - template - T Maybe::UnwrapOr(const T& default_value) const { - return _has_value ? _value : default_value; - } +template +T Maybe::UnwrapOr(const T& default_value) const { + return _has_value ? _value : default_value; +} - template - bool Maybe::UnwrapTo(T* out) const { - if (IsJust()) { - *out = _value; - return true; - }; - return false; - } +template +bool Maybe::UnwrapTo(T* out) const { + if (IsJust()) { + *out = _value; + return true; + }; + return false; +} - template - bool Maybe::operator==(const Maybe& other) const { - return (IsJust() == other.IsJust()) && - (!IsJust() || Unwrap() == other.Unwrap()); - } +template +bool Maybe::operator==(const Maybe& other) const { + return (IsJust() == other.IsJust()) && + (!IsJust() || Unwrap() == other.Unwrap()); +} - template - bool Maybe::operator!=(const Maybe& other) const { - return !operator==(other); - } +template +bool Maybe::operator!=(const Maybe& other) const { + return !operator==(other); +} - template - Maybe::Maybe() : _has_value(false) {} +template +Maybe::Maybe() : _has_value(false) {} - template - Maybe::Maybe(const T& t) : _has_value(true), _value(t) {} +template +Maybe::Maybe(const T& t) : _has_value(true), _value(t) {} - template - inline Maybe Nothing() { - return Maybe(); - } +template +inline Maybe Nothing() { + return Maybe(); +} - template - inline Maybe Just(const T& t) { - return Maybe(t); - } +template +inline Maybe Just(const T& t) { + return Maybe(t); +} //////////////////////////////////////////////////////////////////////////////// -// Env class +// BasicEnv / Env class //////////////////////////////////////////////////////////////////////////////// - inline Env::Env(napi_env env) : _env(env) {} +inline BasicEnv::BasicEnv(node_addon_api_basic_env env) : _env(env) {} - inline Env::operator napi_env() const { - return _env; - } +inline BasicEnv::operator node_addon_api_basic_env() const { + return _env; +} - inline Object Env::Global() const { - napi_value value; - napi_status status = napi_get_global(*this, &value); - NAPI_THROW_IF_FAILED(*this, status, Object()); - return Object(*this, value); - } +inline Env::Env(napi_env env) : BasicEnv(env) {} - inline Value Env::Undefined() const { - napi_value value; - napi_status status = napi_get_undefined(*this, &value); - NAPI_THROW_IF_FAILED(*this, status, Value()); - return Value(*this, value); - } +inline Env::operator napi_env() const { + return const_cast(_env); +} - inline Value Env::Null() const { - napi_value value; - napi_status status = napi_get_null(*this, &value); - NAPI_THROW_IF_FAILED(*this, status, Value()); - return Value(*this, value); - } +inline Object Env::Global() const { + napi_value value; + napi_status status = napi_get_global(*this, &value); + NAPI_THROW_IF_FAILED(*this, status, Object()); + return Object(*this, value); +} - inline bool Env::IsExceptionPending() const { - bool result; - napi_status status = napi_is_exception_pending(_env, &result); - if (status != napi_ok) - result = false; // Checking for a pending exception shouldn't throw. - return result; - } +inline Value Env::Undefined() const { + napi_value value; + napi_status status = napi_get_undefined(*this, &value); + NAPI_THROW_IF_FAILED(*this, status, Value()); + return Value(*this, value); +} - inline Error Env::GetAndClearPendingException() const { - napi_value value; - napi_status status = napi_get_and_clear_last_exception(_env, &value); - if (status != napi_ok) { - // Don't throw another exception when failing to get the exception! - return Error(); - } - return Error(_env, value); - } +inline Value Env::Null() const { + napi_value value; + napi_status status = napi_get_null(*this, &value); + NAPI_THROW_IF_FAILED(*this, status, Value()); + return Value(*this, value); +} - inline MaybeOrValue Env::RunScript(const std::string& utf8scriptPath) const { - return RunScript(utf8scriptPath.c_str()); - } +inline bool Env::IsExceptionPending() const { + bool result; + napi_status status = napi_is_exception_pending(*this, &result); + if (status != napi_ok) + result = false; // Checking for a pending exception shouldn't throw. + return result; +} - inline MaybeOrValue Env::RunScript(const char* scriptPath) const { - napi_value result; - napi_status status = napi_run_script_path(_env, scriptPath, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Value(_env, result), Napi::Value); - } +inline Error Env::GetAndClearPendingException() const { + napi_value value; + napi_status status = napi_get_and_clear_last_exception(*this, &value); + if (status != napi_ok) { + // Don't throw another exception when failing to get the exception! + return Error(); + } + return Error(*this, value); +} + +inline MaybeOrValue Env::RunScript(const char* utf8script) const { + String script = String::New(*this, utf8script); + return RunScript(script); +} + +inline MaybeOrValue Env::RunScript(const std::string& utf8script) const { + return RunScript(utf8script.c_str()); +} + +inline MaybeOrValue Env::RunScript(String script) const { + napi_value result; + napi_status status = napi_run_script(*this, script, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + *this, status, Napi::Value(*this, result), Napi::Value); +} #if NAPI_VERSION > 2 - template -void Env::CleanupHook::Wrapper(void* data) NAPI_NOEXCEPT { - auto* cleanupData = - static_cast::CleanupData*>( - data); +template +void BasicEnv::CleanupHook::Wrapper(void* data) NAPI_NOEXCEPT { + auto* cleanupData = static_cast< + typename Napi::BasicEnv::CleanupHook::CleanupData*>(data); cleanupData->hook(); delete cleanupData; } template -void Env::CleanupHook::WrapperWithArg(void* data) NAPI_NOEXCEPT { - auto* cleanupData = - static_cast::CleanupData*>( - data); +void BasicEnv::CleanupHook::WrapperWithArg(void* data) + NAPI_NOEXCEPT { + auto* cleanupData = static_cast< + typename Napi::BasicEnv::CleanupHook::CleanupData*>(data); cleanupData->hook(static_cast(cleanupData->arg)); delete cleanupData; } #endif // NAPI_VERSION > 2 #if NAPI_VERSION > 5 - template fini> -inline void Env::SetInstanceData(T* data) const { +template fini> +inline void BasicEnv::SetInstanceData(T* data) const { napi_status status = napi_set_instance_data( _env, data, [](napi_env env, void* data, void*) { fini(env, static_cast(data)); }, nullptr); - NAPI_THROW_IF_FAILED_VOID(_env, status); + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::SetInstanceData", "invalid arguments"); } template fini> -inline void Env::SetInstanceData(DataType* data, HintType* hint) const { + Napi::BasicEnv::FinalizerWithHint fini> +inline void BasicEnv::SetInstanceData(DataType* data, HintType* hint) const { napi_status status = napi_set_instance_data( _env, data, @@ -585,35 +733,38 @@ inline void Env::SetInstanceData(DataType* data, HintType* hint) const { fini(env, static_cast(data), static_cast(hint)); }, hint); - NAPI_THROW_IF_FAILED_VOID(_env, status); + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::SetInstanceData", "invalid arguments"); } template -inline T* Env::GetInstanceData() const { +inline T* BasicEnv::GetInstanceData() const { void* data = nullptr; napi_status status = napi_get_instance_data(_env, &data); - NAPI_THROW_IF_FAILED(_env, status, nullptr); + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::GetInstanceData", "invalid arguments"); return static_cast(data); } template -void Env::DefaultFini(Env, T* data) { +void BasicEnv::DefaultFini(Env, T* data) { delete data; } template -void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) { +void BasicEnv::DefaultFiniWithHint(Env, DataType* data, HintType*) { delete data; } #endif // NAPI_VERSION > 5 #if NAPI_VERSION > 8 - inline const char* Env::GetModuleFileName() const { +inline const char* BasicEnv::GetModuleFileName() const { const char* result; napi_status status = node_api_get_module_file_name(_env, &result); - NAPI_THROW_IF_FAILED(*this, status, nullptr); + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::GetModuleFileName", "invalid arguments"); return result; } #endif // NAPI_VERSION > 8 @@ -621,73 +772,73 @@ void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) { // Value class //////////////////////////////////////////////////////////////////////////////// - inline Value::Value() : _env(nullptr), _value(nullptr) {} +inline Value::Value() : _env(nullptr), _value(nullptr) {} - inline Value::Value(napi_env env, napi_value value) - : _env(env), _value(value) {} +inline Value::Value(napi_env env, napi_value value) + : _env(env), _value(value) {} - inline Value::operator napi_value() const { - return _value; - } +inline Value::operator napi_value() const { + return _value; +} - inline bool Value::operator==(const Value& other) const { - return StrictEquals(other); - } +inline bool Value::operator==(const Value& other) const { + return StrictEquals(other); +} - inline bool Value::operator!=(const Value& other) const { - return !this->operator==(other); - } +inline bool Value::operator!=(const Value& other) const { + return !this->operator==(other); +} - inline bool Value::StrictEquals(const Value& other) const { - bool result; - napi_status status = napi_strict_equals(_env, *this, other, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } +inline bool Value::StrictEquals(const Value& other) const { + bool result; + napi_status status = napi_strict_equals(_env, *this, other, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline Napi::Env Value::Env() const { - return Napi::Env(_env); - } +inline Napi::Env Value::Env() const { + return Napi::Env(_env); +} - inline bool Value::IsEmpty() const { - return _value == nullptr; - } +inline bool Value::IsEmpty() const { + return _value == nullptr; +} - inline napi_valuetype Value::Type() const { - if (IsEmpty()) { - return napi_undefined; - } +inline napi_valuetype Value::Type() const { + if (IsEmpty()) { + return napi_undefined; + } - napi_valuetype type; - napi_status status = napi_typeof(_env, _value, &type); - NAPI_THROW_IF_FAILED(_env, status, napi_undefined); - return type; - } + napi_valuetype type; + napi_status status = napi_typeof(_env, _value, &type); + NAPI_THROW_IF_FAILED(_env, status, napi_undefined); + return type; +} - inline bool Value::IsUndefined() const { - return Type() == napi_undefined; - } +inline bool Value::IsUndefined() const { + return Type() == napi_undefined; +} - inline bool Value::IsNull() const { - return Type() == napi_null; - } +inline bool Value::IsNull() const { + return Type() == napi_null; +} - inline bool Value::IsBoolean() const { - return Type() == napi_boolean; - } +inline bool Value::IsBoolean() const { + return Type() == napi_boolean; +} - inline bool Value::IsNumber() const { - return Type() == napi_number; - } +inline bool Value::IsNumber() const { + return Type() == napi_number; +} #if NAPI_VERSION > 5 - inline bool Value::IsBigInt() const { +inline bool Value::IsBigInt() const { return Type() == napi_bigint; } #endif // NAPI_VERSION > 5 #if (NAPI_VERSION > 4) - inline bool Value::IsDate() const { +inline bool Value::IsDate() const { if (IsEmpty()) { return false; } @@ -699,244 +850,255 @@ void Env::DefaultFiniWithHint(Env, DataType* data, HintType*) { } #endif - inline bool Value::IsString() const { - return Type() == napi_string; - } +inline bool Value::IsString() const { + return Type() == napi_string; +} #ifndef OHOS - inline bool Value::IsSymbol() const { - return Type() == napi_symbol; - } + +inline bool Value::IsSymbol() const { + return Type() == napi_symbol; +} #endif - inline bool Value::IsArray() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsArray() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_array(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_array(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsArrayBuffer() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsArrayBuffer() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_arraybuffer(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_arraybuffer(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsTypedArray() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsTypedArray() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_typedarray(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_typedarray(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsObject() const { - return Type() == napi_object || IsFunction(); - } +inline bool Value::IsObject() const { + return Type() == napi_object || IsFunction(); +} - inline bool Value::IsFunction() const { - return Type() == napi_function; - } +inline bool Value::IsFunction() const { + return Type() == napi_function; +} - inline bool Value::IsPromise() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsPromise() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_promise(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_promise(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsDataView() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsDataView() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_dataview(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_dataview(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsBuffer() const { - if (IsEmpty()) { - return false; - } +inline bool Value::IsBuffer() const { + if (IsEmpty()) { + return false; + } - bool result; - napi_status status = napi_is_buffer(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } + bool result; + napi_status status = napi_is_buffer(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} - inline bool Value::IsExternal() const { - return Type() == napi_external; - } +inline bool Value::IsExternal() const { + return Type() == napi_external; +} - template - inline T Value::As() const { +template +inline T Value::As() const { #ifdef NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS - T::CheckCast(_env, _value); + T::CheckCast(_env, _value); #endif - return T(_env, _value); - } + return T(_env, _value); +} - inline MaybeOrValue Value::ToBoolean() const { - napi_value result; - napi_status status = napi_coerce_to_bool(_env, _value, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Boolean(_env, result), Napi::Boolean); - } +template +inline T Value::UnsafeAs() const { + return T(_env, _value); +} - inline MaybeOrValue Value::ToNumber() const { - napi_value result; - napi_status status = napi_coerce_to_number(_env, _value, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Number(_env, result), Napi::Number); - } +// static +inline void Value::CheckCast(napi_env /* env */, napi_value value) { + NAPI_CHECK(value != nullptr, "Value::CheckCast", "empty value"); +} - inline MaybeOrValue Value::ToString() const { - napi_value result; - napi_status status = napi_coerce_to_string(_env, _value, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::String(_env, result), Napi::String); - } +inline MaybeOrValue Value::ToBoolean() const { + napi_value result; + napi_status status = napi_coerce_to_bool(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Boolean(_env, result), Napi::Boolean); +} - inline MaybeOrValue Value::ToObject() const { - napi_value result; - napi_status status = napi_coerce_to_object(_env, _value, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Object(_env, result), Napi::Object); - } +inline MaybeOrValue Value::ToNumber() const { + napi_value result; + napi_status status = napi_coerce_to_number(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Number(_env, result), Napi::Number); +} + +inline MaybeOrValue Value::ToString() const { + napi_value result; + napi_status status = napi_coerce_to_string(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::String(_env, result), Napi::String); +} + +inline MaybeOrValue Value::ToObject() const { + napi_value result; + napi_status status = napi_coerce_to_object(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Object(_env, result), Napi::Object); +} //////////////////////////////////////////////////////////////////////////////// // Boolean class //////////////////////////////////////////////////////////////////////////////// - inline Boolean Boolean::New(napi_env env, bool val) { - napi_value value; - napi_status status = napi_get_boolean(env, val, &value); - NAPI_THROW_IF_FAILED(env, status, Boolean()); - return Boolean(env, value); - } +inline Boolean Boolean::New(napi_env env, bool val) { + napi_value value; + napi_status status = napi_get_boolean(env, val, &value); + NAPI_THROW_IF_FAILED(env, status, Boolean()); + return Boolean(env, value); +} - inline void Boolean::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Boolean::CheckCast", "empty value"); +inline void Boolean::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Boolean::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Boolean::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_boolean, "%d", "Boolean::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Boolean::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_boolean, "%d", "Boolean::CheckCast"); +} - inline Boolean::Boolean() : Napi::Value() {} +inline Boolean::Boolean() : Napi::Value() {} - inline Boolean::Boolean(napi_env env, napi_value value) - : Napi::Value(env, value) {} +inline Boolean::Boolean(napi_env env, napi_value value) + : Napi::Value(env, value) {} - inline Boolean::operator bool() const { - return Value(); - } +inline Boolean::operator bool() const { + return Value(); +} - inline bool Boolean::Value() const { - bool result; - napi_status status = napi_get_value_bool(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, false); - return result; - } +inline bool Boolean::Value() const { + bool result; + napi_status status = napi_get_value_bool(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, false); + return result; +} //////////////////////////////////////////////////////////////////////////////// // Number class //////////////////////////////////////////////////////////////////////////////// - inline Number Number::New(napi_env env, double val) { - napi_value value; - napi_status status = napi_create_double(env, val, &value); - NAPI_THROW_IF_FAILED(env, status, Number()); - return Number(env, value); - } +inline Number Number::New(napi_env env, double val) { + napi_value value; + napi_status status = napi_create_double(env, val, &value); + NAPI_THROW_IF_FAILED(env, status, Number()); + return Number(env, value); +} - inline void Number::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Number::CheckCast", "empty value"); +inline void Number::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Number::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Number::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_number, "%d", "Number::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Number::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_number, "%d", "Number::CheckCast"); +} - inline Number::Number() : Value() {} +inline Number::Number() : Value() {} - inline Number::Number(napi_env env, napi_value value) : Value(env, value) {} +inline Number::Number(napi_env env, napi_value value) : Value(env, value) {} - inline Number::operator int32_t() const { - return Int32Value(); - } +inline Number::operator int32_t() const { + return Int32Value(); +} - inline Number::operator uint32_t() const { - return Uint32Value(); - } +inline Number::operator uint32_t() const { + return Uint32Value(); +} - inline Number::operator int64_t() const { - return Int64Value(); - } +inline Number::operator int64_t() const { + return Int64Value(); +} - inline Number::operator float() const { - return FloatValue(); - } +inline Number::operator float() const { + return FloatValue(); +} - inline Number::operator double() const { - return DoubleValue(); - } +inline Number::operator double() const { + return DoubleValue(); +} - inline int32_t Number::Int32Value() const { - int32_t result; - napi_status status = napi_get_value_int32(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; - } +inline int32_t Number::Int32Value() const { + int32_t result; + napi_status status = napi_get_value_int32(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; +} - inline uint32_t Number::Uint32Value() const { - uint32_t result; - napi_status status = napi_get_value_uint32(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; - } +inline uint32_t Number::Uint32Value() const { + uint32_t result; + napi_status status = napi_get_value_uint32(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; +} - inline int64_t Number::Int64Value() const { - int64_t result; - napi_status status = napi_get_value_int64(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; - } +inline int64_t Number::Int64Value() const { + int64_t result; + napi_status status = napi_get_value_int64(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; +} - inline float Number::FloatValue() const { - return static_cast(DoubleValue()); - } +inline float Number::FloatValue() const { + return static_cast(DoubleValue()); +} - inline double Number::DoubleValue() const { - double result; - napi_status status = napi_get_value_double(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; - } +inline double Number::DoubleValue() const { + double result; + napi_status status = napi_get_value_double(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; +} #if NAPI_VERSION > 5 - //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // BigInt Class //////////////////////////////////////////////////////////////////////////////// @@ -1012,7 +1174,7 @@ inline void BigInt::ToWords(int* sign_bit, #endif // NAPI_VERSION > 5 #if (NAPI_VERSION > 4) - //////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// // Date Class //////////////////////////////////////////////////////////////////////////////// @@ -1051,193 +1213,196 @@ inline double Date::ValueOf() const { //////////////////////////////////////////////////////////////////////////////// // Name class //////////////////////////////////////////////////////////////////////////////// - inline void Name::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Name::CheckCast", "empty value"); - - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Name::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK(type == napi_string || type == napi_symbol, - "Name::CheckCast", - "value is not napi_string or napi_symbol, got %d.", - type); - } +inline void Name::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Name::CheckCast", "empty value"); + + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Name::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK(type == napi_string || type == napi_symbol, + "Name::CheckCast", + "value is not napi_string or napi_symbol, got %d.", + type); +} - inline Name::Name() : Value() {} +inline Name::Name() : Value() {} - inline Name::Name(napi_env env, napi_value value) : Value(env, value) {} +inline Name::Name(napi_env env, napi_value value) : Value(env, value) {} //////////////////////////////////////////////////////////////////////////////// // String class //////////////////////////////////////////////////////////////////////////////// - inline String String::New(napi_env env, const std::string& val) { - return String::New(env, val.c_str(), val.size()); - } +inline String String::New(napi_env env, const std::string& val) { + return String::New(env, val.c_str(), val.size()); +} - inline String String::New(napi_env env, const std::u16string& val) { - return String::New(env, val.c_str(), val.size()); - } +inline String String::New(napi_env env, const std::u16string& val) { + return String::New(env, val.c_str(), val.size()); +} - inline String String::New(napi_env env, const char* val) { - // TODO(@gabrielschulhof) Remove if-statement when core's error handling is - // available in all supported versions. - if (val == nullptr) { - // Throw an error that looks like it came from core. - NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String()); - } - napi_value value; - napi_status status = - napi_create_string_utf8(env, val, std::strlen(val), &value); - NAPI_THROW_IF_FAILED(env, status, String()); - return String(env, value); - } +inline String String::New(napi_env env, const char* val) { + // TODO(@gabrielschulhof) Remove if-statement when core's error handling is + // available in all supported versions. + if (val == nullptr) { + // Throw an error that looks like it came from core. + NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String()); + } + napi_value value; + napi_status status = + napi_create_string_utf8(env, val, std::strlen(val), &value); + NAPI_THROW_IF_FAILED(env, status, String()); + return String(env, value); +} - inline String String::New(napi_env env, const char16_t* val) { - napi_value value; - // TODO(@gabrielschulhof) Remove if-statement when core's error handling is - // available in all supported versions. - if (val == nullptr) { - // Throw an error that looks like it came from core. - NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String()); - } - napi_status status = - napi_create_string_utf16(env, val, std::u16string(val).size(), &value); - NAPI_THROW_IF_FAILED(env, status, String()); - return String(env, value); - } +inline String String::New(napi_env env, const char16_t* val) { + napi_value value; + // TODO(@gabrielschulhof) Remove if-statement when core's error handling is + // available in all supported versions. + if (val == nullptr) { + // Throw an error that looks like it came from core. + NAPI_THROW_IF_FAILED(env, napi_invalid_arg, String()); + } + napi_status status = + napi_create_string_utf16(env, val, std::u16string(val).size(), &value); + NAPI_THROW_IF_FAILED(env, status, String()); + return String(env, value); +} - inline String String::New(napi_env env, const char* val, size_t length) { - napi_value value; - napi_status status = napi_create_string_utf8(env, val, length, &value); - NAPI_THROW_IF_FAILED(env, status, String()); - return String(env, value); - } +inline String String::New(napi_env env, const char* val, size_t length) { + napi_value value; + napi_status status = napi_create_string_utf8(env, val, length, &value); + NAPI_THROW_IF_FAILED(env, status, String()); + return String(env, value); +} - inline String String::New(napi_env env, const char16_t* val, size_t length) { - napi_value value; - napi_status status = napi_create_string_utf16(env, val, length, &value); - NAPI_THROW_IF_FAILED(env, status, String()); - return String(env, value); - } +inline String String::New(napi_env env, const char16_t* val, size_t length) { + napi_value value; + napi_status status = napi_create_string_utf16(env, val, length, &value); + NAPI_THROW_IF_FAILED(env, status, String()); + return String(env, value); +} - inline void String::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "String::CheckCast", "empty value"); +inline void String::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "String::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "String::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_string, "%d", "String::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "String::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_string, "%d", "String::CheckCast"); +} - inline String::String() : Name() {} +inline String::String() : Name() {} - inline String::String(napi_env env, napi_value value) : Name(env, value) {} +inline String::String(napi_env env, napi_value value) : Name(env, value) {} - inline String::operator std::string() const { - return Utf8Value(); - } +inline String::operator std::string() const { + return Utf8Value(); +} - inline String::operator std::u16string() const { - return Utf16Value(); - } +inline String::operator std::u16string() const { + return Utf16Value(); +} - inline std::string String::Utf8Value() const { - size_t length; - napi_status status = - napi_get_value_string_utf8(_env, _value, nullptr, 0, &length); - NAPI_THROW_IF_FAILED(_env, status, ""); - - std::string value; - value.reserve(length + 1); - value.resize(length); - status = napi_get_value_string_utf8( - _env, _value, &value[0], value.capacity(), nullptr); - NAPI_THROW_IF_FAILED(_env, status, ""); - return value; - } +inline std::string String::Utf8Value() const { + size_t length; + napi_status status = + napi_get_value_string_utf8(_env, _value, nullptr, 0, &length); + NAPI_THROW_IF_FAILED(_env, status, ""); - inline std::u16string String::Utf16Value() const { - size_t length; - napi_status status = - napi_get_value_string_utf16(_env, _value, nullptr, 0, &length); - NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT("")); - - std::u16string value; - value.reserve(length + 1); - value.resize(length); - status = napi_get_value_string_utf16( - _env, _value, &value[0], value.capacity(), nullptr); - NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT("")); - return value; - } + std::string value; + value.reserve(length + 1); + value.resize(length); + status = napi_get_value_string_utf8( + _env, _value, &value[0], value.capacity(), nullptr); + NAPI_THROW_IF_FAILED(_env, status, ""); + return value; +} + +inline std::u16string String::Utf16Value() const { + size_t length; + napi_status status = + napi_get_value_string_utf16(_env, _value, nullptr, 0, &length); + NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT("")); + + std::u16string value; + value.reserve(length + 1); + value.resize(length); + status = napi_get_value_string_utf16( + _env, _value, &value[0], value.capacity(), nullptr); + NAPI_THROW_IF_FAILED(_env, status, NAPI_WIDE_TEXT("")); + return value; +} //////////////////////////////////////////////////////////////////////////////// // Symbol class //////////////////////////////////////////////////////////////////////////////// #ifndef OHOS - inline Symbol Symbol::New(napi_env env, const char* description) { - napi_value descriptionValue = description != nullptr - ? String::New(env, description) - : static_cast(nullptr); - return Symbol::New(env, descriptionValue); - } +inline Symbol Symbol::New(napi_env env, const char* description) { + napi_value descriptionValue = description != nullptr + ? String::New(env, description) + : static_cast(nullptr); + return Symbol::New(env, descriptionValue); +} - inline Symbol Symbol::New(napi_env env, const std::string& description) { - napi_value descriptionValue = String::New(env, description); - return Symbol::New(env, descriptionValue); - } +inline Symbol Symbol::New(napi_env env, const std::string& description) { + napi_value descriptionValue = String::New(env, description); + return Symbol::New(env, descriptionValue); +} - inline Symbol Symbol::New(napi_env env, String description) { - napi_value descriptionValue = description; - return Symbol::New(env, descriptionValue); - } +inline Symbol Symbol::New(napi_env env, String description) { + napi_value descriptionValue = description; + return Symbol::New(env, descriptionValue); +} - inline Symbol Symbol::New(napi_env env, napi_value description) { - napi_value value; - napi_status status = napi_create_symbol(env, description, &value); - NAPI_THROW_IF_FAILED(env, status, Symbol()); - return Symbol(env, value); - } +inline Symbol Symbol::New(napi_env env, napi_value description) { + napi_value value; + napi_status status = napi_create_symbol(env, description, &value); + NAPI_THROW_IF_FAILED(env, status, Symbol()); + return Symbol(env, value); +} - inline MaybeOrValue Symbol::WellKnown(napi_env env, - const std::string& name) { +inline MaybeOrValue Symbol::WellKnown(napi_env env, + const std::string& name) { + // No need to check if the return value is a symbol or undefined. + // Well known symbols are definite and it is an develop time error + // if the symbol does not exist. #if defined(NODE_ADDON_API_ENABLE_MAYBE) - Value symbol_obj; + Value symbol_obj; Value symbol_value; if (Napi::Env(env).Global().Get("Symbol").UnwrapTo(&symbol_obj) && symbol_obj.As().Get(name).UnwrapTo(&symbol_value)) { - return Just(symbol_value.As()); + return Just(symbol_value.UnsafeAs()); } return Nothing(); #else - return Napi::Env(env) - .Global() - .Get("Symbol") - .As() - .Get(name) - .As(); + return Napi::Env(env) + .Global() + .Get("Symbol") + .As() + .Get(name) + .UnsafeAs(); #endif - } +} - inline MaybeOrValue Symbol::For(napi_env env, - const std::string& description) { - napi_value descriptionValue = String::New(env, description); - return Symbol::For(env, descriptionValue); - } +inline MaybeOrValue Symbol::For(napi_env env, + const std::string& description) { + napi_value descriptionValue = String::New(env, description); + return Symbol::For(env, descriptionValue); +} - inline MaybeOrValue Symbol::For(napi_env env, const char* description) { - napi_value descriptionValue = String::New(env, description); - return Symbol::For(env, descriptionValue); - } +inline MaybeOrValue Symbol::For(napi_env env, const char* description) { + napi_value descriptionValue = String::New(env, description); + return Symbol::For(env, descriptionValue); +} - inline MaybeOrValue Symbol::For(napi_env env, String description) { - return Symbol::For(env, static_cast(description)); - } +inline MaybeOrValue Symbol::For(napi_env env, String description) { + return Symbol::For(env, static_cast(description)); +} - inline MaybeOrValue Symbol::For(napi_env env, napi_value description) { +inline MaybeOrValue Symbol::For(napi_env env, napi_value description) { #if defined(NODE_ADDON_API_ENABLE_MAYBE) - Value symbol_obj; + Value symbol_obj; Value symbol_for_value; Value symbol_value; if (Napi::Env(env).Global().Get("Symbol").UnwrapTo(&symbol_obj) && @@ -1249,132 +1414,132 @@ inline double Date::ValueOf() const { } return Nothing(); #else - Object symbol_obj = Napi::Env(env).Global().Get("Symbol").As(); - return symbol_obj.Get("for") - .As() - .Call(symbol_obj, {description}) - .As(); + Object symbol_obj = Napi::Env(env).Global().Get("Symbol").As(); + return symbol_obj.Get("for") + .As() + .Call(symbol_obj, {description}) + .As(); #endif - } +} - inline void Symbol::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Symbol::CheckCast", "empty value"); +inline void Symbol::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Symbol::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Symbol::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_symbol, "%d", "Symbol::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Symbol::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_symbol, "%d", "Symbol::CheckCast"); +} - inline Symbol::Symbol() : Name() {} +inline Symbol::Symbol() : Name() {} - inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {} +inline Symbol::Symbol(napi_env env, napi_value value) : Name(env, value) {} #endif //////////////////////////////////////////////////////////////////////////////// // Automagic value creation //////////////////////////////////////////////////////////////////////////////// - namespace details { - template - struct vf_number { - static Number From(napi_env env, T value) { - return Number::New(env, static_cast(value)); - } - }; - - template <> - struct vf_number { - static Boolean From(napi_env env, bool value) { - return Boolean::New(env, value); - } - }; - - struct vf_utf8_charp { - static String From(napi_env env, const char* value) { - return String::New(env, value); - } - }; - - struct vf_utf16_charp { - static String From(napi_env env, const char16_t* value) { - return String::New(env, value); - } - }; - struct vf_utf8_string { - static String From(napi_env env, const std::string& value) { - return String::New(env, value); - } - }; - - struct vf_utf16_string { - static String From(napi_env env, const std::u16string& value) { - return String::New(env, value); - } - }; - - template - struct vf_fallback { - static Value From(napi_env env, const T& value) { return Value(env, value); } - }; - - template - struct disjunction : std::false_type {}; - template - struct disjunction : B {}; - template - struct disjunction - : std::conditional>::type {}; - - template - struct can_make_string - : disjunction::type, - typename std::is_convertible::type, - typename std::is_convertible::type, - typename std::is_convertible::type> {}; - } // namespace details - - template - Value Value::From(napi_env env, const T& value) { - using Helper = typename std::conditional< - std::is_integral::value || std::is_floating_point::value, - details::vf_number, - typename std::conditional::value, - String, - details::vf_fallback>::type>::type; - return Helper::From(env, value); - } +namespace details { +template +struct vf_number { + static Number From(napi_env env, T value) { + return Number::New(env, static_cast(value)); + } +}; - template - String String::From(napi_env env, const T& value) { - struct Dummy {}; - using Helper = typename std::conditional< - std::is_convertible::value, - details::vf_utf8_charp, - typename std::conditional< - std::is_convertible::value, - details::vf_utf16_charp, - typename std::conditional< - std::is_convertible::value, - details::vf_utf8_string, - typename std::conditional< - std::is_convertible::value, - details::vf_utf16_string, - Dummy>::type>::type>::type>::type; - return Helper::From(env, value); - } +template <> +struct vf_number { + static Boolean From(napi_env env, bool value) { + return Boolean::New(env, value); + } +}; + +struct vf_utf8_charp { + static String From(napi_env env, const char* value) { + return String::New(env, value); + } +}; + +struct vf_utf16_charp { + static String From(napi_env env, const char16_t* value) { + return String::New(env, value); + } +}; +struct vf_utf8_string { + static String From(napi_env env, const std::string& value) { + return String::New(env, value); + } +}; + +struct vf_utf16_string { + static String From(napi_env env, const std::u16string& value) { + return String::New(env, value); + } +}; + +template +struct vf_fallback { + static Value From(napi_env env, const T& value) { return Value(env, value); } +}; + +template +struct disjunction : std::false_type {}; +template +struct disjunction : B {}; +template +struct disjunction + : std::conditional>::type {}; + +template +struct can_make_string + : disjunction::type, + typename std::is_convertible::type, + typename std::is_convertible::type, + typename std::is_convertible::type> {}; +} // namespace details + +template +Value Value::From(napi_env env, const T& value) { + using Helper = typename std::conditional< + std::is_integral::value || std::is_floating_point::value, + details::vf_number, + typename std::conditional::value, + String, + details::vf_fallback>::type>::type; + return Helper::From(env, value); +} + +template +String String::From(napi_env env, const T& value) { + struct Dummy {}; + using Helper = typename std::conditional< + std::is_convertible::value, + details::vf_utf8_charp, + typename std::conditional< + std::is_convertible::value, + details::vf_utf16_charp, + typename std::conditional< + std::is_convertible::value, + details::vf_utf8_string, + typename std::conditional< + std::is_convertible::value, + details::vf_utf16_string, + Dummy>::type>::type>::type>::type; + return Helper::From(env, value); +} //////////////////////////////////////////////////////////////////////////////// // TypeTaggable class //////////////////////////////////////////////////////////////////////////////// - inline TypeTaggable::TypeTaggable() : Value() {} +inline TypeTaggable::TypeTaggable() : Value() {} - inline TypeTaggable::TypeTaggable(napi_env _env, napi_value _value) - : Value(_env, _value) {} +inline TypeTaggable::TypeTaggable(napi_env _env, napi_value _value) + : Value(_env, _value) {} #if NAPI_VERSION >= 8 - inline void TypeTaggable::TypeTag(const napi_type_tag* type_tag) const { +inline void TypeTaggable::TypeTag(const napi_type_tag* type_tag) const { napi_status status = napi_type_tag_object(_env, _value, type_tag); NAPI_THROW_IF_FAILED_VOID(_env, status); } @@ -1393,305 +1558,313 @@ inline bool TypeTaggable::CheckTypeTag(const napi_type_tag* type_tag) const { // Object class //////////////////////////////////////////////////////////////////////////////// - template - inline Object::PropertyLValue::operator Value() const { - MaybeOrValue val = Object(_env, _object).Get(_key); +template +inline Object::PropertyLValue::operator Value() const { + MaybeOrValue val = Object(_env, _object).Get(_key); #ifdef NODE_ADDON_API_ENABLE_MAYBE - return val.Unwrap(); + return val.Unwrap(); #else - return val; + return val; #endif - } +} - template - template - inline Object::PropertyLValue& Object::PropertyLValue::operator=( - ValueType value) { +template +template +inline Object::PropertyLValue& Object::PropertyLValue::operator=( + ValueType value) { #ifdef NODE_ADDON_API_ENABLE_MAYBE - MaybeOrValue result = + MaybeOrValue result = #endif - Object(_env, _object).Set(_key, value); + Object(_env, _object).Set(_key, value); #ifdef NODE_ADDON_API_ENABLE_MAYBE - result.Unwrap(); + result.Unwrap(); #endif - return *this; - } + return *this; +} - template - inline Object::PropertyLValue::PropertyLValue(Object object, Key key) - : _env(object.Env()), _object(object), _key(key) {} +template +inline Value Object::PropertyLValue::AsValue() const { + return Value(*this); +} - inline Object Object::New(napi_env env) { - napi_value value; - napi_status status = napi_create_object(env, &value); - NAPI_THROW_IF_FAILED(env, status, Object()); - return Object(env, value); - } +template +inline Object::PropertyLValue::PropertyLValue(Object object, Key key) + : _env(object.Env()), _object(object), _key(key) {} - inline void Object::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Object::CheckCast", "empty value"); +inline Object Object::New(napi_env env) { + napi_value value; + napi_status status = napi_create_object(env, &value); + NAPI_THROW_IF_FAILED(env, status, Object()); + return Object(env, value); +} - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_object, "%d", "Object::CheckCast"); - } +inline void Object::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Object::CheckCast", "empty value"); - inline Object::Object() : TypeTaggable() {} + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Object::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK(type == napi_object || type == napi_function, + "Object::CheckCast", + "Expect napi_object or napi_function, but got %d.", + type); +} - inline Object::Object(napi_env env, napi_value value) - : TypeTaggable(env, value) {} +inline Object::Object() : TypeTaggable() {} - inline Object::PropertyLValue Object::operator[]( - const char* utf8name) { - return PropertyLValue(*this, utf8name); - } +inline Object::Object(napi_env env, napi_value value) + : TypeTaggable(env, value) {} - inline Object::PropertyLValue Object::operator[]( - const std::string& utf8name) { - return PropertyLValue(*this, utf8name); - } +inline Object::PropertyLValue Object::operator[]( + const char* utf8name) { + return PropertyLValue(*this, utf8name); +} - inline Object::PropertyLValue Object::operator[](uint32_t index) { - return PropertyLValue(*this, index); - } +inline Object::PropertyLValue Object::operator[]( + const std::string& utf8name) { + return PropertyLValue(*this, utf8name); +} - inline Object::PropertyLValue Object::operator[](Value index) const { - return PropertyLValue(*this, index); - } +inline Object::PropertyLValue Object::operator[](uint32_t index) { + return PropertyLValue(*this, index); +} - inline MaybeOrValue Object::operator[](const char* utf8name) const { - return Get(utf8name); - } +inline Object::PropertyLValue Object::operator[](Value index) const { + return PropertyLValue(*this, index); +} - inline MaybeOrValue Object::operator[]( - const std::string& utf8name) const { - return Get(utf8name); - } +inline MaybeOrValue Object::operator[](const char* utf8name) const { + return Get(utf8name); +} - inline MaybeOrValue Object::operator[](uint32_t index) const { - return Get(index); - } +inline MaybeOrValue Object::operator[]( + const std::string& utf8name) const { + return Get(utf8name); +} - inline MaybeOrValue Object::Has(napi_value key) const { - bool result; - napi_status status = napi_has_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::operator[](uint32_t index) const { + return Get(index); +} - inline MaybeOrValue Object::Has(Value key) const { - bool result; - napi_status status = napi_has_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::Has(napi_value key) const { + bool result; + napi_status status = napi_has_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::Has(const char* utf8name) const { - bool result; - napi_status status = napi_has_named_property(_env, _value, utf8name, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::Has(Value key) const { + bool result; + napi_status status = napi_has_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::Has(const std::string& utf8name) const { - return Has(utf8name.c_str()); - } +inline MaybeOrValue Object::Has(const char* utf8name) const { + bool result; + napi_status status = napi_has_named_property(_env, _value, utf8name, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::HasOwnProperty(napi_value key) const { - bool result; - napi_status status = napi_has_own_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::Has(const std::string& utf8name) const { + return Has(utf8name.c_str()); +} - inline MaybeOrValue Object::HasOwnProperty(Value key) const { - bool result; - napi_status status = napi_has_own_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::HasOwnProperty(napi_value key) const { + bool result; + napi_status status = napi_has_own_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::HasOwnProperty(const char* utf8name) const { - napi_value key; - napi_status status = - napi_create_string_utf8(_env, utf8name, std::strlen(utf8name), &key); - NAPI_MAYBE_THROW_IF_FAILED(_env, status, bool); - return HasOwnProperty(key); - } +inline MaybeOrValue Object::HasOwnProperty(Value key) const { + bool result; + napi_status status = napi_has_own_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::HasOwnProperty( - const std::string& utf8name) const { - return HasOwnProperty(utf8name.c_str()); - } +inline MaybeOrValue Object::HasOwnProperty(const char* utf8name) const { + napi_value key; + napi_status status = + napi_create_string_utf8(_env, utf8name, std::strlen(utf8name), &key); + NAPI_MAYBE_THROW_IF_FAILED(_env, status, bool); + return HasOwnProperty(key); +} - inline MaybeOrValue Object::Get(napi_value key) const { - napi_value result; - napi_status status = napi_get_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); - } +inline MaybeOrValue Object::HasOwnProperty( + const std::string& utf8name) const { + return HasOwnProperty(utf8name.c_str()); +} - inline MaybeOrValue Object::Get(Value key) const { - napi_value result; - napi_status status = napi_get_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); - } +inline MaybeOrValue Object::Get(napi_value key) const { + napi_value result; + napi_status status = napi_get_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); +} - inline MaybeOrValue Object::Get(const char* utf8name) const { - napi_value result; - napi_status status = napi_get_named_property(_env, _value, utf8name, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); - } +inline MaybeOrValue Object::Get(Value key) const { + napi_value result; + napi_status status = napi_get_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); +} - inline MaybeOrValue Object::Get(const std::string& utf8name) const { - return Get(utf8name.c_str()); - } +inline MaybeOrValue Object::Get(const char* utf8name) const { + napi_value result; + napi_status status = napi_get_named_property(_env, _value, utf8name, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, result), Value); +} - template - inline MaybeOrValue Object::Set(napi_value key, - const ValueType& value) const { - napi_status status = - napi_set_property(_env, _value, key, Value::From(_env, value)); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +inline MaybeOrValue Object::Get(const std::string& utf8name) const { + return Get(utf8name.c_str()); +} - template - inline MaybeOrValue Object::Set(Value key, const ValueType& value) const { - napi_status status = - napi_set_property(_env, _value, key, Value::From(_env, value)); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +template +inline MaybeOrValue Object::Set(napi_value key, + const ValueType& value) const { + napi_status status = + napi_set_property(_env, _value, key, Value::From(_env, value)); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - template - inline MaybeOrValue Object::Set(const char* utf8name, - const ValueType& value) const { - napi_status status = - napi_set_named_property(_env, _value, utf8name, Value::From(_env, value)); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +template +inline MaybeOrValue Object::Set(Value key, const ValueType& value) const { + napi_status status = + napi_set_property(_env, _value, key, Value::From(_env, value)); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - template - inline MaybeOrValue Object::Set(const std::string& utf8name, - const ValueType& value) const { - return Set(utf8name.c_str(), value); - } +template +inline MaybeOrValue Object::Set(const char* utf8name, + const ValueType& value) const { + napi_status status = + napi_set_named_property(_env, _value, utf8name, Value::From(_env, value)); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - inline MaybeOrValue Object::Delete(napi_value key) const { - bool result; - napi_status status = napi_delete_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +template +inline MaybeOrValue Object::Set(const std::string& utf8name, + const ValueType& value) const { + return Set(utf8name.c_str(), value); +} - inline MaybeOrValue Object::Delete(Value key) const { - bool result; - napi_status status = napi_delete_property(_env, _value, key, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::Delete(napi_value key) const { + bool result; + napi_status status = napi_delete_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::Delete(const char* utf8name) const { - return Delete(String::New(_env, utf8name)); - } +inline MaybeOrValue Object::Delete(Value key) const { + bool result; + napi_status status = napi_delete_property(_env, _value, key, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::Delete(const std::string& utf8name) const { - return Delete(String::New(_env, utf8name)); - } +inline MaybeOrValue Object::Delete(const char* utf8name) const { + return Delete(String::New(_env, utf8name)); +} - inline MaybeOrValue Object::Has(uint32_t index) const { - bool result; - napi_status status = napi_has_element(_env, _value, index, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::Delete(const std::string& utf8name) const { + return Delete(String::New(_env, utf8name)); +} - inline MaybeOrValue Object::Get(uint32_t index) const { - napi_value value; - napi_status status = napi_get_element(_env, _value, index, &value); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, value), Value); - } +inline MaybeOrValue Object::Has(uint32_t index) const { + bool result; + napi_status status = napi_has_element(_env, _value, index, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - template - inline MaybeOrValue Object::Set(uint32_t index, - const ValueType& value) const { - napi_status status = - napi_set_element(_env, _value, index, Value::From(_env, value)); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +inline MaybeOrValue Object::Get(uint32_t index) const { + napi_value value; + napi_status status = napi_get_element(_env, _value, index, &value); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Value(_env, value), Value); +} - inline MaybeOrValue Object::Delete(uint32_t index) const { - bool result; - napi_status status = napi_delete_element(_env, _value, index, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +template +inline MaybeOrValue Object::Set(uint32_t index, + const ValueType& value) const { + napi_status status = + napi_set_element(_env, _value, index, Value::From(_env, value)); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - inline MaybeOrValue Object::GetPropertyNames() const { - napi_value result; - napi_status status = napi_get_property_names(_env, _value, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Array(_env, result), Array); - } +inline MaybeOrValue Object::Delete(uint32_t index) const { + bool result; + napi_status status = napi_delete_element(_env, _value, index, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - inline MaybeOrValue Object::DefineProperty( - const PropertyDescriptor& property) const { - napi_status status = napi_define_properties( - _env, - _value, - 1, - reinterpret_cast(&property)); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +inline MaybeOrValue Object::GetPropertyNames() const { + napi_value result; + napi_status status = napi_get_property_names(_env, _value, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, Array(_env, result), Array); +} - inline MaybeOrValue Object::DefineProperties( - const std::initializer_list& properties) const { - napi_status status = napi_define_properties( - _env, - _value, - properties.size(), - reinterpret_cast(properties.begin())); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +inline MaybeOrValue Object::DefineProperty( + const PropertyDescriptor& property) const { + napi_status status = napi_define_properties( + _env, + _value, + 1, + reinterpret_cast(&property)); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - inline MaybeOrValue Object::DefineProperties( - const std::vector& properties) const { - napi_status status = napi_define_properties( - _env, - _value, - properties.size(), - reinterpret_cast(properties.data())); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); - } +inline MaybeOrValue Object::DefineProperties( + const std::initializer_list& properties) const { + napi_status status = napi_define_properties( + _env, + _value, + properties.size(), + reinterpret_cast(properties.begin())); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - inline MaybeOrValue Object::InstanceOf( - const Function& constructor) const { - bool result; - napi_status status = napi_instanceof(_env, _value, constructor, &result); - NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); - } +inline MaybeOrValue Object::DefineProperties( + const std::vector& properties) const { + napi_status status = napi_define_properties( + _env, + _value, + properties.size(), + reinterpret_cast(properties.data())); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); +} - template - inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) const { - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), nullptr}); - napi_status status = - details::AttachData::Wrapper>( - _env, *this, data, finalizeData); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED_VOID(_env, status); - } - } +inline MaybeOrValue Object::InstanceOf( + const Function& constructor) const { + bool result; + napi_status status = napi_instanceof(_env, _value, constructor, &result); + NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, result, bool); +} - template - inline void Object::AddFinalizer(Finalizer finalizeCallback, - T* data, - Hint* finalizeHint) const { - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), finalizeHint}); - napi_status status = details:: - AttachData::WrapperWithHint>( - _env, *this, data, finalizeData); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED_VOID(_env, status); - } - } +template +inline void Object::AddFinalizer(Finalizer finalizeCallback, T* data) const { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + napi_status status = + details::AttachData::Wrapper>( + _env, *this, data, finalizeData); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED_VOID(_env, status); + } +} + +template +inline void Object::AddFinalizer(Finalizer finalizeCallback, + T* data, + Hint* finalizeHint) const { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); + napi_status status = details:: + AttachData::WrapperWithHint>( + _env, *this, data, finalizeData); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED_VOID(_env, status); + } +} -#ifdef NAPI_CPP_EXCEPTIONS - inline Object::const_iterator::const_iterator(const Object* object, +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS +inline Object::const_iterator::const_iterator(const Object* object, const Type type) { _object = object; _keys = object->GetPropertyNames(); @@ -1765,10 +1938,10 @@ Object::iterator::operator*() { PropertyLValue value = (*_object)[key]; return {key, value}; } -#endif // NAPI_CPP_EXCEPTIONS +#endif // NODE_ADDON_API_CPP_EXCEPTIONS #if NAPI_VERSION >= 8 - inline MaybeOrValue Object::Freeze() const { +inline MaybeOrValue Object::Freeze() const { napi_status status = napi_object_freeze(_env, _value); NAPI_RETURN_OR_THROW_IF_FAILED(_env, status, status == napi_ok, bool); } @@ -1783,235 +1956,231 @@ inline MaybeOrValue Object::Seal() const { // External class //////////////////////////////////////////////////////////////////////////////// - template - inline External External::New(napi_env env, T* data) { - napi_value value; - napi_status status = - napi_create_external(env, data, nullptr, nullptr, &value); - NAPI_THROW_IF_FAILED(env, status, External()); - return External(env, value); - } +template +inline External External::New(napi_env env, T* data) { + napi_value value; + napi_status status = + napi_create_external(env, data, nullptr, nullptr, &value); + NAPI_THROW_IF_FAILED(env, status, External()); + return External(env, value); +} - template - template - inline External External::New(napi_env env, - T* data, - Finalizer finalizeCallback) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), nullptr}); - napi_status status = - napi_create_external(env, - data, - details::PostFinalizerWrapper< - details::FinalizeData::Wrapper>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, External()); - } - return External(env, value); - } +template +template +inline External External::New(napi_env env, + T* data, + Finalizer finalizeCallback) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + napi_status status = + napi_create_external(env, + data, + details::FinalizeData::Wrapper, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, External()); + } + return External(env, value); +} - template - template - inline External External::New(napi_env env, - T* data, - Finalizer finalizeCallback, - Hint* finalizeHint) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), finalizeHint}); - napi_status status = napi_create_external( - env, - data, - details::PostFinalizerWrapper< - details::FinalizeData::WrapperWithHint>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, External()); - } - return External(env, value); - } +template +template +inline External External::New(napi_env env, + T* data, + Finalizer finalizeCallback, + Hint* finalizeHint) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); + napi_status status = napi_create_external( + env, + data, + details::FinalizeData::WrapperWithHint, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, External()); + } + return External(env, value); +} - template - inline void External::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "External::CheckCast", "empty value"); +template +inline void External::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "External::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "External::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_external, "%d", "External::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "External::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_external, "%d", "External::CheckCast"); +} - template - inline External::External() : TypeTaggable() {} +template +inline External::External() : TypeTaggable() {} - template - inline External::External(napi_env env, napi_value value) - : TypeTaggable(env, value) {} +template +inline External::External(napi_env env, napi_value value) + : TypeTaggable(env, value) {} - template - inline T* External::Data() const { - void* data; - napi_status status = napi_get_value_external(_env, _value, &data); - NAPI_THROW_IF_FAILED(_env, status, nullptr); - return reinterpret_cast(data); - } +template +inline T* External::Data() const { + void* data; + napi_status status = napi_get_value_external(_env, _value, &data); + NAPI_THROW_IF_FAILED(_env, status, nullptr); + return reinterpret_cast(data); +} //////////////////////////////////////////////////////////////////////////////// // Array class //////////////////////////////////////////////////////////////////////////////// - inline Array Array::New(napi_env env) { - napi_value value; - napi_status status = napi_create_array(env, &value); - NAPI_THROW_IF_FAILED(env, status, Array()); - return Array(env, value); - } +inline Array Array::New(napi_env env) { + napi_value value; + napi_status status = napi_create_array(env, &value); + NAPI_THROW_IF_FAILED(env, status, Array()); + return Array(env, value); +} - inline Array Array::New(napi_env env, size_t length) { - napi_value value; - napi_status status = napi_create_array_with_length(env, length, &value); - NAPI_THROW_IF_FAILED(env, status, Array()); - return Array(env, value); - } +inline Array Array::New(napi_env env, size_t length) { + napi_value value; + napi_status status = napi_create_array_with_length(env, length, &value); + NAPI_THROW_IF_FAILED(env, status, Array()); + return Array(env, value); +} - inline void Array::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Array::CheckCast", "empty value"); +inline void Array::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Array::CheckCast", "empty value"); - bool result; - napi_status status = napi_is_array(env, value, &result); - NAPI_CHECK(status == napi_ok, "Array::CheckCast", "napi_is_array failed"); - NAPI_CHECK(result, "Array::CheckCast", "value is not array"); - } + bool result; + napi_status status = napi_is_array(env, value, &result); + NAPI_CHECK(status == napi_ok, "Array::CheckCast", "napi_is_array failed"); + NAPI_CHECK(result, "Array::CheckCast", "value is not array"); +} - inline Array::Array() : Object() {} +inline Array::Array() : Object() {} - inline Array::Array(napi_env env, napi_value value) : Object(env, value) {} +inline Array::Array(napi_env env, napi_value value) : Object(env, value) {} - inline uint32_t Array::Length() const { - uint32_t result; - napi_status status = napi_get_array_length(_env, _value, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; - } +inline uint32_t Array::Length() const { + uint32_t result; + napi_status status = napi_get_array_length(_env, _value, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; +} //////////////////////////////////////////////////////////////////////////////// // ArrayBuffer class //////////////////////////////////////////////////////////////////////////////// - inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) { - napi_value value; - void* data; - napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value); - NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); +inline ArrayBuffer ArrayBuffer::New(napi_env env, size_t byteLength) { + napi_value value; + void* data; + napi_status status = napi_create_arraybuffer(env, byteLength, &data, &value); + NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); - return ArrayBuffer(env, value); - } + return ArrayBuffer(env, value); +} #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - inline ArrayBuffer ArrayBuffer::New(napi_env env, - void* externalData, - size_t byteLength) { - napi_value value; - napi_status status = napi_create_external_arraybuffer( - env, externalData, byteLength, nullptr, nullptr, &value); - NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); - - return ArrayBuffer(env, value); - } +inline ArrayBuffer ArrayBuffer::New(napi_env env, + void* externalData, + size_t byteLength) { + napi_value value; + napi_status status = napi_create_external_arraybuffer( + env, externalData, byteLength, nullptr, nullptr, &value); + NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); - template - inline ArrayBuffer ArrayBuffer::New(napi_env env, - void* externalData, - size_t byteLength, - Finalizer finalizeCallback) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), nullptr}); - napi_status status = napi_create_external_arraybuffer( - env, - externalData, - byteLength, - details::PostFinalizerWrapper< - details::FinalizeData::Wrapper>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); - } + return ArrayBuffer(env, value); +} - return ArrayBuffer(env, value); - } +template +inline ArrayBuffer ArrayBuffer::New(napi_env env, + void* externalData, + size_t byteLength, + Finalizer finalizeCallback) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + napi_status status = napi_create_external_arraybuffer( + env, + externalData, + byteLength, + details::FinalizeData::Wrapper, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); + } - template - inline ArrayBuffer ArrayBuffer::New(napi_env env, - void* externalData, - size_t byteLength, - Finalizer finalizeCallback, - Hint* finalizeHint) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), finalizeHint}); - napi_status status = napi_create_external_arraybuffer( - env, - externalData, - byteLength, - details::PostFinalizerWrapper< - details::FinalizeData::WrapperWithHint>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); - } + return ArrayBuffer(env, value); +} - return ArrayBuffer(env, value); - } +template +inline ArrayBuffer ArrayBuffer::New(napi_env env, + void* externalData, + size_t byteLength, + Finalizer finalizeCallback, + Hint* finalizeHint) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); + napi_status status = napi_create_external_arraybuffer( + env, + externalData, + byteLength, + details::FinalizeData::WrapperWithHint, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, ArrayBuffer()); + } + + return ArrayBuffer(env, value); +} #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - inline void ArrayBuffer::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "ArrayBuffer::CheckCast", "empty value"); +inline void ArrayBuffer::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "ArrayBuffer::CheckCast", "empty value"); - bool result; - napi_status status = napi_is_arraybuffer(env, value, &result); - NAPI_CHECK(status == napi_ok, - "ArrayBuffer::CheckCast", - "napi_is_arraybuffer failed"); - NAPI_CHECK(result, "ArrayBuffer::CheckCast", "value is not arraybuffer"); - } + bool result; + napi_status status = napi_is_arraybuffer(env, value, &result); + NAPI_CHECK(status == napi_ok, + "ArrayBuffer::CheckCast", + "napi_is_arraybuffer failed"); + NAPI_CHECK(result, "ArrayBuffer::CheckCast", "value is not arraybuffer"); +} - inline ArrayBuffer::ArrayBuffer() : Object() {} +inline ArrayBuffer::ArrayBuffer() : Object() {} - inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value) - : Object(env, value) {} +inline ArrayBuffer::ArrayBuffer(napi_env env, napi_value value) + : Object(env, value) {} - inline void* ArrayBuffer::Data() { - void* data; - napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr); - NAPI_THROW_IF_FAILED(_env, status, nullptr); - return data; - } +inline void* ArrayBuffer::Data() { + void* data; + napi_status status = napi_get_arraybuffer_info(_env, _value, &data, nullptr); + NAPI_THROW_IF_FAILED(_env, status, nullptr); + return data; +} - inline size_t ArrayBuffer::ByteLength() { - size_t length; - napi_status status = - napi_get_arraybuffer_info(_env, _value, nullptr, &length); - NAPI_THROW_IF_FAILED(_env, status, 0); - return length; - } +inline size_t ArrayBuffer::ByteLength() { + size_t length; + napi_status status = + napi_get_arraybuffer_info(_env, _value, nullptr, &length); + NAPI_THROW_IF_FAILED(_env, status, 0); + return length; +} #if NAPI_VERSION >= 7 - inline bool ArrayBuffer::IsDetached() const { +inline bool ArrayBuffer::IsDetached() const { bool detached; napi_status status = napi_is_detached_arraybuffer(_env, _value, &detached); NAPI_THROW_IF_FAILED(_env, status, false); @@ -2027,947 +2196,943 @@ inline void ArrayBuffer::Detach() { //////////////////////////////////////////////////////////////////////////////// // DataView class //////////////////////////////////////////////////////////////////////////////// - inline DataView DataView::New(napi_env env, Napi::ArrayBuffer arrayBuffer) { - return New(env, arrayBuffer, 0, arrayBuffer.ByteLength()); - } - - inline DataView DataView::New(napi_env env, - Napi::ArrayBuffer arrayBuffer, - size_t byteOffset) { - if (byteOffset > arrayBuffer.ByteLength()) { - NAPI_THROW(RangeError::New( - env, "Start offset is outside the bounds of the buffer"), - DataView()); - } - return New( - env, arrayBuffer, byteOffset, arrayBuffer.ByteLength() - byteOffset); - } +inline DataView DataView::New(napi_env env, Napi::ArrayBuffer arrayBuffer) { + return New(env, arrayBuffer, 0, arrayBuffer.ByteLength()); +} - inline DataView DataView::New(napi_env env, - Napi::ArrayBuffer arrayBuffer, - size_t byteOffset, - size_t byteLength) { - if (byteOffset + byteLength > arrayBuffer.ByteLength()) { - NAPI_THROW(RangeError::New(env, "Invalid DataView length"), DataView()); - } - napi_value value; - napi_status status = - napi_create_dataview(env, byteLength, arrayBuffer, byteOffset, &value); - NAPI_THROW_IF_FAILED(env, status, DataView()); - return DataView(env, value); - } +inline DataView DataView::New(napi_env env, + Napi::ArrayBuffer arrayBuffer, + size_t byteOffset) { + if (byteOffset > arrayBuffer.ByteLength()) { + NAPI_THROW(RangeError::New( + env, "Start offset is outside the bounds of the buffer"), + DataView()); + } + return New( + env, arrayBuffer, byteOffset, arrayBuffer.ByteLength() - byteOffset); +} - inline void DataView::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "DataView::CheckCast", "empty value"); +inline DataView DataView::New(napi_env env, + Napi::ArrayBuffer arrayBuffer, + size_t byteOffset, + size_t byteLength) { + if (byteOffset + byteLength > arrayBuffer.ByteLength()) { + NAPI_THROW(RangeError::New(env, "Invalid DataView length"), DataView()); + } + napi_value value; + napi_status status = + napi_create_dataview(env, byteLength, arrayBuffer, byteOffset, &value); + NAPI_THROW_IF_FAILED(env, status, DataView()); + return DataView(env, value); +} - bool result; - napi_status status = napi_is_dataview(env, value, &result); - NAPI_CHECK( - status == napi_ok, "DataView::CheckCast", "napi_is_dataview failed"); - NAPI_CHECK(result, "DataView::CheckCast", "value is not dataview"); - } +inline void DataView::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "DataView::CheckCast", "empty value"); - inline DataView::DataView() : Object() {} + bool result; + napi_status status = napi_is_dataview(env, value, &result); + NAPI_CHECK( + status == napi_ok, "DataView::CheckCast", "napi_is_dataview failed"); + NAPI_CHECK(result, "DataView::CheckCast", "value is not dataview"); +} - inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) { - napi_status status = napi_get_dataview_info(_env, - _value /* dataView */, - &_length /* byteLength */, - &_data /* data */, - nullptr /* arrayBuffer */, - nullptr /* byteOffset */); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } +inline DataView::DataView() : Object() {} - inline Napi::ArrayBuffer DataView::ArrayBuffer() const { - napi_value arrayBuffer; - napi_status status = napi_get_dataview_info(_env, - _value /* dataView */, - nullptr /* byteLength */, - nullptr /* data */, - &arrayBuffer /* arrayBuffer */, - nullptr /* byteOffset */); - NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer()); - return Napi::ArrayBuffer(_env, arrayBuffer); - } +inline DataView::DataView(napi_env env, napi_value value) : Object(env, value) { + napi_status status = napi_get_dataview_info(_env, + _value /* dataView */, + &_length /* byteLength */, + &_data /* data */, + nullptr /* arrayBuffer */, + nullptr /* byteOffset */); + NAPI_THROW_IF_FAILED_VOID(_env, status); +} - inline size_t DataView::ByteOffset() const { - size_t byteOffset; - napi_status status = napi_get_dataview_info(_env, - _value /* dataView */, - nullptr /* byteLength */, - nullptr /* data */, - nullptr /* arrayBuffer */, - &byteOffset /* byteOffset */); - NAPI_THROW_IF_FAILED(_env, status, 0); - return byteOffset; - } +inline Napi::ArrayBuffer DataView::ArrayBuffer() const { + napi_value arrayBuffer; + napi_status status = napi_get_dataview_info(_env, + _value /* dataView */, + nullptr /* byteLength */, + nullptr /* data */, + &arrayBuffer /* arrayBuffer */, + nullptr /* byteOffset */); + NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer()); + return Napi::ArrayBuffer(_env, arrayBuffer); +} + +inline size_t DataView::ByteOffset() const { + size_t byteOffset; + napi_status status = napi_get_dataview_info(_env, + _value /* dataView */, + nullptr /* byteLength */, + nullptr /* data */, + nullptr /* arrayBuffer */, + &byteOffset /* byteOffset */); + NAPI_THROW_IF_FAILED(_env, status, 0); + return byteOffset; +} - inline size_t DataView::ByteLength() const { - return _length; - } +inline size_t DataView::ByteLength() const { + return _length; +} - inline void* DataView::Data() const { - return _data; - } +inline void* DataView::Data() const { + return _data; +} - inline float DataView::GetFloat32(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline float DataView::GetFloat32(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline double DataView::GetFloat64(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline double DataView::GetFloat64(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline int8_t DataView::GetInt8(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline int8_t DataView::GetInt8(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline int16_t DataView::GetInt16(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline int16_t DataView::GetInt16(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline int32_t DataView::GetInt32(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline int32_t DataView::GetInt32(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline uint8_t DataView::GetUint8(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline uint8_t DataView::GetUint8(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline uint16_t DataView::GetUint16(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline uint16_t DataView::GetUint16(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline uint32_t DataView::GetUint32(size_t byteOffset) const { - return ReadData(byteOffset); - } +inline uint32_t DataView::GetUint32(size_t byteOffset) const { + return ReadData(byteOffset); +} - inline void DataView::SetFloat32(size_t byteOffset, float value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetFloat32(size_t byteOffset, float value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetFloat64(size_t byteOffset, double value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetFloat64(size_t byteOffset, double value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetInt8(size_t byteOffset, int8_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetInt8(size_t byteOffset, int8_t value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetInt16(size_t byteOffset, int16_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetInt16(size_t byteOffset, int16_t value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetInt32(size_t byteOffset, int32_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetInt32(size_t byteOffset, int32_t value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetUint8(size_t byteOffset, uint8_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetUint8(size_t byteOffset, uint8_t value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetUint16(size_t byteOffset, uint16_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetUint16(size_t byteOffset, uint16_t value) const { + WriteData(byteOffset, value); +} - inline void DataView::SetUint32(size_t byteOffset, uint32_t value) const { - WriteData(byteOffset, value); - } +inline void DataView::SetUint32(size_t byteOffset, uint32_t value) const { + WriteData(byteOffset, value); +} - template - inline T DataView::ReadData(size_t byteOffset) const { - if (byteOffset + sizeof(T) > _length || - byteOffset + sizeof(T) < byteOffset) { // overflow - NAPI_THROW( - RangeError::New(_env, "Offset is outside the bounds of the DataView"), - 0); - } +template +inline T DataView::ReadData(size_t byteOffset) const { + if (byteOffset + sizeof(T) > _length || + byteOffset + sizeof(T) < byteOffset) { // overflow + NAPI_THROW( + RangeError::New(_env, "Offset is outside the bounds of the DataView"), + 0); + } - return *reinterpret_cast(static_cast(_data) + byteOffset); - } + return *reinterpret_cast(static_cast(_data) + byteOffset); +} - template - inline void DataView::WriteData(size_t byteOffset, T value) const { - if (byteOffset + sizeof(T) > _length || - byteOffset + sizeof(T) < byteOffset) { // overflow - NAPI_THROW_VOID( - RangeError::New(_env, "Offset is outside the bounds of the DataView")); - } +template +inline void DataView::WriteData(size_t byteOffset, T value) const { + if (byteOffset + sizeof(T) > _length || + byteOffset + sizeof(T) < byteOffset) { // overflow + NAPI_THROW_VOID( + RangeError::New(_env, "Offset is outside the bounds of the DataView")); + } - *reinterpret_cast(static_cast(_data) + byteOffset) = value; - } + *reinterpret_cast(static_cast(_data) + byteOffset) = value; +} //////////////////////////////////////////////////////////////////////////////// // TypedArray class //////////////////////////////////////////////////////////////////////////////// - inline void TypedArray::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "TypedArray::CheckCast", "empty value"); - - bool result; - napi_status status = napi_is_typedarray(env, value, &result); - NAPI_CHECK( - status == napi_ok, "TypedArray::CheckCast", "napi_is_typedarray failed"); - NAPI_CHECK(result, "TypedArray::CheckCast", "value is not typedarray"); - } +inline void TypedArray::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "TypedArray::CheckCast", "empty value"); - inline TypedArray::TypedArray() - : Object(), _type(napi_typedarray_type::napi_int8_array), _length(0) {} - - inline TypedArray::TypedArray(napi_env env, napi_value value) - : Object(env, value), - _type(napi_typedarray_type::napi_int8_array), - _length(0) { - if (value != nullptr) { - size_t len = 0; - napi_status status = - napi_get_typedarray_info(_env, - _value, - &const_cast(this)->_type, - &len, - nullptr, - nullptr, - nullptr); - NAPI_THROW_IF_FAILED_VOID(_env, status); - _length = len / ElementSize(); - } - } + bool result; + napi_status status = napi_is_typedarray(env, value, &result); + NAPI_CHECK( + status == napi_ok, "TypedArray::CheckCast", "napi_is_typedarray failed"); + NAPI_CHECK(result, "TypedArray::CheckCast", "value is not typedarray"); +} - inline TypedArray::TypedArray(napi_env env, - napi_value value, - napi_typedarray_type type, - size_t length) - : Object(env, value), _type(type), _length(length) {} +inline TypedArray::TypedArray() + : Object(), _type(napi_typedarray_type::napi_int8_array), _length(0) {} - inline napi_typedarray_type TypedArray::TypedArrayType() const { - return _type; - } +inline TypedArray::TypedArray(napi_env env, napi_value value) + : Object(env, value), + _type(napi_typedarray_type::napi_int8_array), + _length(0) { + if (value != nullptr) { + size_t len = 0; + napi_status status = + napi_get_typedarray_info(_env, + _value, + &const_cast(this)->_type, + &len, + nullptr, + nullptr, + nullptr); + NAPI_THROW_IF_FAILED_VOID(_env, status); + _length = len / ElementSize(); + } +} - inline uint8_t TypedArray::ElementSize() const { - switch (_type) { - case napi_int8_array: - case napi_uint8_array: - case napi_uint8_clamped_array: - return 1; - case napi_int16_array: - case napi_uint16_array: - return 2; - case napi_int32_array: - case napi_uint32_array: - case napi_float32_array: - return 4; - case napi_float64_array: +inline TypedArray::TypedArray(napi_env env, + napi_value value, + napi_typedarray_type type, + size_t length) + : Object(env, value), _type(type), _length(length) {} + +inline napi_typedarray_type TypedArray::TypedArrayType() const { + return _type; +} + +inline uint8_t TypedArray::ElementSize() const { + switch (_type) { + case napi_int8_array: + case napi_uint8_array: + case napi_uint8_clamped_array: + return 1; + case napi_int16_array: + case napi_uint16_array: + return 2; + case napi_int32_array: + case napi_uint32_array: + case napi_float32_array: + return 4; + case napi_float64_array: #if (NAPI_VERSION > 5) - case napi_bigint64_array: + case napi_bigint64_array: case napi_biguint64_array: #endif // (NAPI_VERSION > 5) - return 8; - default: - return 0; - } - } + return 8; + default: + return 0; + } +} - inline size_t TypedArray::ElementLength() const { - return _length; - } +inline size_t TypedArray::ElementLength() const { + return _length; +} - inline size_t TypedArray::ByteOffset() const { - size_t byteOffset; - napi_status status = napi_get_typedarray_info( - _env, _value, nullptr, nullptr, nullptr, nullptr, &byteOffset); - NAPI_THROW_IF_FAILED(_env, status, 0); - return byteOffset; - } +inline size_t TypedArray::ByteOffset() const { + size_t byteOffset; + napi_status status = napi_get_typedarray_info( + _env, _value, nullptr, nullptr, nullptr, nullptr, &byteOffset); + NAPI_THROW_IF_FAILED(_env, status, 0); + return byteOffset; +} - inline size_t TypedArray::ByteLength() const { - return ElementSize() * ElementLength(); - } +inline size_t TypedArray::ByteLength() const { + return ElementSize() * ElementLength(); +} - inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const { - napi_value arrayBuffer; - napi_status status = napi_get_typedarray_info( - _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr); - NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer()); - return Napi::ArrayBuffer(_env, arrayBuffer); - } +inline Napi::ArrayBuffer TypedArray::ArrayBuffer() const { + napi_value arrayBuffer; + napi_status status = napi_get_typedarray_info( + _env, _value, nullptr, nullptr, nullptr, &arrayBuffer, nullptr); + NAPI_THROW_IF_FAILED(_env, status, Napi::ArrayBuffer()); + return Napi::ArrayBuffer(_env, arrayBuffer); +} //////////////////////////////////////////////////////////////////////////////// // TypedArrayOf class //////////////////////////////////////////////////////////////////////////////// - template - inline void TypedArrayOf::CheckCast(napi_env env, napi_value value) { - TypedArray::CheckCast(env, value); - napi_typedarray_type type; - napi_status status = napi_get_typedarray_info( - env, value, &type, nullptr, nullptr, nullptr, nullptr); - NAPI_CHECK(status == napi_ok, - "TypedArrayOf::CheckCast", - "napi_is_typedarray failed"); - - NAPI_INTERNAL_CHECK( - (type == TypedArrayTypeForPrimitiveType() || - (type == napi_uint8_clamped_array && std::is_same::value)), - "TypedArrayOf::CheckCast", - "Array type must match the template parameter, (Uint8 arrays may " - "optionally have the \"clamped\" array type.), got %d.", - type); - } +template +inline void TypedArrayOf::CheckCast(napi_env env, napi_value value) { + TypedArray::CheckCast(env, value); + napi_typedarray_type type; + napi_status status = napi_get_typedarray_info( + env, value, &type, nullptr, nullptr, nullptr, nullptr); + NAPI_CHECK(status == napi_ok, + "TypedArrayOf::CheckCast", + "napi_is_typedarray failed"); + + NAPI_INTERNAL_CHECK( + (type == TypedArrayTypeForPrimitiveType() || + (type == napi_uint8_clamped_array && std::is_same::value)), + "TypedArrayOf::CheckCast", + "Array type must match the template parameter, (Uint8 arrays may " + "optionally have the \"clamped\" array type.), got %d.", + type); +} - template - inline TypedArrayOf TypedArrayOf::New(napi_env env, - size_t elementLength, - napi_typedarray_type type) { - Napi::ArrayBuffer arrayBuffer = - Napi::ArrayBuffer::New(env, elementLength * sizeof(T)); - return New(env, elementLength, arrayBuffer, 0, type); - } +template +inline TypedArrayOf TypedArrayOf::New(napi_env env, + size_t elementLength, + napi_typedarray_type type) { + Napi::ArrayBuffer arrayBuffer = + Napi::ArrayBuffer::New(env, elementLength * sizeof(T)); + return New(env, elementLength, arrayBuffer, 0, type); +} - template - inline TypedArrayOf TypedArrayOf::New(napi_env env, - size_t elementLength, - Napi::ArrayBuffer arrayBuffer, - size_t bufferOffset, - napi_typedarray_type type) { - napi_value value; - napi_status status = napi_create_typedarray( - env, type, elementLength, arrayBuffer, bufferOffset, &value); - NAPI_THROW_IF_FAILED(env, status, TypedArrayOf()); - - return TypedArrayOf( - env, - value, - type, - elementLength, - reinterpret_cast(reinterpret_cast(arrayBuffer.Data()) + - bufferOffset)); - } +template +inline TypedArrayOf TypedArrayOf::New(napi_env env, + size_t elementLength, + Napi::ArrayBuffer arrayBuffer, + size_t bufferOffset, + napi_typedarray_type type) { + napi_value value; + napi_status status = napi_create_typedarray( + env, type, elementLength, arrayBuffer, bufferOffset, &value); + NAPI_THROW_IF_FAILED(env, status, TypedArrayOf()); - template - inline TypedArrayOf::TypedArrayOf() : TypedArray(), _data(nullptr) {} - - template - inline TypedArrayOf::TypedArrayOf(napi_env env, napi_value value) - : TypedArray(env, value), _data(nullptr) { - napi_status status = napi_ok; - if (value != nullptr) { - void* data = nullptr; - status = napi_get_typedarray_info( - _env, _value, &_type, &_length, &data, nullptr, nullptr); - _data = static_cast(data); - } else { - _type = TypedArrayTypeForPrimitiveType(); - _length = 0; - } - NAPI_THROW_IF_FAILED_VOID(_env, status); - } + return TypedArrayOf( + env, + value, + type, + elementLength, + reinterpret_cast(reinterpret_cast(arrayBuffer.Data()) + + bufferOffset)); +} - template - inline TypedArrayOf::TypedArrayOf(napi_env env, - napi_value value, - napi_typedarray_type type, - size_t length, - T* data) - : TypedArray(env, value, type, length), _data(data) { - if (!(type == TypedArrayTypeForPrimitiveType() || - (type == napi_uint8_clamped_array && - std::is_same::value))) { - NAPI_THROW_VOID(TypeError::New( - env, - "Array type must match the template parameter. " - "(Uint8 arrays may optionally have the \"clamped\" array type.)")); - } - } +template +inline TypedArrayOf::TypedArrayOf() : TypedArray(), _data(nullptr) {} - template - inline T& TypedArrayOf::operator[](size_t index) { - return _data[index]; - } +template +inline TypedArrayOf::TypedArrayOf(napi_env env, napi_value value) + : TypedArray(env, value), _data(nullptr) { + napi_status status = napi_ok; + if (value != nullptr) { + void* data = nullptr; + status = napi_get_typedarray_info( + _env, _value, &_type, &_length, &data, nullptr, nullptr); + _data = static_cast(data); + } else { + _type = TypedArrayTypeForPrimitiveType(); + _length = 0; + } + NAPI_THROW_IF_FAILED_VOID(_env, status); +} - template - inline const T& TypedArrayOf::operator[](size_t index) const { - return _data[index]; - } +template +inline TypedArrayOf::TypedArrayOf(napi_env env, + napi_value value, + napi_typedarray_type type, + size_t length, + T* data) + : TypedArray(env, value, type, length), _data(data) { + if (!(type == TypedArrayTypeForPrimitiveType() || + (type == napi_uint8_clamped_array && + std::is_same::value))) { + NAPI_THROW_VOID(TypeError::New( + env, + "Array type must match the template parameter. " + "(Uint8 arrays may optionally have the \"clamped\" array type.)")); + } +} - template - inline T* TypedArrayOf::Data() { - return _data; - } +template +inline T& TypedArrayOf::operator[](size_t index) { + return _data[index]; +} - template - inline const T* TypedArrayOf::Data() const { - return _data; - } +template +inline const T& TypedArrayOf::operator[](size_t index) const { + return _data[index]; +} + +template +inline T* TypedArrayOf::Data() { + return _data; +} + +template +inline const T* TypedArrayOf::Data() const { + return _data; +} //////////////////////////////////////////////////////////////////////////////// // Function class //////////////////////////////////////////////////////////////////////////////// - template - inline napi_status CreateFunction(napi_env env, - const char* utf8name, - napi_callback cb, - CbData* data, - napi_value* result) { - napi_status status = - napi_create_function(env, utf8name, NAPI_AUTO_LENGTH, cb, data, result); - if (status == napi_ok) { - status = Napi::details::AttachData(env, *result, data); - } +template +inline napi_status CreateFunction(napi_env env, + const char* utf8name, + napi_callback cb, + CbData* data, + napi_value* result) { + napi_status status = + napi_create_function(env, utf8name, NAPI_AUTO_LENGTH, cb, data, result); + if (status == napi_ok) { + status = Napi::details::AttachData(env, *result, data); + } - return status; - } + return status; +} - template - inline Function Function::New(napi_env env, const char* utf8name, void* data) { - napi_value result = nullptr; - napi_status status = napi_create_function(env, - utf8name, - NAPI_AUTO_LENGTH, - details::TemplatedVoidCallback, - data, - &result); - NAPI_THROW_IF_FAILED(env, status, Function()); - return Function(env, result); - } +template +inline Function Function::New(napi_env env, const char* utf8name, void* data) { + napi_value result = nullptr; + napi_status status = napi_create_function(env, + utf8name, + NAPI_AUTO_LENGTH, + details::TemplatedVoidCallback, + data, + &result); + NAPI_THROW_IF_FAILED(env, status, Function()); + return Function(env, result); +} - template - inline Function Function::New(napi_env env, const char* utf8name, void* data) { - napi_value result = nullptr; - napi_status status = napi_create_function(env, - utf8name, - NAPI_AUTO_LENGTH, - details::TemplatedCallback, - data, - &result); - NAPI_THROW_IF_FAILED(env, status, Function()); - return Function(env, result); - } +template +inline Function Function::New(napi_env env, const char* utf8name, void* data) { + napi_value result = nullptr; + napi_status status = napi_create_function(env, + utf8name, + NAPI_AUTO_LENGTH, + details::TemplatedCallback, + data, + &result); + NAPI_THROW_IF_FAILED(env, status, Function()); + return Function(env, result); +} - template - inline Function Function::New(napi_env env, - const std::string& utf8name, - void* data) { - return Function::New(env, utf8name.c_str(), data); - } +template +inline Function Function::New(napi_env env, + const std::string& utf8name, + void* data) { + return Function::New(env, utf8name.c_str(), data); +} - template - inline Function Function::New(napi_env env, - const std::string& utf8name, - void* data) { - return Function::New(env, utf8name.c_str(), data); - } +template +inline Function Function::New(napi_env env, + const std::string& utf8name, + void* data) { + return Function::New(env, utf8name.c_str(), data); +} - template - inline Function Function::New(napi_env env, - Callable cb, - const char* utf8name, - void* data) { - using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr))); - using CbData = details::CallbackData; - auto callbackData = new CbData{std::move(cb), data}; +template +inline Function Function::New(napi_env env, + Callable cb, + const char* utf8name, + void* data) { + using ReturnType = decltype(cb(CallbackInfo(nullptr, nullptr))); + using CbData = details::CallbackData; + auto callbackData = new CbData{std::move(cb), data}; - napi_value value; - napi_status status = - CreateFunction(env, utf8name, CbData::Wrapper, callbackData, &value); - if (status != napi_ok) { - delete callbackData; - NAPI_THROW_IF_FAILED(env, status, Function()); - } + napi_value value; + napi_status status = + CreateFunction(env, utf8name, CbData::Wrapper, callbackData, &value); + if (status != napi_ok) { + delete callbackData; + NAPI_THROW_IF_FAILED(env, status, Function()); + } - return Function(env, value); - } + return Function(env, value); +} - template - inline Function Function::New(napi_env env, - Callable cb, - const std::string& utf8name, - void* data) { - return New(env, cb, utf8name.c_str(), data); - } +template +inline Function Function::New(napi_env env, + Callable cb, + const std::string& utf8name, + void* data) { + return New(env, cb, utf8name.c_str(), data); +} - inline void Function::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Function::CheckCast", "empty value"); +inline void Function::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Function::CheckCast", "empty value"); - napi_valuetype type; - napi_status status = napi_typeof(env, value, &type); - NAPI_CHECK(status == napi_ok, "Function::CheckCast", "napi_typeof failed"); - NAPI_INTERNAL_CHECK_EQ(type, napi_function, "%d", "Function::CheckCast"); - } + napi_valuetype type; + napi_status status = napi_typeof(env, value, &type); + NAPI_CHECK(status == napi_ok, "Function::CheckCast", "napi_typeof failed"); + NAPI_INTERNAL_CHECK_EQ(type, napi_function, "%d", "Function::CheckCast"); +} - inline Function::Function() : Object() {} +inline Function::Function() : Object() {} - inline Function::Function(napi_env env, napi_value value) - : Object(env, value) {} +inline Function::Function(napi_env env, napi_value value) + : Object(env, value) {} - inline MaybeOrValue Function::operator()( - const std::initializer_list& args) const { - return Call(Env().Undefined(), args); - } +inline MaybeOrValue Function::operator()( + const std::initializer_list& args) const { + return Call(Env().Undefined(), args); +} - inline MaybeOrValue Function::Call( - const std::initializer_list& args) const { - return Call(Env().Undefined(), args); - } +inline MaybeOrValue Function::Call( + const std::initializer_list& args) const { + return Call(Env().Undefined(), args); +} - inline MaybeOrValue Function::Call( - const std::vector& args) const { - return Call(Env().Undefined(), args); - } +inline MaybeOrValue Function::Call( + const std::vector& args) const { + return Call(Env().Undefined(), args); +} - inline MaybeOrValue Function::Call( - const std::vector& args) const { - return Call(Env().Undefined(), args); - } +inline MaybeOrValue Function::Call( + const std::vector& args) const { + return Call(Env().Undefined(), args); +} - inline MaybeOrValue Function::Call(size_t argc, - const napi_value* args) const { - return Call(Env().Undefined(), argc, args); - } +inline MaybeOrValue Function::Call(size_t argc, + const napi_value* args) const { + return Call(Env().Undefined(), argc, args); +} - inline MaybeOrValue Function::Call( - napi_value recv, const std::initializer_list& args) const { - return Call(recv, args.size(), args.begin()); - } +inline MaybeOrValue Function::Call( + napi_value recv, const std::initializer_list& args) const { + return Call(recv, args.size(), args.begin()); +} - inline MaybeOrValue Function::Call( - napi_value recv, const std::vector& args) const { - return Call(recv, args.size(), args.data()); - } +inline MaybeOrValue Function::Call( + napi_value recv, const std::vector& args) const { + return Call(recv, args.size(), args.data()); +} - inline MaybeOrValue Function::Call( - napi_value recv, const std::vector& args) const { - const size_t argc = args.size(); - const size_t stackArgsCount = 6; - napi_value stackArgs[stackArgsCount]; - std::vector heapArgs; - napi_value* argv; - if (argc <= stackArgsCount) { - argv = stackArgs; - } else { - heapArgs.resize(argc); - argv = heapArgs.data(); - } +inline MaybeOrValue Function::Call( + napi_value recv, const std::vector& args) const { + const size_t argc = args.size(); + const size_t stackArgsCount = 6; + napi_value stackArgs[stackArgsCount]; + std::vector heapArgs; + napi_value* argv; + if (argc <= stackArgsCount) { + argv = stackArgs; + } else { + heapArgs.resize(argc); + argv = heapArgs.data(); + } - for (size_t index = 0; index < argc; index++) { - argv[index] = static_cast(args[index]); - } + for (size_t index = 0; index < argc; index++) { + argv[index] = static_cast(args[index]); + } - return Call(recv, argc, argv); - } + return Call(recv, argc, argv); +} - inline MaybeOrValue Function::Call(napi_value recv, - size_t argc, - const napi_value* args) const { - napi_value result; - napi_status status = - napi_call_function(_env, recv, _value, argc, args, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Value(_env, result), Napi::Value); - } +inline MaybeOrValue Function::Call(napi_value recv, + size_t argc, + const napi_value* args) const { + napi_value result; + napi_status status = + napi_call_function(_env, recv, _value, argc, args, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Value(_env, result), Napi::Value); +} - inline MaybeOrValue Function::MakeCallback( - napi_value recv, - const std::initializer_list& args, - napi_async_context context) const { - return MakeCallback(recv, args.size(), args.begin(), context); - } +inline MaybeOrValue Function::MakeCallback( + napi_value recv, + const std::initializer_list& args, + napi_async_context context) const { + return MakeCallback(recv, args.size(), args.begin(), context); +} - inline MaybeOrValue Function::MakeCallback( - napi_value recv, - const std::vector& args, - napi_async_context context) const { - return MakeCallback(recv, args.size(), args.data(), context); - } +inline MaybeOrValue Function::MakeCallback( + napi_value recv, + const std::vector& args, + napi_async_context context) const { + return MakeCallback(recv, args.size(), args.data(), context); +} - inline MaybeOrValue Function::MakeCallback( - napi_value recv, - size_t argc, - const napi_value* args, - napi_async_context context) const { - napi_value result; - napi_status status = - napi_make_callback(_env, context, recv, _value, argc, args, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Value(_env, result), Napi::Value); - } +inline MaybeOrValue Function::MakeCallback( + napi_value recv, + size_t argc, + const napi_value* args, + napi_async_context context) const { + napi_value result; + napi_status status = + napi_make_callback(_env, context, recv, _value, argc, args, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Value(_env, result), Napi::Value); +} - inline MaybeOrValue Function::New( - const std::initializer_list& args) const { - return New(args.size(), args.begin()); - } +inline MaybeOrValue Function::New( + const std::initializer_list& args) const { + return New(args.size(), args.begin()); +} - inline MaybeOrValue Function::New( - const std::vector& args) const { - return New(args.size(), args.data()); - } +inline MaybeOrValue Function::New( + const std::vector& args) const { + return New(args.size(), args.data()); +} - inline MaybeOrValue Function::New(size_t argc, - const napi_value* args) const { - napi_value result; - napi_status status = napi_new_instance(_env, _value, argc, args, &result); - NAPI_RETURN_OR_THROW_IF_FAILED( - _env, status, Napi::Object(_env, result), Napi::Object); - } +inline MaybeOrValue Function::New(size_t argc, + const napi_value* args) const { + napi_value result; + napi_status status = napi_new_instance(_env, _value, argc, args, &result); + NAPI_RETURN_OR_THROW_IF_FAILED( + _env, status, Napi::Object(_env, result), Napi::Object); +} //////////////////////////////////////////////////////////////////////////////// // Promise class //////////////////////////////////////////////////////////////////////////////// - inline Promise::Deferred Promise::Deferred::New(napi_env env) { - return Promise::Deferred(env); - } +inline Promise::Deferred Promise::Deferred::New(napi_env env) { + return Promise::Deferred(env); +} - inline Promise::Deferred::Deferred(napi_env env) : _env(env) { - napi_status status = napi_create_promise(_env, &_deferred, &_promise); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } +inline Promise::Deferred::Deferred(napi_env env) : _env(env) { + napi_status status = napi_create_promise(_env, &_deferred, &_promise); + NAPI_THROW_IF_FAILED_VOID(_env, status); +} - inline Promise Promise::Deferred::Promise() const { - return Napi::Promise(_env, _promise); - } +inline Promise Promise::Deferred::Promise() const { + return Napi::Promise(_env, _promise); +} - inline Napi::Env Promise::Deferred::Env() const { - return Napi::Env(_env); - } +inline Napi::Env Promise::Deferred::Env() const { + return Napi::Env(_env); +} - inline void Promise::Deferred::Resolve(napi_value value) const { - napi_status status = napi_resolve_deferred(_env, _deferred, value); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } +inline void Promise::Deferred::Resolve(napi_value value) const { + napi_status status = napi_resolve_deferred(_env, _deferred, value); + NAPI_THROW_IF_FAILED_VOID(_env, status); +} - inline void Promise::Deferred::Reject(napi_value value) const { - napi_status status = napi_reject_deferred(_env, _deferred, value); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } +inline void Promise::Deferred::Reject(napi_value value) const { + napi_status status = napi_reject_deferred(_env, _deferred, value); + NAPI_THROW_IF_FAILED_VOID(_env, status); +} - inline void Promise::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Promise::CheckCast", "empty value"); +inline void Promise::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Promise::CheckCast", "empty value"); - bool result; - napi_status status = napi_is_promise(env, value, &result); - NAPI_CHECK(status == napi_ok, "Promise::CheckCast", "napi_is_promise failed"); - NAPI_CHECK(result, "Promise::CheckCast", "value is not promise"); - } + bool result; + napi_status status = napi_is_promise(env, value, &result); + NAPI_CHECK(status == napi_ok, "Promise::CheckCast", "napi_is_promise failed"); + NAPI_CHECK(result, "Promise::CheckCast", "value is not promise"); +} - inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {} +inline Promise::Promise(napi_env env, napi_value value) : Object(env, value) {} //////////////////////////////////////////////////////////////////////////////// // Buffer class //////////////////////////////////////////////////////////////////////////////// - template - inline Buffer Buffer::New(napi_env env, size_t length) { - napi_value value; - void* data; - napi_status status = - napi_create_buffer(env, length * sizeof(T), &data, &value); - NAPI_THROW_IF_FAILED(env, status, Buffer()); - return Buffer(env, value); - } +template +inline Buffer Buffer::New(napi_env env, size_t length) { + napi_value value; + void* data; + napi_status status = + napi_create_buffer(env, length * sizeof(T), &data, &value); + NAPI_THROW_IF_FAILED(env, status, Buffer()); + return Buffer(env, value); +} #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - template - inline Buffer Buffer::New(napi_env env, T* data, size_t length) { - napi_value value; - napi_status status = napi_create_external_buffer( - env, length * sizeof(T), data, nullptr, nullptr, &value); - NAPI_THROW_IF_FAILED(env, status, Buffer()); - return Buffer(env, value); - } +template +inline Buffer Buffer::New(napi_env env, T* data, size_t length) { + napi_value value; + napi_status status = napi_create_external_buffer( + env, length * sizeof(T), data, nullptr, nullptr, &value); + NAPI_THROW_IF_FAILED(env, status, Buffer()); + return Buffer(env, value); +} - template - template - inline Buffer Buffer::New(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), nullptr}); - napi_status status = napi_create_external_buffer( - env, - length * sizeof(T), - data, - details::PostFinalizerWrapper< - details::FinalizeData::Wrapper>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, Buffer()); - } - return Buffer(env, value); - } +template +template +inline Buffer Buffer::New(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + napi_status status = + napi_create_external_buffer(env, + length * sizeof(T), + data, + details::FinalizeData::Wrapper, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, Buffer()); + } + return Buffer(env, value); +} - template - template - inline Buffer Buffer::New(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback, - Hint* finalizeHint) { - napi_value value; - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), finalizeHint}); - napi_status status = napi_create_external_buffer( - env, - length * sizeof(T), - data, - details::PostFinalizerWrapper< - details::FinalizeData::WrapperWithHint>, - finalizeData, - &value); - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, Buffer()); - } - return Buffer(env, value); - } +template +template +inline Buffer Buffer::New(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback, + Hint* finalizeHint) { + napi_value value; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); + napi_status status = napi_create_external_buffer( + env, + length * sizeof(T), + data, + details::FinalizeData::WrapperWithHint, + finalizeData, + &value); + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, Buffer()); + } + return Buffer(env, value); +} #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - template - inline Buffer Buffer::NewOrCopy(napi_env env, T* data, size_t length) { +template +inline Buffer Buffer::NewOrCopy(napi_env env, T* data, size_t length) { #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - napi_value value; - napi_status status = napi_create_external_buffer( - env, length * sizeof(T), data, nullptr, nullptr, &value); - if (status == details::napi_no_external_buffers_allowed) { + napi_value value; + napi_status status = napi_create_external_buffer( + env, length * sizeof(T), data, nullptr, nullptr, &value); + if (status == details::napi_no_external_buffers_allowed) { #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - // If we can't create an external buffer, we'll just copy the data. - return Buffer::Copy(env, data, length); + // If we can't create an external buffer, we'll just copy the data. + return Buffer::Copy(env, data, length); #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - } - NAPI_THROW_IF_FAILED(env, status, Buffer()); - return Buffer(env, value); + } + NAPI_THROW_IF_FAILED(env, status, Buffer()); + return Buffer(env, value); #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - } +} - template - template - inline Buffer Buffer::NewOrCopy(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback) { - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), nullptr}); +template +template +inline Buffer Buffer::NewOrCopy(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback) { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - napi_value value; - napi_status status = napi_create_external_buffer( - env, - length * sizeof(T), - data, - details::PostFinalizerWrapper< - details::FinalizeData::Wrapper>, - finalizeData, - &value); - if (status == details::napi_no_external_buffers_allowed) { + napi_value value; + napi_status status = + napi_create_external_buffer(env, + length * sizeof(T), + data, + details::FinalizeData::Wrapper, + finalizeData, + &value); + if (status == details::napi_no_external_buffers_allowed) { #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - // If we can't create an external buffer, we'll just copy the data. - Buffer ret = Buffer::Copy(env, data, length); - details::FinalizeData::Wrapper(env, data, finalizeData); - return ret; + // If we can't create an external buffer, we'll just copy the data. + Buffer ret = Buffer::Copy(env, data, length); + details::FinalizeData::WrapperGC(env, data, finalizeData); + return ret; #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - } - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, Buffer()); - } - return Buffer(env, value); + } + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, Buffer()); + } + return Buffer(env, value); #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - } +} - template - template - inline Buffer Buffer::NewOrCopy(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback, - Hint* finalizeHint) { - details::FinalizeData* finalizeData = - new details::FinalizeData( - {std::move(finalizeCallback), finalizeHint}); +template +template +inline Buffer Buffer::NewOrCopy(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback, + Hint* finalizeHint) { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - napi_value value; - napi_status status = napi_create_external_buffer( - env, - length * sizeof(T), - data, - details::PostFinalizerWrapper< - details::FinalizeData::WrapperWithHint>, - finalizeData, - &value); - if (status == details::napi_no_external_buffers_allowed) { + napi_value value; + napi_status status = napi_create_external_buffer( + env, + length * sizeof(T), + data, + details::FinalizeData::WrapperWithHint, + finalizeData, + &value); + if (status == details::napi_no_external_buffers_allowed) { #endif - // If we can't create an external buffer, we'll just copy the data. - Buffer ret = Buffer::Copy(env, data, length); - details::FinalizeData::WrapperWithHint( - env, data, finalizeData); - return ret; + // If we can't create an external buffer, we'll just copy the data. + Buffer ret = Buffer::Copy(env, data, length); + details::FinalizeData::WrapperGCWithHint( + env, data, finalizeData); + return ret; #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - } - if (status != napi_ok) { - delete finalizeData; - NAPI_THROW_IF_FAILED(env, status, Buffer()); - } - return Buffer(env, value); + } + if (status != napi_ok) { + delete finalizeData; + NAPI_THROW_IF_FAILED(env, status, Buffer()); + } + return Buffer(env, value); #endif - } +} - template - inline Buffer Buffer::Copy(napi_env env, const T* data, size_t length) { - napi_value value; - napi_status status = - napi_create_buffer_copy(env, length * sizeof(T), data, nullptr, &value); - NAPI_THROW_IF_FAILED(env, status, Buffer()); - return Buffer(env, value); - } +template +inline Buffer Buffer::Copy(napi_env env, const T* data, size_t length) { + napi_value value; + napi_status status = + napi_create_buffer_copy(env, length * sizeof(T), data, nullptr, &value); + NAPI_THROW_IF_FAILED(env, status, Buffer()); + return Buffer(env, value); +} - template - inline void Buffer::CheckCast(napi_env env, napi_value value) { - NAPI_CHECK(value != nullptr, "Buffer::CheckCast", "empty value"); +template +inline void Buffer::CheckCast(napi_env env, napi_value value) { + NAPI_CHECK(value != nullptr, "Buffer::CheckCast", "empty value"); - bool result; - napi_status status = napi_is_buffer(env, value, &result); - NAPI_CHECK(status == napi_ok, "Buffer::CheckCast", "napi_is_buffer failed"); - NAPI_CHECK(result, "Buffer::CheckCast", "value is not buffer"); - } + bool result; + napi_status status = napi_is_buffer(env, value, &result); + NAPI_CHECK(status == napi_ok, "Buffer::CheckCast", "napi_is_buffer failed"); + NAPI_CHECK(result, "Buffer::CheckCast", "value is not buffer"); +} - template - inline Buffer::Buffer() : Object() {} +template +inline Buffer::Buffer() : Object() {} - template - inline Buffer::Buffer(napi_env env, napi_value value) - : Object(env, value) {} +template +inline Buffer::Buffer(napi_env env, napi_value value) + : Object(env, value) {} - template - inline size_t Buffer::Length() const { - void *data = nullptr; - size_t length = 0; - napi_status status = napi_get_buffer_info(_env, _value, &data, &length); - NAPI_THROW_IF_FAILED(_env, status, 0); - return length; - } +template +inline size_t Buffer::Length() const { + void *data = nullptr; + size_t length = 0; + napi_status status = napi_get_buffer_info(_env, _value, &data, &length); + NAPI_THROW_IF_FAILED(_env, status, 0); + return length; +} - template - inline T* Buffer::Data() const { - void *data = nullptr; - size_t length = 0; - napi_status status = napi_get_buffer_info(_env, _value, &data, &length); - NAPI_THROW_IF_FAILED(_env, status, 0); - return reinterpret_cast(data); - } +template +inline T* Buffer::Data() const { + void *data = nullptr; + size_t length = 0; + napi_status status = napi_get_buffer_info(_env, _value, &data, &length); + NAPI_THROW_IF_FAILED(_env, status, 0); + return reinterpret_cast(data); +} //////////////////////////////////////////////////////////////////////////////// // Error class //////////////////////////////////////////////////////////////////////////////// - inline Error Error::New(napi_env env) { - napi_status status; - napi_value error = nullptr; - bool is_exception_pending; - napi_extended_error_info last_error_info_copy; - - { - // We must retrieve the last error info before doing anything else because - // doing anything else will replace the last error info. - const napi_extended_error_info* last_error_info; - status = napi_get_last_error_info(env, &last_error_info); - NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info"); - - // All fields of the `napi_extended_error_info` structure gets reset in - // subsequent Node-API function calls on the same `env`. This includes a - // call to `napi_is_exception_pending()`. So here it is necessary to make a - // copy of the information as the `error_code` field is used later on. - memcpy(&last_error_info_copy, - last_error_info, - sizeof(napi_extended_error_info)); - } +inline Error Error::New(napi_env env) { + napi_status status; + napi_value error = nullptr; + bool is_exception_pending; + napi_extended_error_info last_error_info_copy; - status = napi_is_exception_pending(env, &is_exception_pending); - NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending"); + { + // We must retrieve the last error info before doing anything else because + // doing anything else will replace the last error info. + const napi_extended_error_info* last_error_info; + status = napi_get_last_error_info(env, &last_error_info); + NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_get_last_error_info"); + + // All fields of the `napi_extended_error_info` structure gets reset in + // subsequent Node-API function calls on the same `env`. This includes a + // call to `napi_is_exception_pending()`. So here it is necessary to make a + // copy of the information as the `error_code` field is used later on. + memcpy(&last_error_info_copy, + last_error_info, + sizeof(napi_extended_error_info)); + } - // A pending exception takes precedence over any internal error status. - if (is_exception_pending) { - status = napi_get_and_clear_last_exception(env, &error); - NAPI_FATAL_IF_FAILED( - status, "Error::New", "napi_get_and_clear_last_exception"); - } else { - const char* error_message = last_error_info_copy.error_message != nullptr - ? last_error_info_copy.error_message - : "Error in native callback"; - - napi_value message; - status = napi_create_string_utf8( - env, error_message, std::strlen(error_message), &message); - NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8"); - - switch (last_error_info_copy.error_code) { - case napi_object_expected: - case napi_string_expected: - case napi_boolean_expected: - case napi_number_expected: - status = napi_create_type_error(env, nullptr, message, &error); - break; - default: - status = napi_create_error(env, nullptr, message, &error); - break; - } - NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error"); - } + status = napi_is_exception_pending(env, &is_exception_pending); + NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_is_exception_pending"); - return Error(env, error); - } + // A pending exception takes precedence over any internal error status. + if (is_exception_pending) { + status = napi_get_and_clear_last_exception(env, &error); + NAPI_FATAL_IF_FAILED( + status, "Error::New", "napi_get_and_clear_last_exception"); + } else { + const char* error_message = last_error_info_copy.error_message != nullptr + ? last_error_info_copy.error_message + : "Error in native callback"; + + napi_value message; + status = napi_create_string_utf8( + env, error_message, std::strlen(error_message), &message); + NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_string_utf8"); + + switch (last_error_info_copy.error_code) { + case napi_object_expected: + case napi_string_expected: + case napi_boolean_expected: + case napi_number_expected: + status = napi_create_type_error(env, nullptr, message, &error); + break; + default: + status = napi_create_error(env, nullptr, message, &error); + break; + } + NAPI_FATAL_IF_FAILED(status, "Error::New", "napi_create_error"); + } - inline Error Error::New(napi_env env, const char* message) { - return Error::New( - env, message, std::strlen(message), napi_create_error); - } + return Error(env, error); +} - inline Error Error::New(napi_env env, const std::string& message) { - return Error::New( - env, message.c_str(), message.size(), napi_create_error); - } +inline Error Error::New(napi_env env, const char* message) { + return Error::New( + env, message, std::strlen(message), napi_create_error); +} - inline NAPI_NO_RETURN void Error::Fatal(const char* location, - const char* message) { - napi_fatal_error(location, NAPI_AUTO_LENGTH, message, NAPI_AUTO_LENGTH); - } +inline Error Error::New(napi_env env, const std::string& message) { + return Error::New( + env, message.c_str(), message.size(), napi_create_error); +} + +inline NAPI_NO_RETURN void Error::Fatal(const char* location, + const char* message) { + napi_fatal_error(location, NAPI_AUTO_LENGTH, message, NAPI_AUTO_LENGTH); +} - inline Error::Error() : ObjectReference() {} - - inline Error::Error(napi_env env, napi_value value) - : ObjectReference(env, nullptr) { - if (value != nullptr) { - // Attempting to create a reference on the error object. - // If it's not a Object/Function/Symbol, this call will return an error - // status. - napi_status status = napi_create_reference(env, value, 1, &_ref); - - if (status != napi_ok) { - napi_value wrappedErrorObj; - - // Create an error object - status = napi_create_object(env, &wrappedErrorObj); - NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_object"); - - // property flag that we attach to show the error object is wrapped - napi_property_descriptor wrapObjFlag = { - ERROR_WRAP_VALUE(), // Unique GUID identifier since Symbol isn't a - // viable option - nullptr, - nullptr, - nullptr, - nullptr, - Value::From(env, value), - napi_enumerable, - nullptr}; - - status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag); +inline Error::Error() : ObjectReference() {} + +inline Error::Error(napi_env env, napi_value value) + : ObjectReference(env, nullptr) { + if (value != nullptr) { + // Attempting to create a reference on the error object. + // If it's not a Object/Function/Symbol, this call will return an error + // status. + napi_status status = napi_create_reference(env, value, 1, &_ref); + + if (status != napi_ok) { + napi_value wrappedErrorObj; + + // Create an error object + status = napi_create_object(env, &wrappedErrorObj); + NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_object"); + + // property flag that we attach to show the error object is wrapped + napi_property_descriptor wrapObjFlag = { + ERROR_WRAP_VALUE(), // Unique GUID identifier since Symbol isn't a + // viable option + nullptr, + nullptr, + nullptr, + nullptr, + Value::From(env, value), + napi_enumerable, + nullptr}; + + status = napi_define_properties(env, wrappedErrorObj, 1, &wrapObjFlag); #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS - if (status == napi_pending_exception) { + if (status == napi_pending_exception) { // Test if the pending exception was reported because the environment is // shutting down. We assume that a status of napi_pending_exception // coupled with the absence of an actual pending exception means that @@ -2982,91 +3147,91 @@ inline void ArrayBuffer::Detach() { } } #endif // NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS - NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties"); - - // Create a reference on the newly wrapped object - status = napi_create_reference(env, wrappedErrorObj, 1, &_ref); - } + NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_define_properties"); - // Avoid infinite recursion in the failure case. - NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference"); - } + // Create a reference on the newly wrapped object + status = napi_create_reference(env, wrappedErrorObj, 1, &_ref); } - inline Object Error::Value() const { - if (_ref == nullptr) { - return Object(_env, nullptr); - } + // Avoid infinite recursion in the failure case. + NAPI_FATAL_IF_FAILED(status, "Error::Error", "napi_create_reference"); + } +} - napi_value refValue; - napi_status status = napi_get_reference_value(_env, _ref, &refValue); - NAPI_THROW_IF_FAILED(_env, status, Object()); - - napi_valuetype type; - status = napi_typeof(_env, refValue, &type); - NAPI_THROW_IF_FAILED(_env, status, Object()); - - // If refValue isn't a symbol, then we proceed to whether the refValue has the - // wrapped error flag - if (type != napi_symbol) { - // We are checking if the object is wrapped - bool isWrappedObject = false; - - status = napi_has_property(_env, - refValue, - String::From(_env, ERROR_WRAP_VALUE()), - &isWrappedObject); - - // Don't care about status - if (isWrappedObject) { - napi_value unwrappedValue; - status = napi_get_property(_env, - refValue, - String::From(_env, ERROR_WRAP_VALUE()), - &unwrappedValue); - NAPI_THROW_IF_FAILED(_env, status, Object()); - - return Object(_env, unwrappedValue); - } - } +inline Object Error::Value() const { + if (_ref == nullptr) { + return Object(_env, nullptr); + } - return Object(_env, refValue); + napi_value refValue; + napi_status status = napi_get_reference_value(_env, _ref, &refValue); + NAPI_THROW_IF_FAILED(_env, status, Object()); + + napi_valuetype type; + status = napi_typeof(_env, refValue, &type); + NAPI_THROW_IF_FAILED(_env, status, Object()); + + // If refValue isn't a symbol, then we proceed to whether the refValue has the + // wrapped error flag + if (type != napi_symbol) { + // We are checking if the object is wrapped + bool isWrappedObject = false; + + status = napi_has_property(_env, + refValue, + String::From(_env, ERROR_WRAP_VALUE()), + &isWrappedObject); + + // Don't care about status + if (isWrappedObject) { + napi_value unwrappedValue; + status = napi_get_property(_env, + refValue, + String::From(_env, ERROR_WRAP_VALUE()), + &unwrappedValue); + NAPI_THROW_IF_FAILED(_env, status, Object()); + + return Object(_env, unwrappedValue); } + } + + return Object(_env, refValue); +} - inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {} +inline Error::Error(Error&& other) : ObjectReference(std::move(other)) {} - inline Error& Error::operator=(Error&& other) { - static_cast*>(this)->operator=(std::move(other)); - return *this; - } +inline Error& Error::operator=(Error&& other) { + static_cast*>(this)->operator=(std::move(other)); + return *this; +} - inline Error::Error(const Error& other) : ObjectReference(other) {} +inline Error::Error(const Error& other) : ObjectReference(other) {} - inline Error& Error::operator=(const Error& other) { - Reset(); +inline Error& Error::operator=(const Error& other) { + Reset(); - _env = other.Env(); - HandleScope scope(_env); + _env = other.Env(); + HandleScope scope(_env); - napi_value value = other.Value(); - if (value != nullptr) { - napi_status status = napi_create_reference(_env, value, 1, &_ref); - NAPI_THROW_IF_FAILED(_env, status, *this); - } + napi_value value = other.Value(); + if (value != nullptr) { + napi_status status = napi_create_reference(_env, value, 1, &_ref); + NAPI_THROW_IF_FAILED(_env, status, *this); + } - return *this; - } + return *this; +} - inline const std::string& Error::Message() const NAPI_NOEXCEPT { - if (_message.size() == 0 && _env != nullptr) { -#ifdef NAPI_CPP_EXCEPTIONS +inline const std::string& Error::Message() const NAPI_NOEXCEPT { + if (_message.size() == 0 && _env != nullptr) { +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS try { _message = Get("message").As(); } catch (...) { // Catch all errors here, to include e.g. a std::bad_alloc from // the std::string::operator=, because this method may not throw. } -#else // NAPI_CPP_EXCEPTIONS +#else // NODE_ADDON_API_CPP_EXCEPTIONS #if defined(NODE_ADDON_API_ENABLE_MAYBE) Napi::Value message_val; if (Get("message").UnwrapTo(&message_val)) { @@ -3075,17 +3240,17 @@ inline void ArrayBuffer::Detach() { #else _message = Get("message").As(); #endif -#endif // NAPI_CPP_EXCEPTIONS -} -return _message; +#endif // NODE_ADDON_API_CPP_EXCEPTIONS + } + return _message; } // we created an object on the &_ref inline void Error::ThrowAsJavaScriptException() const { - HandleScope scope(_env); - if (!IsEmpty()) { + HandleScope scope(_env); + if (!IsEmpty()) { #ifdef NODE_API_SWALLOW_UNTHROWABLE_EXCEPTIONS - bool pendingException = false; + bool pendingException = false; // check if there is already a pending exception. If so don't try to throw a // new one as that is not allowed/possible @@ -3099,7 +3264,7 @@ inline void Error::ThrowAsJavaScriptException() const { status = napi_throw(_env, Value()); -#ifdef NAPI_EXPERIMENTAL +#if (NAPI_VERSION >= 10) napi_status expected_failure_mode = napi_cannot_run_js; #else napi_status expected_failure_mode = napi_pending_exception; @@ -3115,34 +3280,34 @@ inline void Error::ThrowAsJavaScriptException() const { status = napi_pending_exception; } #else - // We intentionally don't use `NAPI_THROW_*` macros here to ensure - // that there is no possible recursion as `ThrowAsJavaScriptException` - // is part of `NAPI_THROW_*` macro definition for noexcept. + // We intentionally don't use `NAPI_THROW_*` macros here to ensure + // that there is no possible recursion as `ThrowAsJavaScriptException` + // is part of `NAPI_THROW_*` macro definition for noexcept. - napi_status status = napi_throw(_env, Value()); + napi_status status = napi_throw(_env, Value()); #endif -#ifdef NAPI_CPP_EXCEPTIONS - if (status != napi_ok) { +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + if (status != napi_ok) { throw Error::New(_env); } -#else // NAPI_CPP_EXCEPTIONS - NAPI_FATAL_IF_FAILED( - status, "Error::ThrowAsJavaScriptException", "napi_throw"); -#endif // NAPI_CPP_EXCEPTIONS - } +#else // NODE_ADDON_API_CPP_EXCEPTIONS + NAPI_FATAL_IF_FAILED( + status, "Error::ThrowAsJavaScriptException", "napi_throw"); +#endif // NODE_ADDON_API_CPP_EXCEPTIONS + } } -#ifdef NAPI_CPP_EXCEPTIONS +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS inline const char* Error::what() const NAPI_NOEXCEPT { return Message().c_str(); } -#endif // NAPI_CPP_EXCEPTIONS +#endif // NODE_ADDON_API_CPP_EXCEPTIONS inline const char* Error::ERROR_WRAP_VALUE() NAPI_NOEXCEPT { -return "4bda9e7e-4913-4dbc-95de-891cbf66598e-errorVal"; + return "4bda9e7e-4913-4dbc-95de-891cbf66598e-errorVal"; } template @@ -3150,46 +3315,46 @@ inline TError Error::New(napi_env env, const char* message, size_t length, create_error_fn create_error) { - napi_value str; - napi_status status = napi_create_string_utf8(env, message, length, &str); - NAPI_THROW_IF_FAILED(env, status, TError()); + napi_value str; + napi_status status = napi_create_string_utf8(env, message, length, &str); + NAPI_THROW_IF_FAILED(env, status, TError()); - napi_value error; - status = create_error(env, nullptr, str, &error); - NAPI_THROW_IF_FAILED(env, status, TError()); + napi_value error; + status = create_error(env, nullptr, str, &error); + NAPI_THROW_IF_FAILED(env, status, TError()); - return TError(env, error); + return TError(env, error); } inline TypeError TypeError::New(napi_env env, const char* message) { - return Error::New( - env, message, std::strlen(message), napi_create_type_error); + return Error::New( + env, message, std::strlen(message), napi_create_type_error); } inline TypeError TypeError::New(napi_env env, const std::string& message) { - return Error::New( - env, message.c_str(), message.size(), napi_create_type_error); + return Error::New( + env, message.c_str(), message.size(), napi_create_type_error); } inline TypeError::TypeError() : Error() {} inline TypeError::TypeError(napi_env env, napi_value value) - : Error(env, value) {} + : Error(env, value) {} inline RangeError RangeError::New(napi_env env, const char* message) { - return Error::New( - env, message, std::strlen(message), napi_create_range_error); + return Error::New( + env, message, std::strlen(message), napi_create_range_error); } inline RangeError RangeError::New(napi_env env, const std::string& message) { - return Error::New( - env, message.c_str(), message.size(), napi_create_range_error); + return Error::New( + env, message.c_str(), message.size(), napi_create_range_error); } inline RangeError::RangeError() : Error() {} inline RangeError::RangeError(napi_env env, napi_value value) - : Error(env, value) {} + : Error(env, value) {} #if NAPI_VERSION > 8 inline SyntaxError SyntaxError::New(napi_env env, const char* message) { @@ -3215,181 +3380,189 @@ inline SyntaxError::SyntaxError(napi_env env, napi_value value) template inline Reference Reference::New(const T& value, uint32_t initialRefcount) { - napi_env env = value.Env(); - napi_value val = value; + napi_env env = value.Env(); + napi_value val = value; - if (val == nullptr) { - return Reference(env, nullptr); - } + if (val == nullptr) { + return Reference(env, nullptr); + } - napi_ref ref; - napi_status status = napi_create_reference(env, value, initialRefcount, &ref); - NAPI_THROW_IF_FAILED(env, status, Reference()); + napi_ref ref; + napi_status status = napi_create_reference(env, value, initialRefcount, &ref); + NAPI_THROW_IF_FAILED(env, status, Reference()); - return Reference(env, ref); + return Reference(env, ref); } template inline Reference::Reference() - : _env(nullptr), _ref(nullptr), _suppressDestruct(false) {} + : _env(nullptr), _ref(nullptr), _suppressDestruct(false) {} template inline Reference::Reference(napi_env env, napi_ref ref) - : _env(env), _ref(ref), _suppressDestruct(false) {} + : _env(env), _ref(ref), _suppressDestruct(false) {} template inline Reference::~Reference() { - if (_ref != nullptr) { - if (!_suppressDestruct) { - napi_delete_reference(_env, _ref); - } - - _ref = nullptr; + if (_ref != nullptr) { + if (!_suppressDestruct) { + // TODO(legendecas): napi_delete_reference should be invoked immediately. + // Fix this when https://github.com/nodejs/node/pull/55620 lands. +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + Env().PostFinalizer( + [](Napi::Env env, napi_ref ref) { napi_delete_reference(env, ref); }, + _ref); +#else + napi_delete_reference(_env, _ref); +#endif } + + _ref = nullptr; + } } template inline Reference::Reference(Reference&& other) - : _env(other._env), - _ref(other._ref), - _suppressDestruct(other._suppressDestruct) { - other._env = nullptr; - other._ref = nullptr; - other._suppressDestruct = false; + : _env(other._env), + _ref(other._ref), + _suppressDestruct(other._suppressDestruct) { + other._env = nullptr; + other._ref = nullptr; + other._suppressDestruct = false; } template inline Reference& Reference::operator=(Reference&& other) { - Reset(); - _env = other._env; - _ref = other._ref; - _suppressDestruct = other._suppressDestruct; - other._env = nullptr; - other._ref = nullptr; - other._suppressDestruct = false; - return *this; + Reset(); + _env = other._env; + _ref = other._ref; + _suppressDestruct = other._suppressDestruct; + other._env = nullptr; + other._ref = nullptr; + other._suppressDestruct = false; + return *this; } template inline Reference::Reference(const Reference& other) - : _env(other._env), _ref(nullptr), _suppressDestruct(false) { - HandleScope scope(_env); - - napi_value value = other.Value(); - if (value != nullptr) { - // Copying is a limited scenario (currently only used for Error object) and - // always creates a strong reference to the given value even if the incoming - // reference is weak. - napi_status status = napi_create_reference(_env, value, 1, &_ref); - NAPI_FATAL_IF_FAILED( - status, "Reference::Reference", "napi_create_reference"); - } + : _env(other._env), _ref(nullptr), _suppressDestruct(false) { + HandleScope scope(_env); + + napi_value value = other.Value(); + if (value != nullptr) { + // Copying is a limited scenario (currently only used for Error object) and + // always creates a strong reference to the given value even if the incoming + // reference is weak. + napi_status status = napi_create_reference(_env, value, 1, &_ref); + NAPI_FATAL_IF_FAILED( + status, "Reference::Reference", "napi_create_reference"); + } } template inline Reference::operator napi_ref() const { - return _ref; + return _ref; } template inline bool Reference::operator==(const Reference& other) const { - HandleScope scope(_env); - return this->Value().StrictEquals(other.Value()); + HandleScope scope(_env); + return this->Value().StrictEquals(other.Value()); } template inline bool Reference::operator!=(const Reference& other) const { - return !this->operator==(other); + return !this->operator==(other); } template inline Napi::Env Reference::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } template inline bool Reference::IsEmpty() const { - return _ref == nullptr; + return _ref == nullptr; } template inline T Reference::Value() const { - if (_ref == nullptr) { - return T(_env, nullptr); - } + if (_ref == nullptr) { + return T(_env, nullptr); + } - napi_value value; - napi_status status = napi_get_reference_value(_env, _ref, &value); - NAPI_THROW_IF_FAILED(_env, status, T()); - return T(_env, value); + napi_value value; + napi_status status = napi_get_reference_value(_env, _ref, &value); + NAPI_THROW_IF_FAILED(_env, status, T()); + return T(_env, value); } template inline uint32_t Reference::Ref() const { - uint32_t result; - napi_status status = napi_reference_ref(_env, _ref, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; + uint32_t result; + napi_status status = napi_reference_ref(_env, _ref, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; } template inline uint32_t Reference::Unref() const { - uint32_t result; - napi_status status = napi_reference_unref(_env, _ref, &result); - NAPI_THROW_IF_FAILED(_env, status, 0); - return result; + uint32_t result; + napi_status status = napi_reference_unref(_env, _ref, &result); + NAPI_THROW_IF_FAILED(_env, status, 0); + return result; } template inline void Reference::Reset() { - if (_ref != nullptr) { - napi_status status = napi_delete_reference(_env, _ref); - NAPI_THROW_IF_FAILED_VOID(_env, status); - _ref = nullptr; - } + if (_ref != nullptr) { + napi_status status = napi_delete_reference(_env, _ref); + NAPI_THROW_IF_FAILED_VOID(_env, status); + _ref = nullptr; + } } template inline void Reference::Reset(const T& value, uint32_t refcount) { - Reset(); - _env = value.Env(); + Reset(); + _env = value.Env(); - napi_value val = value; - if (val != nullptr) { - napi_status status = napi_create_reference(_env, value, refcount, &_ref); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } + napi_value val = value; + if (val != nullptr) { + napi_status status = napi_create_reference(_env, value, refcount, &_ref); + NAPI_THROW_IF_FAILED_VOID(_env, status); + } } template inline void Reference::SuppressDestruct() { - _suppressDestruct = true; + _suppressDestruct = true; } template inline Reference Weak(T value) { - return Reference::New(value, 0); + return Reference::New(value, 0); } inline ObjectReference Weak(Object value) { - return Reference::New(value, 0); + return Reference::New(value, 0); } inline FunctionReference Weak(Function value) { - return Reference::New(value, 0); + return Reference::New(value, 0); } template inline Reference Persistent(T value) { - return Reference::New(value, 1); + return Reference::New(value, 1); } inline ObjectReference Persistent(Object value) { - return Reference::New(value, 1); + return Reference::New(value, 1); } inline FunctionReference Persistent(Function value) { - return Reference::New(value, 1); + return Reference::New(value, 1); } //////////////////////////////////////////////////////////////////////////////// @@ -3399,171 +3572,171 @@ inline FunctionReference Persistent(Function value) { inline ObjectReference::ObjectReference() : Reference() {} inline ObjectReference::ObjectReference(napi_env env, napi_ref ref) - : Reference(env, ref) {} + : Reference(env, ref) {} inline ObjectReference::ObjectReference(Reference&& other) - : Reference(std::move(other)) {} + : Reference(std::move(other)) {} inline ObjectReference& ObjectReference::operator=(Reference&& other) { - static_cast*>(this)->operator=(std::move(other)); - return *this; + static_cast*>(this)->operator=(std::move(other)); + return *this; } inline ObjectReference::ObjectReference(ObjectReference&& other) - : Reference(std::move(other)) {} + : Reference(std::move(other)) {} inline ObjectReference& ObjectReference::operator=(ObjectReference&& other) { - static_cast*>(this)->operator=(std::move(other)); - return *this; + static_cast*>(this)->operator=(std::move(other)); + return *this; } inline ObjectReference::ObjectReference(const ObjectReference& other) - : Reference(other) {} + : Reference(other) {} inline MaybeOrValue ObjectReference::Get( - const char* utf8name) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Get(utf8name); + const char* utf8name) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Get(utf8name); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue ObjectReference::Get( - const std::string& utf8name) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Get(utf8name); + const std::string& utf8name) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Get(utf8name); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue ObjectReference::Set(const char* utf8name, napi_value value) const { - HandleScope scope(_env); - return Value().Set(utf8name, value); + HandleScope scope(_env); + return Value().Set(utf8name, value); } inline MaybeOrValue ObjectReference::Set(const char* utf8name, Napi::Value value) const { - HandleScope scope(_env); - return Value().Set(utf8name, value); + HandleScope scope(_env); + return Value().Set(utf8name, value); } inline MaybeOrValue ObjectReference::Set(const char* utf8name, const char* utf8value) const { - HandleScope scope(_env); - return Value().Set(utf8name, utf8value); + HandleScope scope(_env); + return Value().Set(utf8name, utf8value); } inline MaybeOrValue ObjectReference::Set(const char* utf8name, bool boolValue) const { - HandleScope scope(_env); - return Value().Set(utf8name, boolValue); + HandleScope scope(_env); + return Value().Set(utf8name, boolValue); } inline MaybeOrValue ObjectReference::Set(const char* utf8name, double numberValue) const { - HandleScope scope(_env); - return Value().Set(utf8name, numberValue); + HandleScope scope(_env); + return Value().Set(utf8name, numberValue); } inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, napi_value value) const { - HandleScope scope(_env); - return Value().Set(utf8name, value); + HandleScope scope(_env); + return Value().Set(utf8name, value); } inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, Napi::Value value) const { - HandleScope scope(_env); - return Value().Set(utf8name, value); + HandleScope scope(_env); + return Value().Set(utf8name, value); } inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, std::string& utf8value) const { - HandleScope scope(_env); - return Value().Set(utf8name, utf8value); + HandleScope scope(_env); + return Value().Set(utf8name, utf8value); } inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, bool boolValue) const { - HandleScope scope(_env); - return Value().Set(utf8name, boolValue); + HandleScope scope(_env); + return Value().Set(utf8name, boolValue); } inline MaybeOrValue ObjectReference::Set(const std::string& utf8name, double numberValue) const { - HandleScope scope(_env); - return Value().Set(utf8name, numberValue); + HandleScope scope(_env); + return Value().Set(utf8name, numberValue); } inline MaybeOrValue ObjectReference::Get(uint32_t index) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Get(index); + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Get(index); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue ObjectReference::Set(uint32_t index, napi_value value) const { - HandleScope scope(_env); - return Value().Set(index, value); + HandleScope scope(_env); + return Value().Set(index, value); } inline MaybeOrValue ObjectReference::Set(uint32_t index, Napi::Value value) const { - HandleScope scope(_env); - return Value().Set(index, value); + HandleScope scope(_env); + return Value().Set(index, value); } inline MaybeOrValue ObjectReference::Set(uint32_t index, const char* utf8value) const { - HandleScope scope(_env); - return Value().Set(index, utf8value); + HandleScope scope(_env); + return Value().Set(index, utf8value); } inline MaybeOrValue ObjectReference::Set( - uint32_t index, const std::string& utf8value) const { - HandleScope scope(_env); - return Value().Set(index, utf8value); + uint32_t index, const std::string& utf8value) const { + HandleScope scope(_env); + return Value().Set(index, utf8value); } inline MaybeOrValue ObjectReference::Set(uint32_t index, bool boolValue) const { - HandleScope scope(_env); - return Value().Set(index, boolValue); + HandleScope scope(_env); + return Value().Set(index, boolValue); } inline MaybeOrValue ObjectReference::Set(uint32_t index, double numberValue) const { - HandleScope scope(_env); - return Value().Set(index, numberValue); + HandleScope scope(_env); + return Value().Set(index, numberValue); } //////////////////////////////////////////////////////////////////////////////// @@ -3573,219 +3746,219 @@ inline MaybeOrValue ObjectReference::Set(uint32_t index, inline FunctionReference::FunctionReference() : Reference() {} inline FunctionReference::FunctionReference(napi_env env, napi_ref ref) - : Reference(env, ref) {} + : Reference(env, ref) {} inline FunctionReference::FunctionReference(Reference&& other) - : Reference(std::move(other)) {} + : Reference(std::move(other)) {} inline FunctionReference& FunctionReference::operator=( - Reference&& other) { - static_cast*>(this)->operator=(std::move(other)); - return *this; + Reference&& other) { + static_cast*>(this)->operator=(std::move(other)); + return *this; } inline FunctionReference::FunctionReference(FunctionReference&& other) - : Reference(std::move(other)) {} + : Reference(std::move(other)) {} inline FunctionReference& FunctionReference::operator=( - FunctionReference&& other) { - static_cast*>(this)->operator=(std::move(other)); - return *this; + FunctionReference&& other) { + static_cast*>(this)->operator=(std::move(other)); + return *this; } inline MaybeOrValue FunctionReference::operator()( - const std::initializer_list& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value()(args); + const std::initializer_list& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value()(args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::Call( - const std::initializer_list& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Call(args); + const std::initializer_list& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Call(args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::Call( - const std::vector& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Call(args); + const std::vector& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Call(args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::Call( - napi_value recv, const std::initializer_list& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Call(recv, args); + napi_value recv, const std::initializer_list& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Call(recv, args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::Call( - napi_value recv, const std::vector& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Call(recv, args); + napi_value recv, const std::vector& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Call(recv, args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::Call( - napi_value recv, size_t argc, const napi_value* args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().Call(recv, argc, args); + napi_value recv, size_t argc, const napi_value* args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().Call(recv, argc, args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::MakeCallback( - napi_value recv, - const std::initializer_list& args, - napi_async_context context) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().MakeCallback(recv, args, context); + napi_value recv, + const std::initializer_list& args, + napi_async_context context) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().MakeCallback(recv, args, context); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::MakeCallback( - napi_value recv, - const std::vector& args, - napi_async_context context) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().MakeCallback(recv, args, context); + napi_value recv, + const std::vector& args, + napi_async_context context) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().MakeCallback(recv, args, context); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::MakeCallback( - napi_value recv, - size_t argc, - const napi_value* args, - napi_async_context context) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = - Value().MakeCallback(recv, argc, args, context); + napi_value recv, + size_t argc, + const napi_value* args, + napi_async_context context) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = + Value().MakeCallback(recv, argc, args, context); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap())); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Value(); - } - return scope.Escape(result); + if (scope.Env().IsExceptionPending()) { + return Value(); + } + return scope.Escape(result); #endif } inline MaybeOrValue FunctionReference::New( - const std::initializer_list& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().New(args); + const std::initializer_list& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().New(args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap()).As()); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Object(); - } - return scope.Escape(result).As(); + if (scope.Env().IsExceptionPending()) { + return Object(); + } + return scope.Escape(result).As(); #endif } inline MaybeOrValue FunctionReference::New( - const std::vector& args) const { - EscapableHandleScope scope(_env); - MaybeOrValue result = Value().New(args); + const std::vector& args) const { + EscapableHandleScope scope(_env); + MaybeOrValue result = Value().New(args); #ifdef NODE_ADDON_API_ENABLE_MAYBE - if (result.IsJust()) { + if (result.IsJust()) { return Just(scope.Escape(result.Unwrap()).As()); } return result; #else - if (scope.Env().IsExceptionPending()) { - return Object(); - } - return scope.Escape(result).As(); + if (scope.Env().IsExceptionPending()) { + return Object(); + } + return scope.Escape(result).As(); #endif } @@ -3794,74 +3967,74 @@ inline MaybeOrValue FunctionReference::New( //////////////////////////////////////////////////////////////////////////////// inline CallbackInfo::CallbackInfo(napi_env env, napi_callback_info info) - : _env(env), - _info(info), - _this(nullptr), - _dynamicArgs(nullptr), - _data(nullptr) { - _argc = _staticArgCount; - _argv = _staticArgs; - napi_status status = - napi_get_cb_info(env, info, &_argc, _argv, &_this, &_data); - NAPI_THROW_IF_FAILED_VOID(_env, status); + : _env(env), + _info(info), + _this(nullptr), + _dynamicArgs(nullptr), + _data(nullptr) { + _argc = _staticArgCount; + _argv = _staticArgs; + napi_status status = + napi_get_cb_info(env, info, &_argc, _argv, &_this, &_data); + NAPI_THROW_IF_FAILED_VOID(_env, status); - if (_argc > _staticArgCount) { - // Use either a fixed-size array (on the stack) or a dynamically-allocated - // array (on the heap) depending on the number of args. - _dynamicArgs = new napi_value[_argc]; - _argv = _dynamicArgs; + if (_argc > _staticArgCount) { + // Use either a fixed-size array (on the stack) or a dynamically-allocated + // array (on the heap) depending on the number of args. + _dynamicArgs = new napi_value[_argc]; + _argv = _dynamicArgs; - status = napi_get_cb_info(env, info, &_argc, _argv, nullptr, nullptr); - NAPI_THROW_IF_FAILED_VOID(_env, status); - } + status = napi_get_cb_info(env, info, &_argc, _argv, nullptr, nullptr); + NAPI_THROW_IF_FAILED_VOID(_env, status); + } } inline CallbackInfo::~CallbackInfo() { - if (_dynamicArgs != nullptr) { - delete[] _dynamicArgs; - } + if (_dynamicArgs != nullptr) { + delete[] _dynamicArgs; + } } inline CallbackInfo::operator napi_callback_info() const { - return _info; + return _info; } inline Value CallbackInfo::NewTarget() const { - napi_value newTarget; - napi_status status = napi_get_new_target(_env, _info, &newTarget); - NAPI_THROW_IF_FAILED(_env, status, Value()); - return Value(_env, newTarget); + napi_value newTarget; + napi_status status = napi_get_new_target(_env, _info, &newTarget); + NAPI_THROW_IF_FAILED(_env, status, Value()); + return Value(_env, newTarget); } inline bool CallbackInfo::IsConstructCall() const { - return !NewTarget().IsEmpty(); + return !NewTarget().IsEmpty(); } inline Napi::Env CallbackInfo::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } inline size_t CallbackInfo::Length() const { - return _argc; + return _argc; } inline const Value CallbackInfo::operator[](size_t index) const { - return index < _argc ? Value(_env, _argv[index]) : Env().Undefined(); + return index < _argc ? Value(_env, _argv[index]) : Env().Undefined(); } inline Value CallbackInfo::This() const { - if (_this == nullptr) { - return Env().Undefined(); - } - return Object(_env, _this); + if (_this == nullptr) { + return Env().Undefined(); + } + return Object(_env, _this); } inline void* CallbackInfo::Data() const { - return _data; + return _data; } inline void CallbackInfo::SetData(void* data) { - _data = data; + _data = data; } //////////////////////////////////////////////////////////////////////////////// @@ -3870,301 +4043,301 @@ inline void CallbackInfo::SetData(void* data) { template PropertyDescriptor PropertyDescriptor::Accessor( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = details::TemplatedCallback; - desc.attributes = attributes; - desc.data = data; + desc.utf8name = utf8name; + desc.getter = details::TemplatedCallback; + desc.attributes = attributes; + desc.data = data; - return desc; + return desc; } template PropertyDescriptor PropertyDescriptor::Accessor( - const std::string& utf8name, - napi_property_attributes attributes, - void* data) { - return Accessor(utf8name.c_str(), attributes, data); + const std::string& utf8name, + napi_property_attributes attributes, + void* data) { + return Accessor(utf8name.c_str(), attributes, data); } template PropertyDescriptor PropertyDescriptor::Accessor( - Name name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); + Name name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = details::TemplatedCallback; - desc.attributes = attributes; - desc.data = data; + desc.name = name; + desc.getter = details::TemplatedCallback; + desc.attributes = attributes; + desc.data = data; - return desc; + return desc; } template + typename PropertyDescriptor::SetterCallback Setter> PropertyDescriptor PropertyDescriptor::Accessor( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = details::TemplatedCallback; - desc.setter = details::TemplatedVoidCallback; - desc.attributes = attributes; - desc.data = data; + desc.utf8name = utf8name; + desc.getter = details::TemplatedCallback; + desc.setter = details::TemplatedVoidCallback; + desc.attributes = attributes; + desc.data = data; - return desc; + return desc; } template + typename PropertyDescriptor::SetterCallback Setter> PropertyDescriptor PropertyDescriptor::Accessor( - const std::string& utf8name, - napi_property_attributes attributes, - void* data) { - return Accessor(utf8name.c_str(), attributes, data); + const std::string& utf8name, + napi_property_attributes attributes, + void* data) { + return Accessor(utf8name.c_str(), attributes, data); } template + typename PropertyDescriptor::SetterCallback Setter> PropertyDescriptor PropertyDescriptor::Accessor( - Name name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); + Name name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = details::TemplatedCallback; - desc.setter = details::TemplatedVoidCallback; - desc.attributes = attributes; - desc.data = data; + desc.name = name; + desc.getter = details::TemplatedCallback; + desc.setter = details::TemplatedVoidCallback; + desc.attributes = attributes; + desc.data = data; - return desc; + return desc; } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - const char* utf8name, - Getter getter, - napi_property_attributes attributes, - void* data) { - using CbData = details::CallbackData; - auto callbackData = new CbData({getter, data}); - - napi_status status = AttachData(env, object, callbackData); - if (status != napi_ok) { - delete callbackData; - NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); - } + Napi::Env env, + Napi::Object object, + const char* utf8name, + Getter getter, + napi_property_attributes attributes, + void* data) { + using CbData = details::CallbackData; + auto callbackData = new CbData({getter, data}); + + napi_status status = AttachData(env, object, callbackData); + if (status != napi_ok) { + delete callbackData; + NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); + } - return PropertyDescriptor({utf8name, - nullptr, - nullptr, - CbData::Wrapper, - nullptr, - nullptr, - attributes, - callbackData}); + return PropertyDescriptor({utf8name, + nullptr, + nullptr, + CbData::Wrapper, + nullptr, + nullptr, + attributes, + callbackData}); } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Getter getter, - napi_property_attributes attributes, - void* data) { - return Accessor(env, object, utf8name.c_str(), getter, attributes, data); + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Getter getter, + napi_property_attributes attributes, + void* data) { + return Accessor(env, object, utf8name.c_str(), getter, attributes, data); } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - Name name, - Getter getter, - napi_property_attributes attributes, - void* data) { - using CbData = details::CallbackData; - auto callbackData = new CbData({getter, data}); - - napi_status status = AttachData(env, object, callbackData); - if (status != napi_ok) { - delete callbackData; - NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); - } + Napi::Env env, + Napi::Object object, + Name name, + Getter getter, + napi_property_attributes attributes, + void* data) { + using CbData = details::CallbackData; + auto callbackData = new CbData({getter, data}); + + napi_status status = AttachData(env, object, callbackData); + if (status != napi_ok) { + delete callbackData; + NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); + } - return PropertyDescriptor({nullptr, - name, - nullptr, - CbData::Wrapper, - nullptr, - nullptr, - attributes, - callbackData}); + return PropertyDescriptor({nullptr, + name, + nullptr, + CbData::Wrapper, + nullptr, + nullptr, + attributes, + callbackData}); } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - const char* utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes, - void* data) { - using CbData = details::AccessorCallbackData; - auto callbackData = new CbData({getter, setter, data}); - - napi_status status = AttachData(env, object, callbackData); - if (status != napi_ok) { - delete callbackData; - NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); - } + Napi::Env env, + Napi::Object object, + const char* utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes, + void* data) { + using CbData = details::AccessorCallbackData; + auto callbackData = new CbData({getter, setter, data}); + + napi_status status = AttachData(env, object, callbackData); + if (status != napi_ok) { + delete callbackData; + NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); + } - return PropertyDescriptor({utf8name, - nullptr, - nullptr, - CbData::GetterWrapper, - CbData::SetterWrapper, - nullptr, - attributes, - callbackData}); + return PropertyDescriptor({utf8name, + nullptr, + nullptr, + CbData::GetterWrapper, + CbData::SetterWrapper, + nullptr, + attributes, + callbackData}); } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes, - void* data) { - return Accessor( - env, object, utf8name.c_str(), getter, setter, attributes, data); + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes, + void* data) { + return Accessor( + env, object, utf8name.c_str(), getter, setter, attributes, data); } template inline PropertyDescriptor PropertyDescriptor::Accessor( - Napi::Env env, - Napi::Object object, - Name name, - Getter getter, - Setter setter, - napi_property_attributes attributes, - void* data) { - using CbData = details::AccessorCallbackData; - auto callbackData = new CbData({getter, setter, data}); - - napi_status status = AttachData(env, object, callbackData); - if (status != napi_ok) { - delete callbackData; - NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); - } + Napi::Env env, + Napi::Object object, + Name name, + Getter getter, + Setter setter, + napi_property_attributes attributes, + void* data) { + using CbData = details::AccessorCallbackData; + auto callbackData = new CbData({getter, setter, data}); + + napi_status status = AttachData(env, object, callbackData); + if (status != napi_ok) { + delete callbackData; + NAPI_THROW_IF_FAILED(env, status, napi_property_descriptor()); + } - return PropertyDescriptor({nullptr, - name, - nullptr, - CbData::GetterWrapper, - CbData::SetterWrapper, - nullptr, - attributes, - callbackData}); + return PropertyDescriptor({nullptr, + name, + nullptr, + CbData::GetterWrapper, + CbData::SetterWrapper, + nullptr, + attributes, + callbackData}); } template inline PropertyDescriptor PropertyDescriptor::Function( - Napi::Env env, - Napi::Object /*object*/, - const char* utf8name, - Callable cb, - napi_property_attributes attributes, - void* data) { - return PropertyDescriptor({utf8name, - nullptr, - nullptr, - nullptr, - nullptr, - Napi::Function::New(env, cb, utf8name, data), - attributes, - nullptr}); + Napi::Env env, + Napi::Object /*object*/, + const char* utf8name, + Callable cb, + napi_property_attributes attributes, + void* data) { + return PropertyDescriptor({utf8name, + nullptr, + nullptr, + nullptr, + nullptr, + Napi::Function::New(env, cb, utf8name, data), + attributes, + nullptr}); } template inline PropertyDescriptor PropertyDescriptor::Function( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Callable cb, - napi_property_attributes attributes, - void* data) { - return Function(env, object, utf8name.c_str(), cb, attributes, data); + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Callable cb, + napi_property_attributes attributes, + void* data) { + return Function(env, object, utf8name.c_str(), cb, attributes, data); } template inline PropertyDescriptor PropertyDescriptor::Function( - Napi::Env env, - Napi::Object /*object*/, - Name name, - Callable cb, - napi_property_attributes attributes, - void* data) { - return PropertyDescriptor({nullptr, - name, - nullptr, - nullptr, - nullptr, - Napi::Function::New(env, cb, nullptr, data), - attributes, - nullptr}); + Napi::Env env, + Napi::Object /*object*/, + Name name, + Callable cb, + napi_property_attributes attributes, + void* data) { + return PropertyDescriptor({nullptr, + name, + nullptr, + nullptr, + nullptr, + Napi::Function::New(env, cb, nullptr, data), + attributes, + nullptr}); } inline PropertyDescriptor PropertyDescriptor::Value( - const char* utf8name, - napi_value value, - napi_property_attributes attributes) { - return PropertyDescriptor({utf8name, - nullptr, - nullptr, - nullptr, - nullptr, - value, - attributes, - nullptr}); + const char* utf8name, + napi_value value, + napi_property_attributes attributes) { + return PropertyDescriptor({utf8name, + nullptr, + nullptr, + nullptr, + nullptr, + value, + attributes, + nullptr}); } inline PropertyDescriptor PropertyDescriptor::Value( - const std::string& utf8name, - napi_value value, - napi_property_attributes attributes) { - return Value(utf8name.c_str(), value, attributes); + const std::string& utf8name, + napi_value value, + napi_property_attributes attributes) { + return Value(utf8name.c_str(), value, attributes); } inline PropertyDescriptor PropertyDescriptor::Value( - napi_value name, napi_value value, napi_property_attributes attributes) { - return PropertyDescriptor( - {nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr}); + napi_value name, napi_value value, napi_property_attributes attributes) { + return PropertyDescriptor( + {nullptr, name, nullptr, nullptr, nullptr, value, attributes, nullptr}); } inline PropertyDescriptor PropertyDescriptor::Value( - Name name, Napi::Value value, napi_property_attributes attributes) { - napi_value nameValue = name; - napi_value valueValue = value; - return PropertyDescriptor::Value(nameValue, valueValue, attributes); + Name name, Napi::Value value, napi_property_attributes attributes) { + napi_value nameValue = name; + napi_value valueValue = value; + return PropertyDescriptor::Value(nameValue, valueValue, attributes); } inline PropertyDescriptor::PropertyDescriptor(napi_property_descriptor desc) - : _desc(desc) {} + : _desc(desc) {} inline PropertyDescriptor::operator napi_property_descriptor&() { - return _desc; + return _desc; } inline PropertyDescriptor::operator const napi_property_descriptor&() const { - return _desc; + return _desc; } //////////////////////////////////////////////////////////////////////////////// @@ -4173,305 +4346,305 @@ inline PropertyDescriptor::operator const napi_property_descriptor&() const { template inline void InstanceWrap::AttachPropData( - napi_env env, napi_value value, const napi_property_descriptor* prop) { - napi_status status; - if (!(prop->attributes & napi_static)) { - if (prop->method == T::InstanceVoidMethodCallbackWrapper) { - status = Napi::details::AttachData( - env, value, static_cast(prop->data)); - NAPI_THROW_IF_FAILED_VOID(env, status); - } else if (prop->method == T::InstanceMethodCallbackWrapper) { - status = Napi::details::AttachData( - env, value, static_cast(prop->data)); - NAPI_THROW_IF_FAILED_VOID(env, status); - } else if (prop->getter == T::InstanceGetterCallbackWrapper || - prop->setter == T::InstanceSetterCallbackWrapper) { - status = Napi::details::AttachData( - env, value, static_cast(prop->data)); - NAPI_THROW_IF_FAILED_VOID(env, status); - } + napi_env env, napi_value value, const napi_property_descriptor* prop) { + napi_status status; + if (!(prop->attributes & napi_static)) { + if (prop->method == T::InstanceVoidMethodCallbackWrapper) { + status = Napi::details::AttachData( + env, value, static_cast(prop->data)); + NAPI_THROW_IF_FAILED_VOID(env, status); + } else if (prop->method == T::InstanceMethodCallbackWrapper) { + status = Napi::details::AttachData( + env, value, static_cast(prop->data)); + NAPI_THROW_IF_FAILED_VOID(env, status); + } else if (prop->getter == T::InstanceGetterCallbackWrapper || + prop->setter == T::InstanceSetterCallbackWrapper) { + status = Napi::details::AttachData( + env, value, static_cast(prop->data)); + NAPI_THROW_IF_FAILED_VOID(env, status); } + } } template inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - const char* utf8name, - InstanceVoidMethodCallback method, - napi_property_attributes attributes, - void* data) { - InstanceVoidMethodCallbackData* callbackData = - new InstanceVoidMethodCallbackData({method, data}); + const char* utf8name, + InstanceVoidMethodCallback method, + napi_property_attributes attributes, + void* data) { + InstanceVoidMethodCallbackData* callbackData = + new InstanceVoidMethodCallbackData({method, data}); - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = T::InstanceVoidMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = T::InstanceVoidMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } template inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - const char* utf8name, - InstanceMethodCallback method, - napi_property_attributes attributes, - void* data) { - InstanceMethodCallbackData* callbackData = - new InstanceMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = T::InstanceMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + const char* utf8name, + InstanceMethodCallback method, + napi_property_attributes attributes, + void* data) { + InstanceMethodCallbackData* callbackData = + new InstanceMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = T::InstanceMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - Symbol name, - InstanceVoidMethodCallback method, - napi_property_attributes attributes, - void* data) { - InstanceVoidMethodCallbackData* callbackData = - new InstanceVoidMethodCallbackData({method, data}); + Symbol name, + InstanceVoidMethodCallback method, + napi_property_attributes attributes, + void* data) { + InstanceVoidMethodCallbackData* callbackData = + new InstanceVoidMethodCallbackData({method, data}); - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = T::InstanceVoidMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = T::InstanceVoidMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } template inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - Symbol name, - InstanceMethodCallback method, - napi_property_attributes attributes, - void* data) { - InstanceMethodCallbackData* callbackData = - new InstanceMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = T::InstanceMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + Symbol name, + InstanceMethodCallback method, + napi_property_attributes attributes, + void* data) { + InstanceMethodCallbackData* callbackData = + new InstanceMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = T::InstanceMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } #endif template template ::InstanceVoidMethodCallback method> inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = details::TemplatedInstanceVoidCallback; - desc.data = data; - desc.attributes = attributes; - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = details::TemplatedInstanceVoidCallback; + desc.data = data; + desc.attributes = attributes; + return desc; } template template ::InstanceMethodCallback method> inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = details::TemplatedInstanceCallback; - desc.data = data; - desc.attributes = attributes; - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = details::TemplatedInstanceCallback; + desc.data = data; + desc.attributes = attributes; + return desc; } #ifndef OHOS template template ::InstanceVoidMethodCallback method> inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = details::TemplatedInstanceVoidCallback; - desc.data = data; - desc.attributes = attributes; - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = details::TemplatedInstanceVoidCallback; + desc.data = data; + desc.attributes = attributes; + return desc; } template template ::InstanceMethodCallback method> inline ClassPropertyDescriptor InstanceWrap::InstanceMethod( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = details::TemplatedInstanceCallback; - desc.data = data; - desc.attributes = attributes; - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = details::TemplatedInstanceCallback; + desc.data = data; + desc.attributes = attributes; + return desc; } #endif template inline ClassPropertyDescriptor InstanceWrap::InstanceAccessor( - const char* utf8name, - InstanceGetterCallback getter, - InstanceSetterCallback setter, - napi_property_attributes attributes, - void* data) { - InstanceAccessorCallbackData* callbackData = - new InstanceAccessorCallbackData({getter, setter, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr; - desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + const char* utf8name, + InstanceGetterCallback getter, + InstanceSetterCallback setter, + napi_property_attributes attributes, + void* data) { + InstanceAccessorCallbackData* callbackData = + new InstanceAccessorCallbackData({getter, setter, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr; + desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor InstanceWrap::InstanceAccessor( - Symbol name, - InstanceGetterCallback getter, - InstanceSetterCallback setter, - napi_property_attributes attributes, - void* data) { - InstanceAccessorCallbackData* callbackData = - new InstanceAccessorCallbackData({getter, setter, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr; - desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr; - desc.data = callbackData; - desc.attributes = attributes; - return desc; + Symbol name, + InstanceGetterCallback getter, + InstanceSetterCallback setter, + napi_property_attributes attributes, + void* data) { + InstanceAccessorCallbackData* callbackData = + new InstanceAccessorCallbackData({getter, setter, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr; + desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr; + desc.data = callbackData; + desc.attributes = attributes; + return desc; } #endif template template ::InstanceGetterCallback getter, - typename InstanceWrap::InstanceSetterCallback setter> + typename InstanceWrap::InstanceSetterCallback setter> inline ClassPropertyDescriptor InstanceWrap::InstanceAccessor( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = details::TemplatedInstanceCallback; - desc.setter = This::WrapSetter(This::SetterTag()); - desc.data = data; - desc.attributes = attributes; - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.getter = details::TemplatedInstanceCallback; + desc.setter = This::WrapSetter(This::SetterTag()); + desc.data = data; + desc.attributes = attributes; + return desc; } #ifndef OHOS template template ::InstanceGetterCallback getter, - typename InstanceWrap::InstanceSetterCallback setter> + typename InstanceWrap::InstanceSetterCallback setter> inline ClassPropertyDescriptor InstanceWrap::InstanceAccessor( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = details::TemplatedInstanceCallback; - desc.setter = This::WrapSetter(This::SetterTag()); - desc.data = data; - desc.attributes = attributes; - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.getter = details::TemplatedInstanceCallback; + desc.setter = This::WrapSetter(This::SetterTag()); + desc.data = data; + desc.attributes = attributes; + return desc; } #endif template inline ClassPropertyDescriptor InstanceWrap::InstanceValue( - const char* utf8name, - Napi::Value value, - napi_property_attributes attributes) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.value = value; - desc.attributes = attributes; - return desc; + const char* utf8name, + Napi::Value value, + napi_property_attributes attributes) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.value = value; + desc.attributes = attributes; + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor InstanceWrap::InstanceValue( - Symbol name, Napi::Value value, napi_property_attributes attributes) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.value = value; - desc.attributes = attributes; - return desc; + Symbol name, Napi::Value value, napi_property_attributes attributes) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.value = value; + desc.attributes = attributes; + return desc; } #endif template inline napi_value InstanceWrap::InstanceVoidMethodCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - InstanceVoidMethodCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - T* instance = T::Unwrap(callbackInfo.This().As()); - auto cb = callbackData->callback; - if (instance) (instance->*cb)(callbackInfo); - return nullptr; - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + InstanceVoidMethodCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + T* instance = T::Unwrap(callbackInfo.This().As()); + auto cb = callbackData->callback; + if (instance) (instance->*cb)(callbackInfo); + return nullptr; + }); } template inline napi_value InstanceWrap::InstanceMethodCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - InstanceMethodCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - T* instance = T::Unwrap(callbackInfo.This().As()); - auto cb = callbackData->callback; - return instance ? (instance->*cb)(callbackInfo) : Napi::Value(); - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + InstanceMethodCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + T* instance = T::Unwrap(callbackInfo.This().As()); + auto cb = callbackData->callback; + return instance ? (instance->*cb)(callbackInfo) : Napi::Value(); + }); } template inline napi_value InstanceWrap::InstanceGetterCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - InstanceAccessorCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - T* instance = T::Unwrap(callbackInfo.This().As()); - auto cb = callbackData->getterCallback; - return instance ? (instance->*cb)(callbackInfo) : Napi::Value(); - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + InstanceAccessorCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + T* instance = T::Unwrap(callbackInfo.This().As()); + auto cb = callbackData->getterCallback; + return instance ? (instance->*cb)(callbackInfo) : Napi::Value(); + }); } template inline napi_value InstanceWrap::InstanceSetterCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - InstanceAccessorCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - T* instance = T::Unwrap(callbackInfo.This().As()); - auto cb = callbackData->setterCallback; - if (instance) (instance->*cb)(callbackInfo, callbackInfo[0]); - return nullptr; - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + InstanceAccessorCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + T* instance = T::Unwrap(callbackInfo.This().As()); + auto cb = callbackData->setterCallback; + if (instance) (instance->*cb)(callbackInfo, callbackInfo[0]); + return nullptr; + }); } template template ::InstanceSetterCallback method> inline napi_value InstanceWrap::WrappedMethod( - napi_env env, napi_callback_info info) NAPI_NOEXCEPT { -return details::WrapCallback([&] { -const CallbackInfo cbInfo(env, info); -T* instance = T::Unwrap(cbInfo.This().As()); -if (instance) (instance->*method)(cbInfo, cbInfo[0]); -return nullptr; -}); + napi_env env, napi_callback_info info) NAPI_NOEXCEPT { + return details::WrapCallback(env, [&] { + const CallbackInfo cbInfo(env, info); + T* instance = T::Unwrap(cbInfo.This().As()); + if (instance) (instance->*method)(cbInfo, cbInfo[0]); + return nullptr; + }); } //////////////////////////////////////////////////////////////////////////////// @@ -4480,503 +4653,552 @@ return nullptr; template inline ObjectWrap::ObjectWrap(const Napi::CallbackInfo& callbackInfo) { - napi_env env = callbackInfo.Env(); - napi_value wrapper = callbackInfo.This(); - napi_status status; - napi_ref ref; - T* instance = static_cast(this); - status = napi_wrap(env, - wrapper, - instance, - details::PostFinalizerWrapper, - nullptr, - &ref); - NAPI_THROW_IF_FAILED_VOID(env, status); - // unref after napi_wrap - // https://gitee.com/openharmony/docs/pulls/57998/files - status = napi_reference_unref(env, ref, nullptr); - NAPI_THROW_IF_FAILED_VOID(env, status); - - Reference* instanceRef = instance; - *instanceRef = Reference(env, ref); + napi_env env = callbackInfo.Env(); + napi_value wrapper = callbackInfo.This(); + napi_status status; + napi_ref ref; + T* instance = static_cast(this); + status = napi_wrap(env, wrapper, instance, FinalizeCallback, nullptr, &ref); + NAPI_THROW_IF_FAILED_VOID(env, status); + // unref after napi_wrap + // https://gitee.com/openharmony/docs/pulls/57998/files + status = napi_reference_unref(env, ref, nullptr); + NAPI_THROW_IF_FAILED_VOID(env, status); + + Reference* instanceRef = instance; + *instanceRef = Reference(env, ref); } template inline ObjectWrap::~ObjectWrap() { - // If the JS object still exists at this point, remove the finalizer added - // through `napi_wrap()`. - if (!IsEmpty()) { - Object object = Value(); - // It is not valid to call `napi_remove_wrap()` with an empty `object`. - // This happens e.g. during garbage collection. - if (!object.IsEmpty() && _construction_failed) { - napi_remove_wrap(Env(), object, nullptr); - } + // If the JS object still exists at this point, remove the finalizer added + // through `napi_wrap()`. + if (!IsEmpty() && !_finalized) { + Object object = Value(); + // It is not valid to call `napi_remove_wrap()` with an empty `object`. + // This happens e.g. during garbage collection. + if (!object.IsEmpty() && _construction_failed) { + napi_remove_wrap(Env(), object, nullptr); } + } } template inline T* ObjectWrap::Unwrap(Object wrapper) { - void* unwrapped; - napi_status status = napi_unwrap(wrapper.Env(), wrapper, &unwrapped); - NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr); - return static_cast(unwrapped); + void* unwrapped; + napi_status status = napi_unwrap(wrapper.Env(), wrapper, &unwrapped); + NAPI_THROW_IF_FAILED(wrapper.Env(), status, nullptr); + return static_cast(unwrapped); } template inline Function ObjectWrap::DefineClass( - Napi::Env env, - const char* utf8name, - const size_t props_count, - const napi_property_descriptor* descriptors, - void* data) { - napi_status status; - std::vector props(props_count); - - // We copy the descriptors to a local array because before defining the class - // we must replace static method property descriptors with value property - // descriptors such that the value is a function-valued `napi_value` created - // with `CreateFunction()`. - // - // This replacement could be made for instance methods as well, but V8 aborts - // if we do that, because it expects methods defined on the prototype template - // to have `FunctionTemplate`s. - for (size_t index = 0; index < props_count; index++) { - props[index] = descriptors[index]; - napi_property_descriptor* prop = &props[index]; - if (prop->method == T::StaticMethodCallbackWrapper) { - status = - CreateFunction(env, - utf8name, - prop->method, - static_cast(prop->data), - &(prop->value)); - NAPI_THROW_IF_FAILED(env, status, Function()); - prop->method = nullptr; - prop->data = nullptr; - } else if (prop->method == T::StaticVoidMethodCallbackWrapper) { - status = - CreateFunction(env, - utf8name, - prop->method, - static_cast(prop->data), - &(prop->value)); - NAPI_THROW_IF_FAILED(env, status, Function()); - prop->method = nullptr; - prop->data = nullptr; - } + Napi::Env env, + const char* utf8name, + const size_t props_count, + const napi_property_descriptor* descriptors, + void* data) { + napi_status status; + std::vector props(props_count); + + // We copy the descriptors to a local array because before defining the class + // we must replace static method property descriptors with value property + // descriptors such that the value is a function-valued `napi_value` created + // with `CreateFunction()`. + // + // This replacement could be made for instance methods as well, but V8 aborts + // if we do that, because it expects methods defined on the prototype template + // to have `FunctionTemplate`s. + for (size_t index = 0; index < props_count; index++) { + props[index] = descriptors[index]; + napi_property_descriptor* prop = &props[index]; + if (prop->method == T::StaticMethodCallbackWrapper) { + status = + CreateFunction(env, + utf8name, + prop->method, + static_cast(prop->data), + &(prop->value)); + NAPI_THROW_IF_FAILED(env, status, Function()); + prop->method = nullptr; + prop->data = nullptr; + } else if (prop->method == T::StaticVoidMethodCallbackWrapper) { + status = + CreateFunction(env, + utf8name, + prop->method, + static_cast(prop->data), + &(prop->value)); + NAPI_THROW_IF_FAILED(env, status, Function()); + prop->method = nullptr; + prop->data = nullptr; } + } - napi_value value; - status = napi_define_class(env, - utf8name, - NAPI_AUTO_LENGTH, - T::ConstructorCallbackWrapper, - data, - props_count, - props.data(), - &value); - NAPI_THROW_IF_FAILED(env, status, Function()); - - // After defining the class we iterate once more over the property descriptors - // and attach the data associated with accessors and instance methods to the - // newly created JavaScript class. - for (size_t idx = 0; idx < props_count; idx++) { - const napi_property_descriptor* prop = &props[idx]; - - if (prop->getter == T::StaticGetterCallbackWrapper || - prop->setter == T::StaticSetterCallbackWrapper) { - status = Napi::details::AttachData( - env, value, static_cast(prop->data)); - NAPI_THROW_IF_FAILED(env, status, Function()); - } else { - // InstanceWrap::AttachPropData is responsible for attaching the data - // of instance methods and accessors. - T::AttachPropData(env, value, prop); - } + napi_value value; + status = napi_define_class(env, + utf8name, + NAPI_AUTO_LENGTH, + T::ConstructorCallbackWrapper, + data, + props_count, + props.data(), + &value); + NAPI_THROW_IF_FAILED(env, status, Function()); + + // After defining the class we iterate once more over the property descriptors + // and attach the data associated with accessors and instance methods to the + // newly created JavaScript class. + for (size_t idx = 0; idx < props_count; idx++) { + const napi_property_descriptor* prop = &props[idx]; + + if (prop->getter == T::StaticGetterCallbackWrapper || + prop->setter == T::StaticSetterCallbackWrapper) { + status = Napi::details::AttachData( + env, value, static_cast(prop->data)); + NAPI_THROW_IF_FAILED(env, status, Function()); + } else { + // InstanceWrap::AttachPropData is responsible for attaching the data + // of instance methods and accessors. + T::AttachPropData(env, value, prop); } + } - return Function(env, value); + return Function(env, value); } template inline Function ObjectWrap::DefineClass( - Napi::Env env, - const char* utf8name, - const std::initializer_list>& properties, - void* data) { - return DefineClass( - env, - utf8name, - properties.size(), - reinterpret_cast(properties.begin()), - data); + Napi::Env env, + const char* utf8name, + const std::initializer_list>& properties, + void* data) { + return DefineClass( + env, + utf8name, + properties.size(), + reinterpret_cast(properties.begin()), + data); } template inline Function ObjectWrap::DefineClass( - Napi::Env env, - const char* utf8name, - const std::vector>& properties, - void* data) { - return DefineClass( - env, - utf8name, - properties.size(), - reinterpret_cast(properties.data()), - data); + Napi::Env env, + const char* utf8name, + const std::vector>& properties, + void* data) { + return DefineClass( + env, + utf8name, + properties.size(), + reinterpret_cast(properties.data()), + data); } template inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - const char* utf8name, - StaticVoidMethodCallback method, - napi_property_attributes attributes, - void* data) { - StaticVoidMethodCallbackData* callbackData = - new StaticVoidMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = T::StaticVoidMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, + StaticVoidMethodCallback method, + napi_property_attributes attributes, + void* data) { + StaticVoidMethodCallbackData* callbackData = + new StaticVoidMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = T::StaticVoidMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } template inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - const char* utf8name, - StaticMethodCallback method, - napi_property_attributes attributes, - void* data) { - StaticMethodCallbackData* callbackData = - new StaticMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = T::StaticMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, + StaticMethodCallback method, + napi_property_attributes attributes, + void* data) { + StaticMethodCallbackData* callbackData = + new StaticMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = T::StaticMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - Symbol name, - StaticVoidMethodCallback method, - napi_property_attributes attributes, - void* data) { - StaticVoidMethodCallbackData* callbackData = - new StaticVoidMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = T::StaticVoidMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, + StaticVoidMethodCallback method, + napi_property_attributes attributes, + void* data) { + StaticVoidMethodCallbackData* callbackData = + new StaticVoidMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = T::StaticVoidMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif #ifndef OHOS template inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - Symbol name, - StaticMethodCallback method, - napi_property_attributes attributes, - void* data) { - StaticMethodCallbackData* callbackData = - new StaticMethodCallbackData({method, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = T::StaticMethodCallbackWrapper; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, + StaticMethodCallback method, + napi_property_attributes attributes, + void* data) { + StaticMethodCallbackData* callbackData = + new StaticMethodCallbackData({method, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = T::StaticMethodCallbackWrapper; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template template ::StaticVoidMethodCallback method> inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = details::TemplatedVoidCallback; - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = details::TemplatedVoidCallback; + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template template ::StaticVoidMethodCallback method> inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = details::TemplatedVoidCallback; - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = details::TemplatedVoidCallback; + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template template ::StaticMethodCallback method> inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.method = details::TemplatedCallback; - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.method = details::TemplatedCallback; + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template template ::StaticMethodCallback method> inline ClassPropertyDescriptor ObjectWrap::StaticMethod( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.method = details::TemplatedCallback; - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.method = details::TemplatedCallback; + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template inline ClassPropertyDescriptor ObjectWrap::StaticAccessor( - const char* utf8name, - StaticGetterCallback getter, - StaticSetterCallback setter, - napi_property_attributes attributes, - void* data) { - StaticAccessorCallbackData* callbackData = - new StaticAccessorCallbackData({getter, setter, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr; - desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, + StaticGetterCallback getter, + StaticSetterCallback setter, + napi_property_attributes attributes, + void* data) { + StaticAccessorCallbackData* callbackData = + new StaticAccessorCallbackData({getter, setter, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr; + desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor ObjectWrap::StaticAccessor( - Symbol name, - StaticGetterCallback getter, - StaticSetterCallback setter, - napi_property_attributes attributes, - void* data) { - StaticAccessorCallbackData* callbackData = - new StaticAccessorCallbackData({getter, setter, data}); - - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr; - desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr; - desc.data = callbackData; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, + StaticGetterCallback getter, + StaticSetterCallback setter, + napi_property_attributes attributes, + void* data) { + StaticAccessorCallbackData* callbackData = + new StaticAccessorCallbackData({getter, setter, data}); + + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr; + desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr; + desc.data = callbackData; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template template ::StaticGetterCallback getter, - typename ObjectWrap::StaticSetterCallback setter> + typename ObjectWrap::StaticSetterCallback setter> inline ClassPropertyDescriptor ObjectWrap::StaticAccessor( - const char* utf8name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.getter = details::TemplatedCallback; - desc.setter = This::WrapStaticSetter(This::StaticSetterTag()); - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.getter = details::TemplatedCallback; + desc.setter = This::WrapStaticSetter(This::StaticSetterTag()); + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template template ::StaticGetterCallback getter, - typename ObjectWrap::StaticSetterCallback setter> + typename ObjectWrap::StaticSetterCallback setter> inline ClassPropertyDescriptor ObjectWrap::StaticAccessor( - Symbol name, napi_property_attributes attributes, void* data) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.getter = details::TemplatedCallback; - desc.setter = This::WrapStaticSetter(This::StaticSetterTag()); - desc.data = data; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, napi_property_attributes attributes, void* data) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.getter = details::TemplatedCallback; + desc.setter = This::WrapStaticSetter(This::StaticSetterTag()); + desc.data = data; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template inline ClassPropertyDescriptor ObjectWrap::StaticValue( - const char* utf8name, - Napi::Value value, - napi_property_attributes attributes) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.utf8name = utf8name; - desc.value = value; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + const char* utf8name, + Napi::Value value, + napi_property_attributes attributes) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.utf8name = utf8name; + desc.value = value; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #ifndef OHOS template inline ClassPropertyDescriptor ObjectWrap::StaticValue( - Symbol name, Napi::Value value, napi_property_attributes attributes) { - napi_property_descriptor desc = napi_property_descriptor(); - desc.name = name; - desc.value = value; - desc.attributes = - static_cast(attributes | napi_static); - return desc; + Symbol name, Napi::Value value, napi_property_attributes attributes) { + napi_property_descriptor desc = napi_property_descriptor(); + desc.name = name; + desc.value = value; + desc.attributes = + static_cast(attributes | napi_static); + return desc; } #endif template inline Value ObjectWrap::OnCalledAsFunction( - const Napi::CallbackInfo& callbackInfo) { - NAPI_THROW( - TypeError::New(callbackInfo.Env(), - "Class constructors cannot be invoked without 'new'"), - Napi::Value()); + const Napi::CallbackInfo& callbackInfo) { + NAPI_THROW( + TypeError::New(callbackInfo.Env(), + "Class constructors cannot be invoked without 'new'"), + Napi::Value()); } template inline void ObjectWrap::Finalize(Napi::Env /*env*/) {} +template +inline void ObjectWrap::Finalize(BasicEnv /*env*/) {} + template inline napi_value ObjectWrap::ConstructorCallbackWrapper( - napi_env env, napi_callback_info info) { - napi_value new_target; - napi_status status = napi_get_new_target(env, info, &new_target); - if (status != napi_ok) return nullptr; - - bool isConstructCall = (new_target != nullptr); - if (!isConstructCall) { - return details::WrapCallback( - [&] { return T::OnCalledAsFunction(CallbackInfo(env, info)); }); - } + napi_env env, napi_callback_info info) { + napi_value new_target; + napi_status status = napi_get_new_target(env, info, &new_target); + if (status != napi_ok) return nullptr; + + bool isConstructCall = (new_target != nullptr); + if (!isConstructCall) { + return details::WrapCallback( + env, [&] { return T::OnCalledAsFunction(CallbackInfo(env, info)); }); + } - napi_value wrapper = details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - T* instance = new T(callbackInfo); -#ifdef NAPI_CPP_EXCEPTIONS - instance->_construction_failed = false; + napi_value wrapper = details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + T* instance = new T(callbackInfo); +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + instance->_construction_failed = false; #else - if (callbackInfo.Env().IsExceptionPending()) { - // We need to clear the exception so that removing the wrap might work. - Error e = callbackInfo.Env().GetAndClearPendingException(); - delete instance; - e.ThrowAsJavaScriptException(); - } else { - instance->_construction_failed = false; - } -#endif // NAPI_CPP_EXCEPTIONS - return callbackInfo.This(); - }); + if (callbackInfo.Env().IsExceptionPending()) { + // We need to clear the exception so that removing the wrap might work. + Error e = callbackInfo.Env().GetAndClearPendingException(); + delete instance; + e.ThrowAsJavaScriptException(); + } else { + instance->_construction_failed = false; + } +#endif // NODE_ADDON_API_CPP_EXCEPTIONS + return callbackInfo.This(); + }); - return wrapper; + return wrapper; } template inline napi_value ObjectWrap::StaticVoidMethodCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - StaticVoidMethodCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - callbackData->callback(callbackInfo); - return nullptr; - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + StaticVoidMethodCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + callbackData->callback(callbackInfo); + return nullptr; + }); } template inline napi_value ObjectWrap::StaticMethodCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - StaticMethodCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - return callbackData->callback(callbackInfo); - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + StaticMethodCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + return callbackData->callback(callbackInfo); + }); } template inline napi_value ObjectWrap::StaticGetterCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - StaticAccessorCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - return callbackData->getterCallback(callbackInfo); - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + StaticAccessorCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + return callbackData->getterCallback(callbackInfo); + }); } template inline napi_value ObjectWrap::StaticSetterCallbackWrapper( - napi_env env, napi_callback_info info) { - return details::WrapCallback([&] { - CallbackInfo callbackInfo(env, info); - StaticAccessorCallbackData* callbackData = - reinterpret_cast(callbackInfo.Data()); - callbackInfo.SetData(callbackData->data); - callbackData->setterCallback(callbackInfo, callbackInfo[0]); - return nullptr; - }); + napi_env env, napi_callback_info info) { + return details::WrapCallback(env, [&] { + CallbackInfo callbackInfo(env, info); + StaticAccessorCallbackData* callbackData = + reinterpret_cast(callbackInfo.Data()); + callbackInfo.SetData(callbackData->data); + callbackData->setterCallback(callbackInfo, callbackInfo[0]); + return nullptr; + }); } template -inline void ObjectWrap::FinalizeCallback(napi_env env, +inline void ObjectWrap::FinalizeCallback(node_addon_api_basic_env env, void* data, void* /*hint*/) { + // If the child class does not override _any_ Finalize() method, `env` will be + // unused because of the constexpr guards. Explicitly reference it here to + // bypass compiler warnings. + (void)env; + T* instance = static_cast(data); + + // Prevent ~ObjectWrap from calling napi_remove_wrap. + // The instance->_ref should be deleted with napi_delete_reference in + // ~Reference. + instance->_finalized = true; + + // If class overrides the basic finalizer, execute it. + if constexpr (details::HasBasicFinalizer::value) { +#ifndef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + HandleScope scope(env); +#endif + + instance->Finalize(Napi::BasicEnv(env)); + } + + // If class overrides the (extended) finalizer, either schedule it or + // execute it immediately (depending on experimental features enabled). + if constexpr (details::HasExtendedFinalizer::value) { +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + // In experimental, attach via node_api_post_finalizer. + // `PostFinalizeCallback` is responsible for deleting the `T* instance`, + // after calling the user-provided finalizer. + napi_status status = + node_api_post_finalizer(env, PostFinalizeCallback, data, nullptr); + NAPI_FATAL_IF_FAILED(status, + "ObjectWrap::FinalizeCallback", + "node_api_post_finalizer failed"); +#else + // In non-experimental, this `FinalizeCallback` already executes from a + // non-basic environment. Execute the override directly. + // `PostFinalizeCallback` is responsible for deleting the `T* instance`, + // after calling the user-provided finalizer. HandleScope scope(env); - T* instance = static_cast(data); - instance->Finalize(Napi::Env(env)); + PostFinalizeCallback(env, data, static_cast(nullptr)); +#endif + } + // If the instance does _not_ override the (extended) finalizer, delete the + // `T* instance` immediately. + else { delete instance; + } +} + +template +inline void ObjectWrap::PostFinalizeCallback(napi_env env, + void* data, + void* /*hint*/) { + T* instance = static_cast(data); + instance->Finalize(Napi::Env(env)); + delete instance; } template template ::StaticSetterCallback method> inline napi_value ObjectWrap::WrappedMethod( - napi_env env, napi_callback_info info) NAPI_NOEXCEPT { -return details::WrapCallback([&] { -const CallbackInfo cbInfo(env, info); -// MSVC requires to copy 'method' function pointer to a local variable -// before invoking it. -auto m = method; -m(cbInfo, cbInfo[0]); -return nullptr; -}); + napi_env env, napi_callback_info info) NAPI_NOEXCEPT { + return details::WrapCallback(env, [&] { + const CallbackInfo cbInfo(env, info); + // MSVC requires to copy 'method' function pointer to a local variable + // before invoking it. + auto m = method; + m(cbInfo, cbInfo[0]); + return nullptr; + }); } //////////////////////////////////////////////////////////////////////////////// @@ -4984,25 +5206,25 @@ return nullptr; //////////////////////////////////////////////////////////////////////////////// inline HandleScope::HandleScope(napi_env env, napi_handle_scope scope) - : _env(env), _scope(scope) {} + : _env(env), _scope(scope) {} inline HandleScope::HandleScope(Napi::Env env) : _env(env) { - napi_status status = napi_open_handle_scope(_env, &_scope); - NAPI_THROW_IF_FAILED_VOID(_env, status); + napi_status status = napi_open_handle_scope(_env, &_scope); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline HandleScope::~HandleScope() { - napi_status status = napi_close_handle_scope(_env, _scope); - NAPI_FATAL_IF_FAILED( - status, "HandleScope::~HandleScope", "napi_close_handle_scope"); + napi_status status = napi_close_handle_scope(_env, _scope); + NAPI_FATAL_IF_FAILED( + status, "HandleScope::~HandleScope", "napi_close_handle_scope"); } inline HandleScope::operator napi_handle_scope() const { - return _scope; + return _scope; } inline Napi::Env HandleScope::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } //////////////////////////////////////////////////////////////////////////////// @@ -5010,34 +5232,34 @@ inline Napi::Env HandleScope::Env() const { //////////////////////////////////////////////////////////////////////////////// inline EscapableHandleScope::EscapableHandleScope( - napi_env env, napi_escapable_handle_scope scope) - : _env(env), _scope(scope) {} + napi_env env, napi_escapable_handle_scope scope) + : _env(env), _scope(scope) {} inline EscapableHandleScope::EscapableHandleScope(Napi::Env env) : _env(env) { - napi_status status = napi_open_escapable_handle_scope(_env, &_scope); - NAPI_THROW_IF_FAILED_VOID(_env, status); + napi_status status = napi_open_escapable_handle_scope(_env, &_scope); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline EscapableHandleScope::~EscapableHandleScope() { - napi_status status = napi_close_escapable_handle_scope(_env, _scope); - NAPI_FATAL_IF_FAILED(status, - "EscapableHandleScope::~EscapableHandleScope", - "napi_close_escapable_handle_scope"); + napi_status status = napi_close_escapable_handle_scope(_env, _scope); + NAPI_FATAL_IF_FAILED(status, + "EscapableHandleScope::~EscapableHandleScope", + "napi_close_escapable_handle_scope"); } inline EscapableHandleScope::operator napi_escapable_handle_scope() const { - return _scope; + return _scope; } inline Napi::Env EscapableHandleScope::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } inline Value EscapableHandleScope::Escape(napi_value escapee) { - napi_value result; - napi_status status = napi_escape_handle(_env, _scope, escapee, &result); - NAPI_THROW_IF_FAILED(_env, status, Value()); - return Value(_env, result); + napi_value result; + napi_status status = napi_escape_handle(_env, _scope, escapee, &result); + NAPI_THROW_IF_FAILED(_env, status, Value()); + return Value(_env, result); } #if (NAPI_VERSION > 2) @@ -5075,49 +5297,49 @@ inline Napi::Env CallbackScope::Env() const { //////////////////////////////////////////////////////////////////////////////// inline AsyncContext::AsyncContext(napi_env env, const char* resource_name) - : AsyncContext(env, resource_name, Object::New(env)) {} + : AsyncContext(env, resource_name, Object::New(env)) {} inline AsyncContext::AsyncContext(napi_env env, const char* resource_name, const Object& resource) - : _env(env), _context(nullptr) { - napi_value resource_id; - napi_status status = napi_create_string_utf8( - _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); - NAPI_THROW_IF_FAILED_VOID(_env, status); + : _env(env), _context(nullptr) { + napi_value resource_id; + napi_status status = napi_create_string_utf8( + _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); + NAPI_THROW_IF_FAILED_VOID(_env, status); - status = napi_async_init(_env, resource, resource_id, &_context); - NAPI_THROW_IF_FAILED_VOID(_env, status); + status = napi_async_init(_env, resource, resource_id, &_context); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline AsyncContext::~AsyncContext() { - if (_context != nullptr) { - napi_async_destroy(_env, _context); - _context = nullptr; - } + if (_context != nullptr) { + napi_async_destroy(_env, _context); + _context = nullptr; + } } inline AsyncContext::AsyncContext(AsyncContext&& other) { - _env = other._env; - other._env = nullptr; - _context = other._context; - other._context = nullptr; + _env = other._env; + other._env = nullptr; + _context = other._context; + other._context = nullptr; } inline AsyncContext& AsyncContext::operator=(AsyncContext&& other) { - _env = other._env; - other._env = nullptr; - _context = other._context; - other._context = nullptr; - return *this; + _env = other._env; + other._env = nullptr; + _context = other._context; + other._context = nullptr; + return *this; } inline AsyncContext::operator napi_async_context() const { - return _context; + return _context; } inline Napi::Env AsyncContext::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } //////////////////////////////////////////////////////////////////////////////// @@ -5127,181 +5349,181 @@ inline Napi::Env AsyncContext::Env() const { #if NAPI_HAS_THREADS inline AsyncWorker::AsyncWorker(const Function& callback) - : AsyncWorker(callback, "generic") {} + : AsyncWorker(callback, "generic") {} inline AsyncWorker::AsyncWorker(const Function& callback, const char* resource_name) - : AsyncWorker(callback, resource_name, Object::New(callback.Env())) {} + : AsyncWorker(callback, resource_name, Object::New(callback.Env())) {} inline AsyncWorker::AsyncWorker(const Function& callback, const char* resource_name, const Object& resource) - : AsyncWorker( - Object::New(callback.Env()), callback, resource_name, resource) {} + : AsyncWorker( + Object::New(callback.Env()), callback, resource_name, resource) {} inline AsyncWorker::AsyncWorker(const Object& receiver, const Function& callback) - : AsyncWorker(receiver, callback, "generic") {} + : AsyncWorker(receiver, callback, "generic") {} inline AsyncWorker::AsyncWorker(const Object& receiver, const Function& callback, const char* resource_name) - : AsyncWorker( - receiver, callback, resource_name, Object::New(callback.Env())) {} + : AsyncWorker( + receiver, callback, resource_name, Object::New(callback.Env())) {} inline AsyncWorker::AsyncWorker(const Object& receiver, const Function& callback, const char* resource_name, const Object& resource) - : _env(callback.Env()), - _receiver(Napi::Persistent(receiver)), - _callback(Napi::Persistent(callback)), - _suppress_destruct(false) { - napi_value resource_id; - napi_status status = napi_create_string_latin1( - _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); - NAPI_THROW_IF_FAILED_VOID(_env, status); + : _env(callback.Env()), + _receiver(Napi::Persistent(receiver)), + _callback(Napi::Persistent(callback)), + _suppress_destruct(false) { + napi_value resource_id; + napi_status status = napi_create_string_latin1( + _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); + NAPI_THROW_IF_FAILED_VOID(_env, status); - status = napi_create_async_work(_env, - resource, - resource_id, - OnAsyncWorkExecute, - OnAsyncWorkComplete, - this, - &_work); - NAPI_THROW_IF_FAILED_VOID(_env, status); + status = napi_create_async_work(_env, + resource, + resource_id, + OnAsyncWorkExecute, + OnAsyncWorkComplete, + this, + &_work); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline AsyncWorker::AsyncWorker(Napi::Env env) : AsyncWorker(env, "generic") {} inline AsyncWorker::AsyncWorker(Napi::Env env, const char* resource_name) - : AsyncWorker(env, resource_name, Object::New(env)) {} + : AsyncWorker(env, resource_name, Object::New(env)) {} inline AsyncWorker::AsyncWorker(Napi::Env env, const char* resource_name, const Object& resource) - : _env(env), _receiver(), _callback(), _suppress_destruct(false) { - napi_value resource_id; - napi_status status = napi_create_string_latin1( - _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); - NAPI_THROW_IF_FAILED_VOID(_env, status); + : _env(env), _receiver(), _callback(), _suppress_destruct(false) { + napi_value resource_id; + napi_status status = napi_create_string_latin1( + _env, resource_name, NAPI_AUTO_LENGTH, &resource_id); + NAPI_THROW_IF_FAILED_VOID(_env, status); - status = napi_create_async_work(_env, - resource, - resource_id, - OnAsyncWorkExecute, - OnAsyncWorkComplete, - this, - &_work); - NAPI_THROW_IF_FAILED_VOID(_env, status); + status = napi_create_async_work(_env, + resource, + resource_id, + OnAsyncWorkExecute, + OnAsyncWorkComplete, + this, + &_work); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline AsyncWorker::~AsyncWorker() { - if (_work != nullptr) { - napi_delete_async_work(_env, _work); - _work = nullptr; - } + if (_work != nullptr) { + napi_delete_async_work(_env, _work); + _work = nullptr; + } } inline void AsyncWorker::Destroy() { - delete this; + delete this; } inline AsyncWorker::operator napi_async_work() const { - return _work; + return _work; } inline Napi::Env AsyncWorker::Env() const { - return Napi::Env(_env); + return Napi::Env(_env); } inline void AsyncWorker::Queue() { - napi_status status = napi_queue_async_work(_env, _work); - NAPI_THROW_IF_FAILED_VOID(_env, status); + napi_status status = napi_queue_async_work(_env, _work); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline void AsyncWorker::Cancel() { - napi_status status = napi_cancel_async_work(_env, _work); - NAPI_THROW_IF_FAILED_VOID(_env, status); + napi_status status = napi_cancel_async_work(_env, _work); + NAPI_THROW_IF_FAILED_VOID(_env, status); } inline ObjectReference& AsyncWorker::Receiver() { - return _receiver; + return _receiver; } inline FunctionReference& AsyncWorker::Callback() { - return _callback; + return _callback; } inline void AsyncWorker::SuppressDestruct() { - _suppress_destruct = true; + _suppress_destruct = true; } inline void AsyncWorker::OnOK() { - if (!_callback.IsEmpty()) { - _callback.Call(_receiver.Value(), GetResult(_callback.Env())); - } + if (!_callback.IsEmpty()) { + _callback.Call(_receiver.Value(), GetResult(_callback.Env())); + } } inline void AsyncWorker::OnError(const Error& e) { - if (!_callback.IsEmpty()) { - _callback.Call(_receiver.Value(), - std::initializer_list{e.Value()}); - } + if (!_callback.IsEmpty()) { + _callback.Call(_receiver.Value(), + std::initializer_list{e.Value()}); + } } inline void AsyncWorker::SetError(const std::string& error) { - _error = error; + _error = error; } inline std::vector AsyncWorker::GetResult(Napi::Env /*env*/) { - return {}; + return {}; } // The OnAsyncWorkExecute method receives an napi_env argument. However, do NOT // use it within this method, as it does not run on the JavaScript thread and // must not run any method that would cause JavaScript to run. In practice, // this means that almost any use of napi_env will be incorrect. inline void AsyncWorker::OnAsyncWorkExecute(napi_env env, void* asyncworker) { - AsyncWorker* self = static_cast(asyncworker); - self->OnExecute(env); + AsyncWorker* self = static_cast(asyncworker); + self->OnExecute(env); } // The OnExecute method receives an napi_env argument. However, do NOT // use it within this method, as it does not run on the JavaScript thread and // must not run any method that would cause JavaScript to run. In practice, // this means that almost any use of napi_env will be incorrect. inline void AsyncWorker::OnExecute(Napi::Env /*DO_NOT_USE*/) { -#ifdef NAPI_CPP_EXCEPTIONS - try { +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + try { Execute(); } catch (const std::exception& e) { SetError(e.what()); } -#else // NAPI_CPP_EXCEPTIONS - Execute(); -#endif // NAPI_CPP_EXCEPTIONS +#else // NODE_ADDON_API_CPP_EXCEPTIONS + Execute(); +#endif // NODE_ADDON_API_CPP_EXCEPTIONS } inline void AsyncWorker::OnAsyncWorkComplete(napi_env env, napi_status status, void* asyncworker) { - AsyncWorker* self = static_cast(asyncworker); - self->OnWorkComplete(env, status); -} -inline void AsyncWorker::OnWorkComplete(Napi::Env /*env*/, napi_status status) { - if (status != napi_cancelled) { - HandleScope scope(_env); - details::WrapCallback([&] { - if (_error.size() == 0) { - OnOK(); - } else { - OnError(Error::New(_env, _error)); - } - return nullptr; - }); - } - if (!_suppress_destruct) { - Destroy(); - } + AsyncWorker* self = static_cast(asyncworker); + self->OnWorkComplete(env, status); +} +inline void AsyncWorker::OnWorkComplete(Napi::Env env, napi_status status) { + if (status != napi_cancelled) { + HandleScope scope(_env); + details::WrapCallback(env, [&] { + if (_error.size() == 0) { + OnOK(); + } else { + OnError(Error::New(_env, _error)); + } + return nullptr; + }); + } + if (!_suppress_destruct) { + Destroy(); + } } #endif // NAPI_HAS_THREADS @@ -6202,7 +6424,7 @@ inline void ThreadSafeFunction::CallJS(napi_env env, return; } - details::WrapVoidCallback([&]() { + details::WrapVoidCallback(env, [&]() { if (data != nullptr) { auto* callbackWrapper = static_cast(data); (*callbackWrapper)(env, Function(env, jsCallback)); @@ -6571,31 +6793,36 @@ inline void AsyncProgressQueueWorker::ExecutionProgress::Send( // Memory Management class //////////////////////////////////////////////////////////////////////////////// #ifndef OHOS -inline int64_t MemoryManagement::AdjustExternalMemory(Env env, -int64_t change_in_bytes) { -int64_t result; -napi_status status = - napi_adjust_external_memory(env, change_in_bytes, &result); -NAPI_THROW_IF_FAILED(env, status, 0); -return result; +inline int64_t MemoryManagement::AdjustExternalMemory(BasicEnv env, + int64_t change_in_bytes) { + int64_t result; + napi_status status = + napi_adjust_external_memory(env, change_in_bytes, &result); + NAPI_FATAL_IF_FAILED(status, + "MemoryManagement::AdjustExternalMemory", + "napi_adjust_external_memory"); + return result; } #endif //////////////////////////////////////////////////////////////////////////////// // Version Management class //////////////////////////////////////////////////////////////////////////////// -inline uint32_t VersionManagement::GetNapiVersion(Env env) { -uint32_t result; -napi_status status = napi_get_version(env, &result); -NAPI_THROW_IF_FAILED(env, status, 0); -return result; +inline uint32_t VersionManagement::GetNapiVersion(BasicEnv env) { + uint32_t result; + napi_status status = napi_get_version(env, &result); + NAPI_FATAL_IF_FAILED( + status, "VersionManagement::GetNapiVersion", "napi_get_version"); + return result; } -inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) { -const napi_node_version* result; -napi_status status = napi_get_node_version(env, &result); -NAPI_THROW_IF_FAILED(env, status, 0); -return result; +inline const napi_node_version* VersionManagement::GetNodeVersion( + BasicEnv env) { + const napi_node_version* result; + napi_status status = napi_get_node_version(env, &result); + NAPI_FATAL_IF_FAILED( + status, "VersionManagement::GetNodeVersion", "napi_get_node_version"); + return result; } #if NAPI_VERSION > 5 @@ -6639,12 +6866,12 @@ inline Napi::Object Addon::DefineProperties( #if NAPI_VERSION > 2 template -Env::CleanupHook Env::AddCleanupHook(Hook hook, Arg* arg) { +Env::CleanupHook BasicEnv::AddCleanupHook(Hook hook, Arg* arg) { return CleanupHook(*this, hook, arg); } template -Env::CleanupHook Env::AddCleanupHook(Hook hook) { +Env::CleanupHook BasicEnv::AddCleanupHook(Hook hook) { return CleanupHook(*this, hook); } @@ -6654,7 +6881,7 @@ Env::CleanupHook::CleanupHook() { } template -Env::CleanupHook::CleanupHook(Napi::Env env, Hook hook) +Env::CleanupHook::CleanupHook(Napi::BasicEnv env, Hook hook) : wrapper(Env::CleanupHook::Wrapper) { data = new CleanupData{std::move(hook), nullptr}; napi_status status = napi_add_env_cleanup_hook(env, wrapper, data); @@ -6665,7 +6892,9 @@ Env::CleanupHook::CleanupHook(Napi::Env env, Hook hook) } template -Env::CleanupHook::CleanupHook(Napi::Env env, Hook hook, Arg* arg) +Env::CleanupHook::CleanupHook(Napi::BasicEnv env, + Hook hook, + Arg* arg) : wrapper(Env::CleanupHook::WrapperWithArg) { data = new CleanupData{std::move(hook), arg}; napi_status status = napi_add_env_cleanup_hook(env, wrapper, data); @@ -6676,7 +6905,7 @@ Env::CleanupHook::CleanupHook(Napi::Env env, Hook hook, Arg* arg) } template -bool Env::CleanupHook::Remove(Env env) { +bool Env::CleanupHook::Remove(BasicEnv env) { napi_status status = napi_remove_env_cleanup_hook(env, wrapper, data); delete data; data = nullptr; @@ -6689,10 +6918,69 @@ bool Env::CleanupHook::IsEmpty() const { } #endif // NAPI_VERSION > 2 +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER +template +inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback) const { + using T = void*; + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + + napi_status status = node_api_post_finalizer( + _env, + details::FinalizeData::WrapperGCWithoutData, + static_cast(nullptr), + finalizeData); + if (status != napi_ok) { + delete finalizeData; + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::PostFinalizer", "invalid arguments"); + } +} + +template +inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback, + T* data) const { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), nullptr}); + + napi_status status = node_api_post_finalizer( + _env, + details::FinalizeData::WrapperGC, + data, + finalizeData); + if (status != napi_ok) { + delete finalizeData; + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::PostFinalizer", "invalid arguments"); + } +} + +template +inline void BasicEnv::PostFinalizer(FinalizerType finalizeCallback, + T* data, + Hint* finalizeHint) const { + details::FinalizeData* finalizeData = + new details::FinalizeData( + {std::move(finalizeCallback), finalizeHint}); + napi_status status = node_api_post_finalizer( + _env, + details::FinalizeData::WrapperGCWithHint, + data, + finalizeData); + if (status != napi_ok) { + delete finalizeData; + NAPI_FATAL_IF_FAILED( + status, "BasicEnv::PostFinalizer", "invalid arguments"); + } +} +#endif // NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + #ifdef NAPI_CPP_CUSTOM_NAMESPACE } // namespace NAPI_CPP_CUSTOM_NAMESPACE #endif -} // namespace Napi +} // namespace Napi #endif // SRC_NAPI_INL_H_ diff --git a/include/napi.h b/include/napi.h index 194c48c..c2e7fe6 100644 --- a/include/napi.h +++ b/include/napi.h @@ -41,22 +41,40 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), #define NAPI_WIDE_TEXT(x) u##x #endif +// Backwards-compatibility to handle the rename of this macro definition, in +// case they are used within userland code. +#ifdef NAPI_CPP_EXCEPTIONS +#define NODE_ADDON_API_CPP_EXCEPTIONS +#endif +#if defined(NODE_ADDON_API_CPP_EXCEPTIONS) && !defined(NAPI_CPP_EXCEPTIONS) +#define NAPI_CPP_EXCEPTIONS +#endif +#ifdef NAPI_DISABLE_CPP_EXCEPTIONS +#define NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS +#endif +#if defined(NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS) && \ + !defined(NAPI_DISABLE_CPP_EXCEPTIONS) +#define NAPI_DISABLE_CPP_EXCEPTIONS +#endif + // If C++ exceptions are not explicitly enabled or disabled, enable them // if exceptions were enabled in the compiler settings. -#if !defined(NAPI_CPP_EXCEPTIONS) && !defined(NAPI_DISABLE_CPP_EXCEPTIONS) +#if !defined(NODE_ADDON_API_CPP_EXCEPTIONS) && \ + !defined(NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS) #if defined(_CPPUNWIND) || defined(__EXCEPTIONS) -#define NAPI_CPP_EXCEPTIONS +#define NODE_ADDON_API_CPP_EXCEPTIONS #else #error Exception support not detected. \ - Define either NAPI_CPP_EXCEPTIONS or NAPI_DISABLE_CPP_EXCEPTIONS. + Define either NODE_ADDON_API_CPP_EXCEPTIONS or NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS. #endif #endif -// If C++ NAPI_CPP_EXCEPTIONS are enabled, NODE_ADDON_API_ENABLE_MAYBE should -// not be set -#if defined(NAPI_CPP_EXCEPTIONS) && defined(NODE_ADDON_API_ENABLE_MAYBE) +// If C++ NODE_ADDON_API_CPP_EXCEPTIONS are enabled, NODE_ADDON_API_ENABLE_MAYBE +// should not be set +#if defined(NODE_ADDON_API_CPP_EXCEPTIONS) && \ + defined(NODE_ADDON_API_ENABLE_MAYBE) #error NODE_ADDON_API_ENABLE_MAYBE should not be set when \ - NAPI_CPP_EXCEPTIONS is defined. + NODE_ADDON_API_CPP_EXCEPTIONS is defined. #endif #ifdef _NOEXCEPT @@ -65,7 +83,7 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), #define NAPI_NOEXCEPT noexcept #endif -#ifdef NAPI_CPP_EXCEPTIONS +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS // When C++ exceptions are enabled, Errors are thrown directly. There is no need // to return anything after the throw statements. The variadic parameter is an @@ -82,7 +100,7 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), #define NAPI_THROW_IF_FAILED_VOID(env, status) \ if ((status) != napi_ok) throw Napi::Error::New(env); -#else // NAPI_CPP_EXCEPTIONS +#else // NODE_ADDON_API_CPP_EXCEPTIONS // When C++ exceptions are disabled, Errors are thrown as JavaScript exceptions, // which are pending until the callback returns to JS. The variadic parameter @@ -114,7 +132,7 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), return; \ } -#endif // NAPI_CPP_EXCEPTIONS +#endif // NODE_ADDON_API_CPP_EXCEPTIONS #ifdef NODE_ADDON_API_ENABLE_MAYBE #define NAPI_MAYBE_THROW_IF_FAILED(env, status, type) \ @@ -179,7 +197,7 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), namespace Napi { #ifdef NAPI_CPP_CUSTOM_NAMESPACE - // NAPI_CPP_CUSTOM_NAMESPACE can be #define'd per-addon to avoid symbol +// NAPI_CPP_CUSTOM_NAMESPACE can be #define'd per-addon to avoid symbol // conflicts between different instances of node-addon-api // First dummy definition of the namespace to make sure that Napi::(name) still @@ -191,46 +209,46 @@ namespace NAPI_CPP_CUSTOM_NAMESPACE { #endif // Forward declarations - class Env; - class Value; - class Boolean; - class Number; +class Env; +class Value; +class Boolean; +class Number; #if NAPI_VERSION > 5 - class BigInt; +class BigInt; #endif // NAPI_VERSION > 5 #if (NAPI_VERSION > 4) - class Date; +class Date; #endif - class String; - class Object; - class Array; - class ArrayBuffer; - class Function; - class Error; - class PropertyDescriptor; - class CallbackInfo; - class TypedArray; - template - class TypedArrayOf; - - using Int8Array = - TypedArrayOf; ///< Typed-array of signed 8-bit integers - using Uint8Array = - TypedArrayOf; ///< Typed-array of unsigned 8-bit integers - using Int16Array = - TypedArrayOf; ///< Typed-array of signed 16-bit integers - using Uint16Array = - TypedArrayOf; ///< Typed-array of unsigned 16-bit integers - using Int32Array = - TypedArrayOf; ///< Typed-array of signed 32-bit integers - using Uint32Array = - TypedArrayOf; ///< Typed-array of unsigned 32-bit integers - using Float32Array = - TypedArrayOf; ///< Typed-array of 32-bit floating-point values - using Float64Array = - TypedArrayOf; ///< Typed-array of 64-bit floating-point values +class String; +class Object; +class Array; +class ArrayBuffer; +class Function; +class Error; +class PropertyDescriptor; +class CallbackInfo; +class TypedArray; +template +class TypedArrayOf; + +using Int8Array = + TypedArrayOf; ///< Typed-array of signed 8-bit integers +using Uint8Array = + TypedArrayOf; ///< Typed-array of unsigned 8-bit integers +using Int16Array = + TypedArrayOf; ///< Typed-array of signed 16-bit integers +using Uint16Array = + TypedArrayOf; ///< Typed-array of unsigned 16-bit integers +using Int32Array = + TypedArrayOf; ///< Typed-array of signed 32-bit integers +using Uint32Array = + TypedArrayOf; ///< Typed-array of unsigned 32-bit integers +using Float32Array = + TypedArrayOf; ///< Typed-array of 32-bit floating-point values +using Float64Array = + TypedArrayOf; ///< Typed-array of 64-bit floating-point values #if NAPI_VERSION > 5 - using BigInt64Array = +using BigInt64Array = TypedArrayOf; ///< Typed array of signed 64-bit integers using BigUint64Array = TypedArrayOf; ///< Typed array of unsigned 64-bit integers @@ -238,9 +256,9 @@ using BigUint64Array = /// Defines the signature of a Node-API C++ module's registration callback /// (init) function. - using ModuleRegisterCallback = Object (*)(Env env, Object exports); +using ModuleRegisterCallback = Object (*)(Env env, Object exports); - class MemoryManagement; +class MemoryManagement; /// A simple Maybe type, representing an object which may or may not have a /// value. @@ -249,58 +267,66 @@ using BigUint64Array = /// either because an exception is thrown, or because an exception is pending, /// e.g. because a previous API call threw an exception that hasn't been /// caught yet. In that case, a "Nothing" value is returned. - template - class Maybe { - public: - bool IsNothing() const; - bool IsJust() const; - - /// Short-hand for Unwrap(), which doesn't return a value. Could be used - /// where the actual value of the Maybe is not needed like Object::Set. - /// If this Maybe is nothing (empty), node-addon-api will crash the - /// process. - void Check() const; - - /// Return the value of type T contained in the Maybe. If this Maybe is - /// nothing (empty), node-addon-api will crash the process. - T Unwrap() const; - - /// Return the value of type T contained in the Maybe, or using a default - /// value if this Maybe is nothing (empty). - T UnwrapOr(const T& default_value) const; - - /// Converts this Maybe to a value of type T in the out. If this Maybe is - /// nothing (empty), `false` is returned and `out` is left untouched. - bool UnwrapTo(T* out) const; - - bool operator==(const Maybe& other) const; - bool operator!=(const Maybe& other) const; - - private: - Maybe(); - explicit Maybe(const T& t); - - bool _has_value; - T _value; - - template - friend Maybe Nothing(); - template - friend Maybe Just(const U& u); - }; +template +class Maybe { + public: + bool IsNothing() const; + bool IsJust() const; - template - inline Maybe Nothing(); + /// Short-hand for Unwrap(), which doesn't return a value. Could be used + /// where the actual value of the Maybe is not needed like Object::Set. + /// If this Maybe is nothing (empty), node-addon-api will crash the + /// process. + void Check() const; - template - inline Maybe Just(const T& t); + /// Return the value of type T contained in the Maybe. If this Maybe is + /// nothing (empty), node-addon-api will crash the process. + T Unwrap() const; + + /// Return the value of type T contained in the Maybe, or using a default + /// value if this Maybe is nothing (empty). + T UnwrapOr(const T& default_value) const; + + /// Converts this Maybe to a value of type T in the out. If this Maybe is + /// nothing (empty), `false` is returned and `out` is left untouched. + bool UnwrapTo(T* out) const; + + bool operator==(const Maybe& other) const; + bool operator!=(const Maybe& other) const; + + private: + Maybe(); + explicit Maybe(const T& t); + + bool _has_value; + T _value; + + template + friend Maybe Nothing(); + template + friend Maybe Just(const U& u); +}; + +template +inline Maybe Nothing(); + +template +inline Maybe Just(const T& t); #if defined(NODE_ADDON_API_ENABLE_MAYBE) - template +template using MaybeOrValue = Maybe; #else - template - using MaybeOrValue = T; +template +using MaybeOrValue = T; +#endif + +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER +using node_addon_api_basic_env = node_api_nogc_env; +using node_addon_api_basic_finalize = node_api_nogc_finalize; +#else +using node_addon_api_basic_env = napi_env; +using node_addon_api_basic_finalize = napi_finalize; #endif /// Environment for Node-API values and operations. @@ -311,38 +337,39 @@ using MaybeOrValue = Maybe; /// Node-API operations within the callback. (Many methods infer the /// environment from the `this` instance that the method is called on.) /// -/// In the future, multiple environments per process may be supported, -/// although current implementations only support one environment per process. +/// Multiple environments may co-exist in a single process or a thread. /// /// In the V8 JavaScript engine, a Node-API environment approximately /// corresponds to an Isolate. - class Env { - private: - napi_env _env; +class BasicEnv { + private: + node_addon_api_basic_env _env; #if NAPI_VERSION > 5 - template + template static void DefaultFini(Env, T* data); template static void DefaultFiniWithHint(Env, DataType* data, HintType* hint); #endif // NAPI_VERSION > 5 - public: - Env(napi_env env); - - operator napi_env() const; - - Object Global() const; - Value Undefined() const; - Value Null() const; - - bool IsExceptionPending() const; - Error GetAndClearPendingException() const; - - MaybeOrValue RunScript(const char* utf8script) const; - MaybeOrValue RunScript(const std::string& utf8script) const; - MaybeOrValue RunScript(String script) const; + public: + BasicEnv(node_addon_api_basic_env env); + + operator node_addon_api_basic_env() const; + + // Without these operator overloads, the error: + // + // Use of overloaded operator '==' is ambiguous (with operand types + // 'Napi::Env' and 'Napi::Env') + // + // ... occurs when comparing foo.Env() == bar.Env() or foo.Env() == nullptr + bool operator==(const BasicEnv& other) const { + return _env == other._env; + }; + bool operator==(std::nullptr_t /*other*/) const { + return _env == nullptr; + }; #if NAPI_VERSION > 2 - template + template class CleanupHook; template @@ -353,12 +380,12 @@ using MaybeOrValue = Maybe; #endif // NAPI_VERSION > 2 #if NAPI_VERSION > 5 - template + template T* GetInstanceData() const; template using Finalizer = void (*)(Env, T*); - template fini = Env::DefaultFini> + template fini = BasicEnv::DefaultFini> void SetInstanceData(T* data) const; template @@ -366,18 +393,18 @@ using MaybeOrValue = Maybe; template fini = - Env::DefaultFiniWithHint> + BasicEnv::DefaultFiniWithHint> void SetInstanceData(DataType* data, HintType* hint) const; #endif // NAPI_VERSION > 5 #if NAPI_VERSION > 2 - template + template class CleanupHook { public: CleanupHook(); - CleanupHook(Env env, Hook hook, Arg* arg); - CleanupHook(Env env, Hook hook); - bool Remove(Env env); + CleanupHook(BasicEnv env, Hook hook, Arg* arg); + CleanupHook(BasicEnv env, Hook hook); + bool Remove(BasicEnv env); bool IsEmpty() const; private: @@ -393,9 +420,42 @@ using MaybeOrValue = Maybe; #endif // NAPI_VERSION > 2 #if NAPI_VERSION > 8 - const char* GetModuleFileName() const; + const char* GetModuleFileName() const; #endif // NAPI_VERSION > 8 - }; + +#ifdef NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + template + inline void PostFinalizer(FinalizerType finalizeCallback) const; + + template + inline void PostFinalizer(FinalizerType finalizeCallback, T* data) const; + + template + inline void PostFinalizer(FinalizerType finalizeCallback, + T* data, + Hint* finalizeHint) const; +#endif // NODE_API_EXPERIMENTAL_HAS_POST_FINALIZER + + friend class Env; +}; + +class Env : public BasicEnv { + public: + Env(napi_env env); + + operator napi_env() const; + + Object Global() const; + Value Undefined() const; + Value Null() const; + + bool IsExceptionPending() const; + Error GetAndClearPendingException() const; + + MaybeOrValue RunScript(const char* utf8script) const; + MaybeOrValue RunScript(const std::string& utf8script) const; + MaybeOrValue RunScript(String script) const; +}; /// A JavaScript value of unknown type. /// @@ -410,166 +470,172 @@ using MaybeOrValue = Maybe; /// /// Napi::Value anotherValue = ... /// bool isTruthy = anotherValue.ToBoolean(); // Coerce to a boolean value - class Value { - public: - Value(); ///< Creates a new _empty_ Value instance. - Value(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. +class Value { + public: + Value(); ///< Creates a new _empty_ Value instance. + Value(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. + + /// Creates a JS value from a C++ primitive. + /// + /// `value` may be any of: + /// - bool + /// - Any integer type + /// - Any floating point type + /// - const char* (encoded using UTF-8, null-terminated) + /// - const char16_t* (encoded using UTF-16-LE, null-terminated) + /// - std::string (encoded using UTF-8) + /// - std::u16string + /// - napi::Value + /// - napi_value + template + static Value From(napi_env env, const T& value); + + static void CheckCast(napi_env env, napi_value value); + + /// Converts to a Node-API value primitive. + /// + /// If the instance is _empty_, this returns `nullptr`. + operator napi_value() const; + + /// Tests if this value strictly equals another value. + bool operator==(const Value& other) const; + + /// Tests if this value does not strictly equal another value. + bool operator!=(const Value& other) const; - /// Creates a JS value from a C++ primitive. - /// - /// `value` may be any of: - /// - bool - /// - Any integer type - /// - Any floating point type - /// - const char* (encoded using UTF-8, null-terminated) - /// - const char16_t* (encoded using UTF-16-LE, null-terminated) - /// - std::string (encoded using UTF-8) - /// - std::u16string - /// - napi::Value - /// - napi_value - template - static Value From(napi_env env, const T& value); - - /// Converts to a Node-API value primitive. - /// - /// If the instance is _empty_, this returns `nullptr`. - operator napi_value() const; - - /// Tests if this value strictly equals another value. - bool operator==(const Value& other) const; - - /// Tests if this value does not strictly equal another value. - bool operator!=(const Value& other) const; - - /// Tests if this value strictly equals another value. - bool StrictEquals(const Value& other) const; - - /// Gets the environment the value is associated with. - Napi::Env Env() const; - - /// Checks if the value is empty (uninitialized). - /// - /// An empty value is invalid, and most attempts to perform an operation on an - /// empty value will result in an exception. Note an empty value is distinct - /// from JavaScript `null` or `undefined`, which are valid values. - /// - /// When C++ exceptions are disabled at compile time, a method with a `Value` - /// return type may return an empty value to indicate a pending exception. So - /// when not using C++ exceptions, callers should check whether the value is - /// empty before attempting to use it. - bool IsEmpty() const; - - napi_valuetype Type() const; ///< Gets the type of the value. - - bool IsUndefined() - const; ///< Tests if a value is an undefined JavaScript value. - bool IsNull() const; ///< Tests if a value is a null JavaScript value. - bool IsBoolean() const; ///< Tests if a value is a JavaScript boolean. - bool IsNumber() const; ///< Tests if a value is a JavaScript number. + /// Tests if this value strictly equals another value. + bool StrictEquals(const Value& other) const; + + /// Gets the environment the value is associated with. + Napi::Env Env() const; + + /// Checks if the value is empty (uninitialized). + /// + /// An empty value is invalid, and most attempts to perform an operation on an + /// empty value will result in an exception. Note an empty value is distinct + /// from JavaScript `null` or `undefined`, which are valid values. + /// + /// When C++ exceptions are disabled at compile time, a method with a `Value` + /// return type may return an empty value to indicate a pending exception. So + /// when not using C++ exceptions, callers should check whether the value is + /// empty before attempting to use it. + bool IsEmpty() const; + + napi_valuetype Type() const; ///< Gets the type of the value. + + bool IsUndefined() + const; ///< Tests if a value is an undefined JavaScript value. + bool IsNull() const; ///< Tests if a value is a null JavaScript value. + bool IsBoolean() const; ///< Tests if a value is a JavaScript boolean. + bool IsNumber() const; ///< Tests if a value is a JavaScript number. #if NAPI_VERSION > 5 - bool IsBigInt() const; ///< Tests if a value is a JavaScript bigint. + bool IsBigInt() const; ///< Tests if a value is a JavaScript bigint. #endif // NAPI_VERSION > 5 #if (NAPI_VERSION > 4) - bool IsDate() const; ///< Tests if a value is a JavaScript date. + bool IsDate() const; ///< Tests if a value is a JavaScript date. #endif - bool IsString() const; ///< Tests if a value is a JavaScript string. + bool IsString() const; ///< Tests if a value is a JavaScript string. #ifndef OHOS - bool IsSymbol() const; ///< Tests if a value is a JavaScript symbol. + bool IsSymbol() const; ///< Tests if a value is a JavaScript symbol. #endif - bool IsArray() const; ///< Tests if a value is a JavaScript array. - bool IsArrayBuffer() - const; ///< Tests if a value is a JavaScript array buffer. - bool IsTypedArray() const; ///< Tests if a value is a JavaScript typed array. - bool IsObject() const; ///< Tests if a value is a JavaScript object. - bool IsFunction() const; ///< Tests if a value is a JavaScript function. - bool IsPromise() const; ///< Tests if a value is a JavaScript promise. - bool IsDataView() const; ///< Tests if a value is a JavaScript data view. - bool IsBuffer() const; ///< Tests if a value is a Node buffer. - bool IsExternal() const; ///< Tests if a value is a pointer to external data. - - /// Casts to another type of `Napi::Value`, when the actual type is known or - /// assumed. - /// - /// This conversion does NOT coerce the type. Calling any methods - /// inappropriate for the actual value type will throw `Napi::Error`. - /// - /// If `NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS` is defined, this method - /// asserts that the actual type is the expected type. - template - T As() const; - - MaybeOrValue ToBoolean() - const; ///< Coerces a value to a JavaScript boolean. - MaybeOrValue ToNumber() - const; ///< Coerces a value to a JavaScript number. - MaybeOrValue ToString() - const; ///< Coerces a value to a JavaScript string. - MaybeOrValue ToObject() - const; ///< Coerces a value to a JavaScript object. - - protected: - /// !cond INTERNAL - napi_env _env; - napi_value _value; - /// !endcond - }; + bool IsArray() const; ///< Tests if a value is a JavaScript array. + bool IsArrayBuffer() + const; ///< Tests if a value is a JavaScript array buffer. + bool IsTypedArray() const; ///< Tests if a value is a JavaScript typed array. + bool IsObject() const; ///< Tests if a value is a JavaScript object. + bool IsFunction() const; ///< Tests if a value is a JavaScript function. + bool IsPromise() const; ///< Tests if a value is a JavaScript promise. + bool IsDataView() const; ///< Tests if a value is a JavaScript data view. + bool IsBuffer() const; ///< Tests if a value is a Node buffer. + bool IsExternal() const; ///< Tests if a value is a pointer to external data. + + /// Casts to another type of `Napi::Value`, when the actual type is known or + /// assumed. + /// + /// This conversion does NOT coerce the type. Calling any methods + /// inappropriate for the actual value type will throw `Napi::Error`. + /// + /// If `NODE_ADDON_API_ENABLE_TYPE_CHECK_ON_AS` is defined, this method + /// asserts that the actual type is the expected type. + template + T As() const; + + // Unsafe Value::As(), should be avoided. + template + T UnsafeAs() const; + + MaybeOrValue ToBoolean() + const; ///< Coerces a value to a JavaScript boolean. + MaybeOrValue ToNumber() + const; ///< Coerces a value to a JavaScript number. + MaybeOrValue ToString() + const; ///< Coerces a value to a JavaScript string. + MaybeOrValue ToObject() + const; ///< Coerces a value to a JavaScript object. + + protected: + /// !cond INTERNAL + napi_env _env; + napi_value _value; + /// !endcond +}; /// A JavaScript boolean value. - class Boolean : public Value { - public: - static Boolean New(napi_env env, ///< Node-API environment - bool value ///< Boolean value - ); +class Boolean : public Value { + public: + static Boolean New(napi_env env, ///< Node-API environment + bool value ///< Boolean value + ); - static void CheckCast(napi_env env, napi_value value); + static void CheckCast(napi_env env, napi_value value); - Boolean(); ///< Creates a new _empty_ Boolean instance. - Boolean(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. + Boolean(); ///< Creates a new _empty_ Boolean instance. + Boolean(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. - operator bool() const; ///< Converts a Boolean value to a boolean primitive. - bool Value() const; ///< Converts a Boolean value to a boolean primitive. - }; + operator bool() const; ///< Converts a Boolean value to a boolean primitive. + bool Value() const; ///< Converts a Boolean value to a boolean primitive. +}; /// A JavaScript number value. - class Number : public Value { - public: - static Number New(napi_env env, ///< Node-API environment - double value ///< Number value - ); +class Number : public Value { + public: + static Number New(napi_env env, ///< Node-API environment + double value ///< Number value + ); - static void CheckCast(napi_env env, napi_value value); + static void CheckCast(napi_env env, napi_value value); - Number(); ///< Creates a new _empty_ Number instance. - Number(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. + Number(); ///< Creates a new _empty_ Number instance. + Number(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. - operator int32_t() - const; ///< Converts a Number value to a 32-bit signed integer value. - operator uint32_t() - const; ///< Converts a Number value to a 32-bit unsigned integer value. - operator int64_t() - const; ///< Converts a Number value to a 64-bit signed integer value. - operator float() - const; ///< Converts a Number value to a 32-bit floating-point value. - operator double() - const; ///< Converts a Number value to a 64-bit floating-point value. - - int32_t Int32Value() - const; ///< Converts a Number value to a 32-bit signed integer value. - uint32_t Uint32Value() - const; ///< Converts a Number value to a 32-bit unsigned integer value. - int64_t Int64Value() - const; ///< Converts a Number value to a 64-bit signed integer value. - float FloatValue() - const; ///< Converts a Number value to a 32-bit floating-point value. - double DoubleValue() - const; ///< Converts a Number value to a 64-bit floating-point value. - }; + operator int32_t() + const; ///< Converts a Number value to a 32-bit signed integer value. + operator uint32_t() + const; ///< Converts a Number value to a 32-bit unsigned integer value. + operator int64_t() + const; ///< Converts a Number value to a 64-bit signed integer value. + operator float() + const; ///< Converts a Number value to a 32-bit floating-point value. + operator double() + const; ///< Converts a Number value to a 64-bit floating-point value. + + int32_t Int32Value() + const; ///< Converts a Number value to a 32-bit signed integer value. + uint32_t Uint32Value() + const; ///< Converts a Number value to a 32-bit unsigned integer value. + int64_t Int64Value() + const; ///< Converts a Number value to a 64-bit signed integer value. + float FloatValue() + const; ///< Converts a Number value to a 32-bit floating-point value. + double DoubleValue() + const; ///< Converts a Number value to a 64-bit floating-point value. +}; #if NAPI_VERSION > 5 - /// A JavaScript bigint value. +/// A JavaScript bigint value. class BigInt : public Value { public: static BigInt New(napi_env env, ///< Node-API environment @@ -614,7 +680,7 @@ class BigInt : public Value { #endif // NAPI_VERSION > 5 #if (NAPI_VERSION > 4) - /// A JavaScript date value. +/// A JavaScript date value. class Date : public Value { public: /// Creates a new Date value from a double primitive. @@ -633,416 +699,419 @@ class Date : public Value { #endif /// A JavaScript string or symbol value (that can be used as a property name). - class Name : public Value { - public: - static void CheckCast(napi_env env, napi_value value); +class Name : public Value { + public: + static void CheckCast(napi_env env, napi_value value); - Name(); ///< Creates a new _empty_ Name instance. - Name(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. - }; + Name(); ///< Creates a new _empty_ Name instance. + Name(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. +}; /// A JavaScript string value. - class String : public Name { - public: - /// Creates a new String value from a UTF-8 encoded C++ string. - static String New(napi_env env, ///< Node-API environment - const std::string& value ///< UTF-8 encoded C++ string - ); - - /// Creates a new String value from a UTF-16 encoded C++ string. - static String New(napi_env env, ///< Node-API environment - const std::u16string& value ///< UTF-16 encoded C++ string - ); - - /// Creates a new String value from a UTF-8 encoded C string. - static String New( - napi_env env, ///< Node-API environment - const char* value ///< UTF-8 encoded null-terminated C string - ); - - /// Creates a new String value from a UTF-16 encoded C string. - static String New( - napi_env env, ///< Node-API environment - const char16_t* value ///< UTF-16 encoded null-terminated C string - ); - - /// Creates a new String value from a UTF-8 encoded C string with specified - /// length. - static String New(napi_env env, ///< Node-API environment - const char* value, ///< UTF-8 encoded C string (not - ///< necessarily null-terminated) - size_t length ///< length of the string in bytes - ); - - /// Creates a new String value from a UTF-16 encoded C string with specified - /// length. - static String New( - napi_env env, ///< Node-API environment - const char16_t* value, ///< UTF-16 encoded C string (not necessarily - ///< null-terminated) - size_t length ///< Length of the string in 2-byte code units - ); - - /// Creates a new String based on the original object's type. - /// - /// `value` may be any of: - /// - const char* (encoded using UTF-8, null-terminated) - /// - const char16_t* (encoded using UTF-16-LE, null-terminated) - /// - std::string (encoded using UTF-8) - /// - std::u16string - template - static String From(napi_env env, const T& value); - - static void CheckCast(napi_env env, napi_value value); - - String(); ///< Creates a new _empty_ String instance. - String(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. +class String : public Name { + public: + /// Creates a new String value from a UTF-8 encoded C++ string. + static String New(napi_env env, ///< Node-API environment + const std::string& value ///< UTF-8 encoded C++ string + ); - operator std::string() - const; ///< Converts a String value to a UTF-8 encoded C++ string. - operator std::u16string() - const; ///< Converts a String value to a UTF-16 encoded C++ string. - std::string Utf8Value() - const; ///< Converts a String value to a UTF-8 encoded C++ string. - std::u16string Utf16Value() - const; ///< Converts a String value to a UTF-16 encoded C++ string. - }; + /// Creates a new String value from a UTF-16 encoded C++ string. + static String New(napi_env env, ///< Node-API environment + const std::u16string& value ///< UTF-16 encoded C++ string + ); + + /// Creates a new String value from a UTF-8 encoded C string. + static String New( + napi_env env, ///< Node-API environment + const char* value ///< UTF-8 encoded null-terminated C string + ); + + /// Creates a new String value from a UTF-16 encoded C string. + static String New( + napi_env env, ///< Node-API environment + const char16_t* value ///< UTF-16 encoded null-terminated C string + ); + + /// Creates a new String value from a UTF-8 encoded C string with specified + /// length. + static String New(napi_env env, ///< Node-API environment + const char* value, ///< UTF-8 encoded C string (not + ///< necessarily null-terminated) + size_t length ///< length of the string in bytes + ); + + /// Creates a new String value from a UTF-16 encoded C string with specified + /// length. + static String New( + napi_env env, ///< Node-API environment + const char16_t* value, ///< UTF-16 encoded C string (not necessarily + ///< null-terminated) + size_t length ///< Length of the string in 2-byte code units + ); + + /// Creates a new String based on the original object's type. + /// + /// `value` may be any of: + /// - const char* (encoded using UTF-8, null-terminated) + /// - const char16_t* (encoded using UTF-16-LE, null-terminated) + /// - std::string (encoded using UTF-8) + /// - std::u16string + template + static String From(napi_env env, const T& value); + + static void CheckCast(napi_env env, napi_value value); + + String(); ///< Creates a new _empty_ String instance. + String(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. + + operator std::string() + const; ///< Converts a String value to a UTF-8 encoded C++ string. + operator std::u16string() + const; ///< Converts a String value to a UTF-16 encoded C++ string. + std::string Utf8Value() + const; ///< Converts a String value to a UTF-8 encoded C++ string. + std::u16string Utf16Value() + const; ///< Converts a String value to a UTF-16 encoded C++ string. +}; #ifndef OHOS /// A JavaScript symbol value. - class Symbol : public Name { - public: - /// Creates a new Symbol value with an optional description. - static Symbol New( - napi_env env, ///< Node-API environment - const char* description = - nullptr ///< Optional UTF-8 encoded null-terminated C string - /// describing the symbol - ); - - /// Creates a new Symbol value with a description. - static Symbol New( - napi_env env, ///< Node-API environment - const std::string& - description ///< UTF-8 encoded C++ string describing the symbol - ); - - /// Creates a new Symbol value with a description. - static Symbol New(napi_env env, ///< Node-API environment - String description ///< String value describing the symbol - ); - - /// Creates a new Symbol value with a description. - static Symbol New( - napi_env env, ///< Node-API environment - napi_value description ///< String value describing the symbol - ); - - /// Get a public Symbol (e.g. Symbol.iterator). - static MaybeOrValue WellKnown(napi_env, const std::string& name); - - // Create a symbol in the global registry, UTF-8 Encoded cpp string - static MaybeOrValue For(napi_env env, const std::string& description); - - // Create a symbol in the global registry, C style string (null terminated) - static MaybeOrValue For(napi_env env, const char* description); - - // Create a symbol in the global registry, String value describing the symbol - static MaybeOrValue For(napi_env env, String description); - - // Create a symbol in the global registry, napi_value describing the symbol - static MaybeOrValue For(napi_env env, napi_value description); - - static void CheckCast(napi_env env, napi_value value); - - Symbol(); ///< Creates a new _empty_ Symbol instance. - Symbol(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. - }; +class Symbol : public Name { + public: + /// Creates a new Symbol value with an optional description. + static Symbol New( + napi_env env, ///< Node-API environment + const char* description = + nullptr ///< Optional UTF-8 encoded null-terminated C string + /// describing the symbol + ); + + /// Creates a new Symbol value with a description. + static Symbol New( + napi_env env, ///< Node-API environment + const std::string& + description ///< UTF-8 encoded C++ string describing the symbol + ); + + /// Creates a new Symbol value with a description. + static Symbol New(napi_env env, ///< Node-API environment + String description ///< String value describing the symbol + ); + + /// Creates a new Symbol value with a description. + static Symbol New( + napi_env env, ///< Node-API environment + napi_value description ///< String value describing the symbol + ); + + /// Get a public Symbol (e.g. Symbol.iterator). + static MaybeOrValue WellKnown(napi_env, const std::string& name); + + // Create a symbol in the global registry, UTF-8 Encoded cpp string + static MaybeOrValue For(napi_env env, const std::string& description); + + // Create a symbol in the global registry, C style string (null terminated) + static MaybeOrValue For(napi_env env, const char* description); + + // Create a symbol in the global registry, String value describing the symbol + static MaybeOrValue For(napi_env env, String description); + + // Create a symbol in the global registry, napi_value describing the symbol + static MaybeOrValue For(napi_env env, napi_value description); + + static void CheckCast(napi_env env, napi_value value); + + Symbol(); ///< Creates a new _empty_ Symbol instance. + Symbol(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. +}; #endif - class TypeTaggable : public Value { - public: +class TypeTaggable : public Value { + public: #if NAPI_VERSION >= 8 - void TypeTag(const napi_type_tag* type_tag) const; + void TypeTag(const napi_type_tag* type_tag) const; bool CheckTypeTag(const napi_type_tag* type_tag) const; #endif // NAPI_VERSION >= 8 - protected: - TypeTaggable(); - TypeTaggable(napi_env env, napi_value value); - }; + protected: + TypeTaggable(); + TypeTaggable(napi_env env, napi_value value); +}; /// A JavaScript object value. - class Object : public TypeTaggable { - public: - /// Enables property and element assignments using indexing syntax. - /// - /// This is a convenient helper to get and set object properties. As - /// getting and setting object properties may throw with JavaScript - /// exceptions, it is notable that these operations may fail. - /// When NODE_ADDON_API_ENABLE_MAYBE is defined, the process will abort - /// on JavaScript exceptions. - /// - /// Example: - /// - /// Napi::Value propertyValue = object1['A']; - /// object2['A'] = propertyValue; - /// Napi::Value elementValue = array[0]; - /// array[1] = elementValue; - template - class PropertyLValue { - public: - /// Converts an L-value to a value. - operator Value() const; - - /// Assigns a value to the property. The type of value can be - /// anything supported by `Object::Set`. - template - PropertyLValue& operator=(ValueType value); - - private: - PropertyLValue() = delete; - PropertyLValue(Object object, Key key); - napi_env _env; - napi_value _object; - Key _key; - - friend class Napi::Object; - }; - - /// Creates a new Object value. - static Object New(napi_env env ///< Node-API environment - ); - - static void CheckCast(napi_env env, napi_value value); - - Object(); ///< Creates a new _empty_ Object instance. - Object(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. +class Object : public TypeTaggable { + public: + /// Enables property and element assignments using indexing syntax. + /// + /// This is a convenient helper to get and set object properties. As + /// getting and setting object properties may throw with JavaScript + /// exceptions, it is notable that these operations may fail. + /// When NODE_ADDON_API_ENABLE_MAYBE is defined, the process will abort + /// on JavaScript exceptions. + /// + /// Example: + /// + /// Napi::Value propertyValue = object1['A']; + /// object2['A'] = propertyValue; + /// Napi::Value elementValue = array[0]; + /// array[1] = elementValue; + template + class PropertyLValue { + public: + /// Converts an L-value to a value. + operator Value() const; - /// Gets or sets a named property. - PropertyLValue operator[]( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ); - - /// Gets or sets a named property. - PropertyLValue operator[]( - const std::string& utf8name ///< UTF-8 encoded property name - ); - - /// Gets or sets an indexed property or array element. - PropertyLValue operator[]( - uint32_t index /// Property / element index - ); - - /// Gets or sets an indexed property or array element. - PropertyLValue operator[](Value index /// Property / element index - ) const; - - /// Gets a named property. - MaybeOrValue operator[]( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ) const; - - /// Gets a named property. - MaybeOrValue operator[]( - const std::string& utf8name ///< UTF-8 encoded property name - ) const; - - /// Gets an indexed property or array element. - MaybeOrValue operator[](uint32_t index ///< Property / element index - ) const; - - /// Checks whether a property is present. - MaybeOrValue Has(napi_value key ///< Property key primitive - ) const; - - /// Checks whether a property is present. - MaybeOrValue Has(Value key ///< Property key - ) const; - - /// Checks whether a named property is present. - MaybeOrValue Has( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ) const; - - /// Checks whether a named property is present. - MaybeOrValue Has( - const std::string& utf8name ///< UTF-8 encoded property name - ) const; - - /// Checks whether a own property is present. - MaybeOrValue HasOwnProperty(napi_value key ///< Property key primitive - ) const; - - /// Checks whether a own property is present. - MaybeOrValue HasOwnProperty(Value key ///< Property key - ) const; - - /// Checks whether a own property is present. - MaybeOrValue HasOwnProperty( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ) const; - - /// Checks whether a own property is present. - MaybeOrValue HasOwnProperty( - const std::string& utf8name ///< UTF-8 encoded property name - ) const; - - /// Gets a property. - MaybeOrValue Get(napi_value key ///< Property key primitive - ) const; - - /// Gets a property. - MaybeOrValue Get(Value key ///< Property key - ) const; - - /// Gets a named property. - MaybeOrValue Get( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ) const; - - /// Gets a named property. - MaybeOrValue Get( - const std::string& utf8name ///< UTF-8 encoded property name - ) const; - - /// Sets a property. - template - MaybeOrValue Set(napi_value key, ///< Property key primitive - const ValueType& value ///< Property value primitive - ) const; - - /// Sets a property. - template - MaybeOrValue Set(Value key, ///< Property key - const ValueType& value ///< Property value - ) const; - - /// Sets a named property. - template - MaybeOrValue Set( - const char* utf8name, ///< UTF-8 encoded null-terminated property name - const ValueType& value) const; - - /// Sets a named property. - template - MaybeOrValue Set( - const std::string& utf8name, ///< UTF-8 encoded property name - const ValueType& value ///< Property value primitive - ) const; - - /// Delete property. - MaybeOrValue Delete(napi_value key ///< Property key primitive - ) const; - - /// Delete property. - MaybeOrValue Delete(Value key ///< Property key - ) const; - - /// Delete property. - MaybeOrValue Delete( - const char* utf8name ///< UTF-8 encoded null-terminated property name - ) const; - - /// Delete property. - MaybeOrValue Delete( - const std::string& utf8name ///< UTF-8 encoded property name - ) const; - - /// Checks whether an indexed property is present. - MaybeOrValue Has(uint32_t index ///< Property / element index - ) const; - - /// Gets an indexed property or array element. - MaybeOrValue Get(uint32_t index ///< Property / element index - ) const; - - /// Sets an indexed property or array element. - template - MaybeOrValue Set(uint32_t index, ///< Property / element index - const ValueType& value ///< Property value primitive - ) const; - - /// Deletes an indexed property or array element. - MaybeOrValue Delete(uint32_t index ///< Property / element index - ) const; - - /// This operation can fail in case of Proxy.[[OwnPropertyKeys]] and - /// Proxy.[[GetOwnProperty]] calling into JavaScript. See: - /// - - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys - /// - - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p - MaybeOrValue GetPropertyNames() const; ///< Get all property names - - /// Defines a property on the object. - /// - /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling - /// into JavaScript. See - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc - MaybeOrValue DefineProperty( - const PropertyDescriptor& - property ///< Descriptor for the property to be defined - ) const; - - /// Defines properties on the object. - /// - /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling - /// into JavaScript. See - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc - MaybeOrValue DefineProperties( - const std::initializer_list& properties - ///< List of descriptors for the properties to be defined - ) const; - - /// Defines properties on the object. - /// - /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling - /// into JavaScript. See - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc - MaybeOrValue DefineProperties( - const std::vector& properties - ///< Vector of descriptors for the properties to be defined - ) const; - - /// Checks if an object is an instance created by a constructor function. - /// - /// This is equivalent to the JavaScript `instanceof` operator. - /// - /// This operation can fail in case of Proxy.[[GetPrototypeOf]] calling into - /// JavaScript. - /// See - /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof - MaybeOrValue InstanceOf( - const Function& constructor ///< Constructor function - ) const; - - template - inline void AddFinalizer(Finalizer finalizeCallback, T* data) const; - - template - inline void AddFinalizer(Finalizer finalizeCallback, - T* data, - Hint* finalizeHint) const; + /// Assigns a value to the property. The type of value can be + /// anything supported by `Object::Set`. + template + PropertyLValue& operator=(ValueType value); -#ifdef NAPI_CPP_EXCEPTIONS - class const_iterator; + /// Converts an L-value to a value. For convenience. + Value AsValue() const; + + private: + PropertyLValue() = delete; + PropertyLValue(Object object, Key key); + napi_env _env; + napi_value _object; + Key _key; + + friend class Napi::Object; + }; - inline const_iterator begin() const; + /// Creates a new Object value. + static Object New(napi_env env ///< Node-API environment + ); - inline const_iterator end() const; + static void CheckCast(napi_env env, napi_value value); - class iterator; + Object(); ///< Creates a new _empty_ Object instance. + Object(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. - inline iterator begin(); + /// Gets or sets a named property. + PropertyLValue operator[]( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ); - inline iterator end(); -#endif // NAPI_CPP_EXCEPTIONS + /// Gets or sets a named property. + PropertyLValue operator[]( + const std::string& utf8name ///< UTF-8 encoded property name + ); + + /// Gets or sets an indexed property or array element. + PropertyLValue operator[]( + uint32_t index /// Property / element index + ); + + /// Gets or sets an indexed property or array element. + PropertyLValue operator[](Value index /// Property / element index + ) const; + + /// Gets a named property. + MaybeOrValue operator[]( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ) const; + + /// Gets a named property. + MaybeOrValue operator[]( + const std::string& utf8name ///< UTF-8 encoded property name + ) const; + + /// Gets an indexed property or array element. + MaybeOrValue operator[](uint32_t index ///< Property / element index + ) const; + + /// Checks whether a property is present. + MaybeOrValue Has(napi_value key ///< Property key primitive + ) const; + + /// Checks whether a property is present. + MaybeOrValue Has(Value key ///< Property key + ) const; + + /// Checks whether a named property is present. + MaybeOrValue Has( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ) const; + + /// Checks whether a named property is present. + MaybeOrValue Has( + const std::string& utf8name ///< UTF-8 encoded property name + ) const; + + /// Checks whether a own property is present. + MaybeOrValue HasOwnProperty(napi_value key ///< Property key primitive + ) const; + + /// Checks whether a own property is present. + MaybeOrValue HasOwnProperty(Value key ///< Property key + ) const; + + /// Checks whether a own property is present. + MaybeOrValue HasOwnProperty( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ) const; + + /// Checks whether a own property is present. + MaybeOrValue HasOwnProperty( + const std::string& utf8name ///< UTF-8 encoded property name + ) const; + + /// Gets a property. + MaybeOrValue Get(napi_value key ///< Property key primitive + ) const; + + /// Gets a property. + MaybeOrValue Get(Value key ///< Property key + ) const; + + /// Gets a named property. + MaybeOrValue Get( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ) const; + + /// Gets a named property. + MaybeOrValue Get( + const std::string& utf8name ///< UTF-8 encoded property name + ) const; + + /// Sets a property. + template + MaybeOrValue Set(napi_value key, ///< Property key primitive + const ValueType& value ///< Property value primitive + ) const; + + /// Sets a property. + template + MaybeOrValue Set(Value key, ///< Property key + const ValueType& value ///< Property value + ) const; + + /// Sets a named property. + template + MaybeOrValue Set( + const char* utf8name, ///< UTF-8 encoded null-terminated property name + const ValueType& value) const; + + /// Sets a named property. + template + MaybeOrValue Set( + const std::string& utf8name, ///< UTF-8 encoded property name + const ValueType& value ///< Property value primitive + ) const; + + /// Delete property. + MaybeOrValue Delete(napi_value key ///< Property key primitive + ) const; + + /// Delete property. + MaybeOrValue Delete(Value key ///< Property key + ) const; + + /// Delete property. + MaybeOrValue Delete( + const char* utf8name ///< UTF-8 encoded null-terminated property name + ) const; + + /// Delete property. + MaybeOrValue Delete( + const std::string& utf8name ///< UTF-8 encoded property name + ) const; + + /// Checks whether an indexed property is present. + MaybeOrValue Has(uint32_t index ///< Property / element index + ) const; + + /// Gets an indexed property or array element. + MaybeOrValue Get(uint32_t index ///< Property / element index + ) const; + + /// Sets an indexed property or array element. + template + MaybeOrValue Set(uint32_t index, ///< Property / element index + const ValueType& value ///< Property value primitive + ) const; + + /// Deletes an indexed property or array element. + MaybeOrValue Delete(uint32_t index ///< Property / element index + ) const; + + /// This operation can fail in case of Proxy.[[OwnPropertyKeys]] and + /// Proxy.[[GetOwnProperty]] calling into JavaScript. See: + /// - + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-ownpropertykeys + /// - + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p + MaybeOrValue GetPropertyNames() const; ///< Get all property names + + /// Defines a property on the object. + /// + /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling + /// into JavaScript. See + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc + MaybeOrValue DefineProperty( + const PropertyDescriptor& + property ///< Descriptor for the property to be defined + ) const; + + /// Defines properties on the object. + /// + /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling + /// into JavaScript. See + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc + MaybeOrValue DefineProperties( + const std::initializer_list& properties + ///< List of descriptors for the properties to be defined + ) const; + + /// Defines properties on the object. + /// + /// This operation can fail in case of Proxy.[[DefineOwnProperty]] calling + /// into JavaScript. See + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc + MaybeOrValue DefineProperties( + const std::vector& properties + ///< Vector of descriptors for the properties to be defined + ) const; + + /// Checks if an object is an instance created by a constructor function. + /// + /// This is equivalent to the JavaScript `instanceof` operator. + /// + /// This operation can fail in case of Proxy.[[GetPrototypeOf]] calling into + /// JavaScript. + /// See + /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof + MaybeOrValue InstanceOf( + const Function& constructor ///< Constructor function + ) const; + + template + inline void AddFinalizer(Finalizer finalizeCallback, T* data) const; + + template + inline void AddFinalizer(Finalizer finalizeCallback, + T* data, + Hint* finalizeHint) const; + +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + class const_iterator; + + inline const_iterator begin() const; + + inline const_iterator end() const; + + class iterator; + + inline iterator begin(); + + inline iterator end(); +#endif // NODE_ADDON_API_CPP_EXCEPTIONS #if NAPI_VERSION >= 8 - /// This operation can fail in case of Proxy.[[GetPrototypeOf]] calling into + /// This operation can fail in case of Proxy.[[GetPrototypeOf]] calling into /// JavaScript. /// See /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof @@ -1053,163 +1122,163 @@ class Date : public Value { /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getprototypeof MaybeOrValue Seal() const; #endif // NAPI_VERSION >= 8 - }; +}; - template - class External : public TypeTaggable { - public: - static External New(napi_env env, T* data); - - // Finalizer must implement `void operator()(Env env, T* data)`. - template - static External New(napi_env env, T* data, Finalizer finalizeCallback); - // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. - template - static External New(napi_env env, - T* data, - Finalizer finalizeCallback, - Hint* finalizeHint); +template +class External : public TypeTaggable { + public: + static External New(napi_env env, T* data); + + // Finalizer must implement `void operator()(Env env, T* data)`. + template + static External New(napi_env env, T* data, Finalizer finalizeCallback); + // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. + template + static External New(napi_env env, + T* data, + Finalizer finalizeCallback, + Hint* finalizeHint); - static void CheckCast(napi_env env, napi_value value); + static void CheckCast(napi_env env, napi_value value); - External(); - External(napi_env env, napi_value value); + External(); + External(napi_env env, napi_value value); - T* Data() const; - }; + T* Data() const; +}; - class Array : public Object { - public: - static Array New(napi_env env); - static Array New(napi_env env, size_t length); +class Array : public Object { + public: + static Array New(napi_env env); + static Array New(napi_env env, size_t length); - static void CheckCast(napi_env env, napi_value value); + static void CheckCast(napi_env env, napi_value value); - Array(); - Array(napi_env env, napi_value value); + Array(); + Array(napi_env env, napi_value value); - uint32_t Length() const; - }; + uint32_t Length() const; +}; -#ifdef NAPI_CPP_EXCEPTIONS - class Object::const_iterator { - private: - enum class Type { BEGIN, END }; +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS +class Object::const_iterator { + private: + enum class Type { BEGIN, END }; - inline const_iterator(const Object* object, const Type type); + inline const_iterator(const Object* object, const Type type); - public: - inline const_iterator& operator++(); + public: + inline const_iterator& operator++(); - inline bool operator==(const const_iterator& other) const; + inline bool operator==(const const_iterator& other) const; - inline bool operator!=(const const_iterator& other) const; + inline bool operator!=(const const_iterator& other) const; - inline const std::pair> operator*() - const; + inline const std::pair> operator*() + const; - private: - const Napi::Object* _object; - Array _keys; - uint32_t _index; + private: + const Napi::Object* _object; + Array _keys; + uint32_t _index; - friend class Object; - }; + friend class Object; +}; - class Object::iterator { - private: - enum class Type { BEGIN, END }; +class Object::iterator { + private: + enum class Type { BEGIN, END }; - inline iterator(Object* object, const Type type); + inline iterator(Object* object, const Type type); - public: - inline iterator& operator++(); + public: + inline iterator& operator++(); - inline bool operator==(const iterator& other) const; + inline bool operator==(const iterator& other) const; - inline bool operator!=(const iterator& other) const; + inline bool operator!=(const iterator& other) const; - inline std::pair> operator*(); + inline std::pair> operator*(); - private: - Napi::Object* _object; - Array _keys; - uint32_t _index; + private: + Napi::Object* _object; + Array _keys; + uint32_t _index; - friend class Object; - }; -#endif // NAPI_CPP_EXCEPTIONS + friend class Object; +}; +#endif // NODE_ADDON_API_CPP_EXCEPTIONS /// A JavaScript array buffer value. - class ArrayBuffer : public Object { - public: - /// Creates a new ArrayBuffer instance over a new automatically-allocated - /// buffer. - static ArrayBuffer New( - napi_env env, ///< Node-API environment - size_t byteLength ///< Length of the buffer to be allocated, in bytes - ); +class ArrayBuffer : public Object { + public: + /// Creates a new ArrayBuffer instance over a new automatically-allocated + /// buffer. + static ArrayBuffer New( + napi_env env, ///< Node-API environment + size_t byteLength ///< Length of the buffer to be allocated, in bytes + ); #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - /// Creates a new ArrayBuffer instance, using an external buffer with - /// specified byte length. - static ArrayBuffer New( - napi_env env, ///< Node-API environment - void* externalData, ///< Pointer to the external buffer to be used by - ///< the array - size_t byteLength ///< Length of the external buffer to be used by the - ///< array, in bytes - ); - - /// Creates a new ArrayBuffer instance, using an external buffer with - /// specified byte length. - template - static ArrayBuffer New( - napi_env env, ///< Node-API environment - void* externalData, ///< Pointer to the external buffer to be used by - ///< the array - size_t byteLength, ///< Length of the external buffer to be used by the - ///< array, - /// in bytes - Finalizer finalizeCallback ///< Function to be called when the array - ///< buffer is destroyed; - /// must implement `void operator()(Env env, - /// void* externalData)` - ); - - /// Creates a new ArrayBuffer instance, using an external buffer with - /// specified byte length. - template - static ArrayBuffer New( - napi_env env, ///< Node-API environment - void* externalData, ///< Pointer to the external buffer to be used by - ///< the array - size_t byteLength, ///< Length of the external buffer to be used by the - ///< array, - /// in bytes - Finalizer finalizeCallback, ///< Function to be called when the array - ///< buffer is destroyed; - /// must implement `void operator()(Env - /// env, void* externalData, Hint* hint)` - Hint* finalizeHint ///< Hint (second parameter) to be passed to the - ///< finalize callback - ); + /// Creates a new ArrayBuffer instance, using an external buffer with + /// specified byte length. + static ArrayBuffer New( + napi_env env, ///< Node-API environment + void* externalData, ///< Pointer to the external buffer to be used by + ///< the array + size_t byteLength ///< Length of the external buffer to be used by the + ///< array, in bytes + ); + + /// Creates a new ArrayBuffer instance, using an external buffer with + /// specified byte length. + template + static ArrayBuffer New( + napi_env env, ///< Node-API environment + void* externalData, ///< Pointer to the external buffer to be used by + ///< the array + size_t byteLength, ///< Length of the external buffer to be used by the + ///< array, + /// in bytes + Finalizer finalizeCallback ///< Function to be called when the array + ///< buffer is destroyed; + /// must implement `void operator()(Env env, + /// void* externalData)` + ); + + /// Creates a new ArrayBuffer instance, using an external buffer with + /// specified byte length. + template + static ArrayBuffer New( + napi_env env, ///< Node-API environment + void* externalData, ///< Pointer to the external buffer to be used by + ///< the array + size_t byteLength, ///< Length of the external buffer to be used by the + ///< array, + /// in bytes + Finalizer finalizeCallback, ///< Function to be called when the array + ///< buffer is destroyed; + /// must implement `void operator()(Env + /// env, void* externalData, Hint* hint)` + Hint* finalizeHint ///< Hint (second parameter) to be passed to the + ///< finalize callback + ); #endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - static void CheckCast(napi_env env, napi_value value); + static void CheckCast(napi_env env, napi_value value); - ArrayBuffer(); ///< Creates a new _empty_ ArrayBuffer instance. - ArrayBuffer(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. + ArrayBuffer(); ///< Creates a new _empty_ ArrayBuffer instance. + ArrayBuffer(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. - void* Data(); ///< Gets a pointer to the data buffer. - size_t ByteLength(); ///< Gets the length of the array buffer in bytes. + void* Data(); ///< Gets a pointer to the data buffer. + size_t ByteLength(); ///< Gets the length of the array buffer in bytes. #if NAPI_VERSION >= 7 - bool IsDetached() const; + bool IsDetached() const; void Detach(); #endif // NAPI_VERSION >= 7 - }; +}; /// A JavaScript typed-array value with unknown array type. /// @@ -1220,349 +1289,349 @@ class Date : public Value { /// if (t.TypedArrayType() == napi_int32_array) { /// Napi::Int32Array int32Array = t.As(); /// } - class TypedArray : public Object { - public: - static void CheckCast(napi_env env, napi_value value); - - TypedArray(); ///< Creates a new _empty_ TypedArray instance. - TypedArray(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. - - napi_typedarray_type TypedArrayType() - const; ///< Gets the type of this typed-array. - Napi::ArrayBuffer ArrayBuffer() const; ///< Gets the backing array buffer. - - uint8_t ElementSize() - const; ///< Gets the size in bytes of one element in the array. - size_t ElementLength() const; ///< Gets the number of elements in the array. - size_t ByteOffset() - const; ///< Gets the offset into the buffer where the array starts. - size_t ByteLength() const; ///< Gets the length of the array in bytes. - - protected: - /// !cond INTERNAL - napi_typedarray_type _type; - size_t _length; - - TypedArray(napi_env env, - napi_value value, - napi_typedarray_type type, - size_t length); - - template - static +class TypedArray : public Object { + public: + static void CheckCast(napi_env env, napi_value value); + + TypedArray(); ///< Creates a new _empty_ TypedArray instance. + TypedArray(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. + + napi_typedarray_type TypedArrayType() + const; ///< Gets the type of this typed-array. + Napi::ArrayBuffer ArrayBuffer() const; ///< Gets the backing array buffer. + + uint8_t ElementSize() + const; ///< Gets the size in bytes of one element in the array. + size_t ElementLength() const; ///< Gets the number of elements in the array. + size_t ByteOffset() + const; ///< Gets the offset into the buffer where the array starts. + size_t ByteLength() const; ///< Gets the length of the array in bytes. + + protected: + /// !cond INTERNAL + napi_typedarray_type _type; + size_t _length; + + TypedArray(napi_env env, + napi_value value, + napi_typedarray_type type, + size_t length); + + template + static #if defined(NAPI_HAS_CONSTEXPR) - constexpr + constexpr #endif - napi_typedarray_type - TypedArrayTypeForPrimitiveType() { - return std::is_same::value ? napi_int8_array - : std::is_same::value ? napi_uint8_array - : std::is_same::value ? napi_int16_array - : std::is_same::value ? napi_uint16_array - : std::is_same::value ? napi_int32_array - : std::is_same::value ? napi_uint32_array - : std::is_same::value ? napi_float32_array - : std::is_same::value ? napi_float64_array - #if NAPI_VERSION > 5 - : std::is_same::value ? napi_bigint64_array - : std::is_same::value ? napi_biguint64_array - #endif // NAPI_VERSION > 5 - : napi_int8_array; - } - /// !endcond - }; + napi_typedarray_type + TypedArrayTypeForPrimitiveType() { + return std::is_same::value ? napi_int8_array + : std::is_same::value ? napi_uint8_array + : std::is_same::value ? napi_int16_array + : std::is_same::value ? napi_uint16_array + : std::is_same::value ? napi_int32_array + : std::is_same::value ? napi_uint32_array + : std::is_same::value ? napi_float32_array + : std::is_same::value ? napi_float64_array +#if NAPI_VERSION > 5 + : std::is_same::value ? napi_bigint64_array + : std::is_same::value ? napi_biguint64_array +#endif // NAPI_VERSION > 5 + : napi_int8_array; + } + /// !endcond +}; /// A JavaScript typed-array value with known array type. /// /// Note while it is possible to create and access Uint8 "clamped" arrays using /// this class, the _clamping_ behavior is only applied in JavaScript. - template - class TypedArrayOf : public TypedArray { - public: - /// Creates a new TypedArray instance over a new automatically-allocated array - /// buffer. - /// - /// The array type parameter can normally be omitted (because it is inferred - /// from the template parameter T), except when creating a "clamped" array: - /// - /// Uint8Array::New(env, length, napi_uint8_clamped_array) - static TypedArrayOf New( - napi_env env, ///< Node-API environment - size_t elementLength, ///< Length of the created array, as a number of - ///< elements +template +class TypedArrayOf : public TypedArray { + public: + /// Creates a new TypedArray instance over a new automatically-allocated array + /// buffer. + /// + /// The array type parameter can normally be omitted (because it is inferred + /// from the template parameter T), except when creating a "clamped" array: + /// + /// Uint8Array::New(env, length, napi_uint8_clamped_array) + static TypedArrayOf New( + napi_env env, ///< Node-API environment + size_t elementLength, ///< Length of the created array, as a number of + ///< elements #if defined(NAPI_HAS_CONSTEXPR) - napi_typedarray_type type = - TypedArray::TypedArrayTypeForPrimitiveType() + napi_typedarray_type type = + TypedArray::TypedArrayTypeForPrimitiveType() #else - napi_typedarray_type type + napi_typedarray_type type #endif - ///< Type of array, if different from the default array type for the - ///< template parameter T. - ); - - /// Creates a new TypedArray instance over a provided array buffer. - /// - /// The array type parameter can normally be omitted (because it is inferred - /// from the template parameter T), except when creating a "clamped" array: - /// - /// Uint8Array::New(env, length, buffer, 0, napi_uint8_clamped_array) - static TypedArrayOf New( - napi_env env, ///< Node-API environment - size_t elementLength, ///< Length of the created array, as a number of - ///< elements - Napi::ArrayBuffer arrayBuffer, ///< Backing array buffer instance to use - size_t bufferOffset, ///< Offset into the array buffer where the - ///< typed-array starts + ///< Type of array, if different from the default array type for the + ///< template parameter T. + ); + + /// Creates a new TypedArray instance over a provided array buffer. + /// + /// The array type parameter can normally be omitted (because it is inferred + /// from the template parameter T), except when creating a "clamped" array: + /// + /// Uint8Array::New(env, length, buffer, 0, napi_uint8_clamped_array) + static TypedArrayOf New( + napi_env env, ///< Node-API environment + size_t elementLength, ///< Length of the created array, as a number of + ///< elements + Napi::ArrayBuffer arrayBuffer, ///< Backing array buffer instance to use + size_t bufferOffset, ///< Offset into the array buffer where the + ///< typed-array starts #if defined(NAPI_HAS_CONSTEXPR) - napi_typedarray_type type = - TypedArray::TypedArrayTypeForPrimitiveType() + napi_typedarray_type type = + TypedArray::TypedArrayTypeForPrimitiveType() #else - napi_typedarray_type type + napi_typedarray_type type #endif - ///< Type of array, if different from the default array type for the - ///< template parameter T. - ); - - static void CheckCast(napi_env env, napi_value value); - - TypedArrayOf(); ///< Creates a new _empty_ TypedArrayOf instance. - TypedArrayOf(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. - - T& operator[](size_t index); ///< Gets or sets an element in the array. - const T& operator[](size_t index) const; ///< Gets an element in the array. - - /// Gets a pointer to the array's backing buffer. - /// - /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, - /// because the typed-array may have a non-zero `ByteOffset()` into the - /// `ArrayBuffer`. - T* Data(); - - /// Gets a pointer to the array's backing buffer. - /// - /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, - /// because the typed-array may have a non-zero `ByteOffset()` into the - /// `ArrayBuffer`. - const T* Data() const; - - private: - T* _data; - - TypedArrayOf(napi_env env, - napi_value value, - napi_typedarray_type type, - size_t length, - T* data); - }; + ///< Type of array, if different from the default array type for the + ///< template parameter T. + ); + + static void CheckCast(napi_env env, napi_value value); + + TypedArrayOf(); ///< Creates a new _empty_ TypedArrayOf instance. + TypedArrayOf(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. + + T& operator[](size_t index); ///< Gets or sets an element in the array. + const T& operator[](size_t index) const; ///< Gets an element in the array. + + /// Gets a pointer to the array's backing buffer. + /// + /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, + /// because the typed-array may have a non-zero `ByteOffset()` into the + /// `ArrayBuffer`. + T* Data(); + + /// Gets a pointer to the array's backing buffer. + /// + /// This is not necessarily the same as the `ArrayBuffer::Data()` pointer, + /// because the typed-array may have a non-zero `ByteOffset()` into the + /// `ArrayBuffer`. + const T* Data() const; + + private: + T* _data; + + TypedArrayOf(napi_env env, + napi_value value, + napi_typedarray_type type, + size_t length, + T* data); +}; /// The DataView provides a low-level interface for reading/writing multiple /// number types in an ArrayBuffer irrespective of the platform's endianness. - class DataView : public Object { - public: - static DataView New(napi_env env, Napi::ArrayBuffer arrayBuffer); - static DataView New(napi_env env, - Napi::ArrayBuffer arrayBuffer, - size_t byteOffset); - static DataView New(napi_env env, - Napi::ArrayBuffer arrayBuffer, - size_t byteOffset, - size_t byteLength); - - static void CheckCast(napi_env env, napi_value value); - - DataView(); ///< Creates a new _empty_ DataView instance. - DataView(napi_env env, - napi_value value); ///< Wraps a Node-API value primitive. - - Napi::ArrayBuffer ArrayBuffer() const; ///< Gets the backing array buffer. - size_t ByteOffset() - const; ///< Gets the offset into the buffer where the array starts. - size_t ByteLength() const; ///< Gets the length of the array in bytes. - - void* Data() const; - - float GetFloat32(size_t byteOffset) const; - double GetFloat64(size_t byteOffset) const; - int8_t GetInt8(size_t byteOffset) const; - int16_t GetInt16(size_t byteOffset) const; - int32_t GetInt32(size_t byteOffset) const; - uint8_t GetUint8(size_t byteOffset) const; - uint16_t GetUint16(size_t byteOffset) const; - uint32_t GetUint32(size_t byteOffset) const; - - void SetFloat32(size_t byteOffset, float value) const; - void SetFloat64(size_t byteOffset, double value) const; - void SetInt8(size_t byteOffset, int8_t value) const; - void SetInt16(size_t byteOffset, int16_t value) const; - void SetInt32(size_t byteOffset, int32_t value) const; - void SetUint8(size_t byteOffset, uint8_t value) const; - void SetUint16(size_t byteOffset, uint16_t value) const; - void SetUint32(size_t byteOffset, uint32_t value) const; - - private: - template - T ReadData(size_t byteOffset) const; - - template - void WriteData(size_t byteOffset, T value) const; - - void* _data{}; - size_t _length{}; - }; +class DataView : public Object { + public: + static DataView New(napi_env env, Napi::ArrayBuffer arrayBuffer); + static DataView New(napi_env env, + Napi::ArrayBuffer arrayBuffer, + size_t byteOffset); + static DataView New(napi_env env, + Napi::ArrayBuffer arrayBuffer, + size_t byteOffset, + size_t byteLength); - class Function : public Object { - public: - using VoidCallback = void (*)(const CallbackInfo& info); - using Callback = Value (*)(const CallbackInfo& info); - - template - static Function New(napi_env env, - const char* utf8name = nullptr, - void* data = nullptr); - - template - static Function New(napi_env env, - const char* utf8name = nullptr, - void* data = nullptr); - - template - static Function New(napi_env env, - const std::string& utf8name, - void* data = nullptr); - - template - static Function New(napi_env env, - const std::string& utf8name, - void* data = nullptr); - - /// Callable must implement operator() accepting a const CallbackInfo& - /// and return either void or Value. - template - static Function New(napi_env env, - Callable cb, - const char* utf8name = nullptr, - void* data = nullptr); - /// Callable must implement operator() accepting a const CallbackInfo& - /// and return either void or Value. - template - static Function New(napi_env env, - Callable cb, - const std::string& utf8name, - void* data = nullptr); - - static void CheckCast(napi_env env, napi_value value); - - Function(); - Function(napi_env env, napi_value value); - - MaybeOrValue operator()( - const std::initializer_list& args) const; - - MaybeOrValue Call(const std::initializer_list& args) const; - MaybeOrValue Call(const std::vector& args) const; - MaybeOrValue Call(const std::vector& args) const; - MaybeOrValue Call(size_t argc, const napi_value* args) const; - MaybeOrValue Call(napi_value recv, - const std::initializer_list& args) const; - MaybeOrValue Call(napi_value recv, - const std::vector& args) const; - MaybeOrValue Call(napi_value recv, - const std::vector& args) const; - MaybeOrValue Call(napi_value recv, - size_t argc, - const napi_value* args) const; + static void CheckCast(napi_env env, napi_value value); - MaybeOrValue MakeCallback( - napi_value recv, - const std::initializer_list& args, - napi_async_context context = nullptr) const; - MaybeOrValue MakeCallback(napi_value recv, - const std::vector& args, - napi_async_context context = nullptr) const; - MaybeOrValue MakeCallback(napi_value recv, - size_t argc, - const napi_value* args, - napi_async_context context = nullptr) const; - - MaybeOrValue New(const std::initializer_list& args) const; - MaybeOrValue New(const std::vector& args) const; - MaybeOrValue New(size_t argc, const napi_value* args) const; - }; + DataView(); ///< Creates a new _empty_ DataView instance. + DataView(napi_env env, + napi_value value); ///< Wraps a Node-API value primitive. + + Napi::ArrayBuffer ArrayBuffer() const; ///< Gets the backing array buffer. + size_t ByteOffset() + const; ///< Gets the offset into the buffer where the array starts. + size_t ByteLength() const; ///< Gets the length of the array in bytes. + + void* Data() const; + + float GetFloat32(size_t byteOffset) const; + double GetFloat64(size_t byteOffset) const; + int8_t GetInt8(size_t byteOffset) const; + int16_t GetInt16(size_t byteOffset) const; + int32_t GetInt32(size_t byteOffset) const; + uint8_t GetUint8(size_t byteOffset) const; + uint16_t GetUint16(size_t byteOffset) const; + uint32_t GetUint32(size_t byteOffset) const; + + void SetFloat32(size_t byteOffset, float value) const; + void SetFloat64(size_t byteOffset, double value) const; + void SetInt8(size_t byteOffset, int8_t value) const; + void SetInt16(size_t byteOffset, int16_t value) const; + void SetInt32(size_t byteOffset, int32_t value) const; + void SetUint8(size_t byteOffset, uint8_t value) const; + void SetUint16(size_t byteOffset, uint16_t value) const; + void SetUint32(size_t byteOffset, uint32_t value) const; + + private: + template + T ReadData(size_t byteOffset) const; - class Promise : public Object { - public: - class Deferred { - public: - static Deferred New(napi_env env); - Deferred(napi_env env); + template + void WriteData(size_t byteOffset, T value) const; - Napi::Promise Promise() const; - Napi::Env Env() const; + void* _data{}; + size_t _length{}; +}; - void Resolve(napi_value value) const; - void Reject(napi_value value) const; +class Function : public Object { + public: + using VoidCallback = void (*)(const CallbackInfo& info); + using Callback = Value (*)(const CallbackInfo& info); + + template + static Function New(napi_env env, + const char* utf8name = nullptr, + void* data = nullptr); + + template + static Function New(napi_env env, + const char* utf8name = nullptr, + void* data = nullptr); + + template + static Function New(napi_env env, + const std::string& utf8name, + void* data = nullptr); + + template + static Function New(napi_env env, + const std::string& utf8name, + void* data = nullptr); + + /// Callable must implement operator() accepting a const CallbackInfo& + /// and return either void or Value. + template + static Function New(napi_env env, + Callable cb, + const char* utf8name = nullptr, + void* data = nullptr); + /// Callable must implement operator() accepting a const CallbackInfo& + /// and return either void or Value. + template + static Function New(napi_env env, + Callable cb, + const std::string& utf8name, + void* data = nullptr); - private: - napi_env _env; - napi_deferred _deferred; - napi_value _promise; - }; + static void CheckCast(napi_env env, napi_value value); - static void CheckCast(napi_env env, napi_value value); + Function(); + Function(napi_env env, napi_value value); + + MaybeOrValue operator()( + const std::initializer_list& args) const; + + MaybeOrValue Call(const std::initializer_list& args) const; + MaybeOrValue Call(const std::vector& args) const; + MaybeOrValue Call(const std::vector& args) const; + MaybeOrValue Call(size_t argc, const napi_value* args) const; + MaybeOrValue Call(napi_value recv, + const std::initializer_list& args) const; + MaybeOrValue Call(napi_value recv, + const std::vector& args) const; + MaybeOrValue Call(napi_value recv, + const std::vector& args) const; + MaybeOrValue Call(napi_value recv, + size_t argc, + const napi_value* args) const; + + MaybeOrValue MakeCallback( + napi_value recv, + const std::initializer_list& args, + napi_async_context context = nullptr) const; + MaybeOrValue MakeCallback(napi_value recv, + const std::vector& args, + napi_async_context context = nullptr) const; + MaybeOrValue MakeCallback(napi_value recv, + size_t argc, + const napi_value* args, + napi_async_context context = nullptr) const; + + MaybeOrValue New(const std::initializer_list& args) const; + MaybeOrValue New(const std::vector& args) const; + MaybeOrValue New(size_t argc, const napi_value* args) const; +}; - Promise(napi_env env, napi_value value); - }; +class Promise : public Object { + public: + class Deferred { + public: + static Deferred New(napi_env env); + Deferred(napi_env env); - template - class Buffer : public Object { - public: - static Buffer New(napi_env env, size_t length); + Napi::Promise Promise() const; + Napi::Env Env() const; + + void Resolve(napi_value value) const; + void Reject(napi_value value) const; + + private: + napi_env _env; + napi_deferred _deferred; + napi_value _promise; + }; + + static void CheckCast(napi_env env, napi_value value); + + Promise(napi_env env, napi_value value); +}; + +template +class Buffer : public Object { + public: + static Buffer New(napi_env env, size_t length); #ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - static Buffer New(napi_env env, T* data, size_t length); + static Buffer New(napi_env env, T* data, size_t length); + + // Finalizer must implement `void operator()(Env env, T* data)`. + template + static Buffer New(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback); + // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. + template + static Buffer New(napi_env env, + T* data, + size_t length, + Finalizer finalizeCallback, + Hint* finalizeHint); +#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - // Finalizer must implement `void operator()(Env env, T* data)`. - template - static Buffer New(napi_env env, + static Buffer NewOrCopy(napi_env env, T* data, size_t length); + // Finalizer must implement `void operator()(Env env, T* data)`. + template + static Buffer NewOrCopy(napi_env env, T* data, size_t length, Finalizer finalizeCallback); - // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. - template - static Buffer New(napi_env env, + // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. + template + static Buffer NewOrCopy(napi_env env, T* data, size_t length, Finalizer finalizeCallback, Hint* finalizeHint); -#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED - static Buffer NewOrCopy(napi_env env, T* data, size_t length); - // Finalizer must implement `void operator()(Env env, T* data)`. - template - static Buffer NewOrCopy(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback); - // Finalizer must implement `void operator()(Env env, T* data, Hint* hint)`. - template - static Buffer NewOrCopy(napi_env env, - T* data, - size_t length, - Finalizer finalizeCallback, - Hint* finalizeHint); - - static Buffer Copy(napi_env env, const T* data, size_t length); - - static void CheckCast(napi_env env, napi_value value); - - Buffer(); - Buffer(napi_env env, napi_value value); - size_t Length() const; - T* Data() const; - - private: - }; + static Buffer Copy(napi_env env, const T* data, size_t length); + + static void CheckCast(napi_env env, napi_value value); + + Buffer(); + Buffer(napi_env env, napi_value value); + size_t Length() const; + T* Data() const; + + private: +}; /// Holds a counted reference to a value; initially a weak reference unless /// otherwise specified, may be changed to/from a strong reference by adjusting @@ -1571,148 +1640,148 @@ class Date : public Value { /// The referenced value is not immediately destroyed when the reference count /// is zero; it is merely then eligible for garbage-collection if there are no /// other references to the value. - template - class Reference { - public: - static Reference New(const T& value, uint32_t initialRefcount = 0); - - Reference(); - Reference(napi_env env, napi_ref ref); - ~Reference(); - - // A reference can be moved but cannot be copied. - Reference(Reference&& other); - Reference& operator=(Reference&& other); - NAPI_DISALLOW_ASSIGN(Reference) - - operator napi_ref() const; - bool operator==(const Reference& other) const; - bool operator!=(const Reference& other) const; - - Napi::Env Env() const; - bool IsEmpty() const; - - // Note when getting the value of a Reference it is usually correct to do so - // within a HandleScope so that the value handle gets cleaned up efficiently. - T Value() const; - - uint32_t Ref() const; - uint32_t Unref() const; - void Reset(); - 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 the environment is no longer valid. Avoid using - // this if at all possible. If you do need to use static data, MAKE SURE to - // warn your users that your addon is NOT threadsafe. - void SuppressDestruct(); - - protected: - Reference(const Reference&); - - /// !cond INTERNAL - napi_env _env; - napi_ref _ref; - /// !endcond - - private: - bool _suppressDestruct; - }; +template +class Reference { + public: + static Reference New(const T& value, uint32_t initialRefcount = 0); - class ObjectReference : public Reference { - public: - ObjectReference(); - ObjectReference(napi_env env, napi_ref ref); - - // A reference can be moved but cannot be copied. - ObjectReference(Reference&& other); - ObjectReference& operator=(Reference&& other); - ObjectReference(ObjectReference&& other); - ObjectReference& operator=(ObjectReference&& other); - NAPI_DISALLOW_ASSIGN(ObjectReference) - - MaybeOrValue Get(const char* utf8name) const; - MaybeOrValue Get(const std::string& utf8name) const; - MaybeOrValue Set(const char* utf8name, napi_value value) const; - MaybeOrValue Set(const char* utf8name, Napi::Value value) const; - MaybeOrValue Set(const char* utf8name, const char* utf8value) const; - MaybeOrValue Set(const char* utf8name, bool boolValue) const; - MaybeOrValue Set(const char* utf8name, double numberValue) const; - MaybeOrValue Set(const std::string& utf8name, napi_value value) const; - MaybeOrValue Set(const std::string& utf8name, Napi::Value value) const; - MaybeOrValue Set(const std::string& utf8name, - std::string& utf8value) const; - MaybeOrValue Set(const std::string& utf8name, bool boolValue) const; - MaybeOrValue Set(const std::string& utf8name, double numberValue) const; - - MaybeOrValue Get(uint32_t index) const; - MaybeOrValue Set(uint32_t index, const napi_value value) const; - MaybeOrValue Set(uint32_t index, const Napi::Value value) const; - MaybeOrValue Set(uint32_t index, const char* utf8value) const; - MaybeOrValue Set(uint32_t index, const std::string& utf8value) const; - MaybeOrValue Set(uint32_t index, bool boolValue) const; - MaybeOrValue Set(uint32_t index, double numberValue) const; - - protected: - ObjectReference(const ObjectReference&); - }; + Reference(); + Reference(napi_env env, napi_ref ref); + ~Reference(); - class FunctionReference : public Reference { - public: - FunctionReference(); - FunctionReference(napi_env env, napi_ref ref); - - // A reference can be moved but cannot be copied. - FunctionReference(Reference&& other); - FunctionReference& operator=(Reference&& other); - FunctionReference(FunctionReference&& other); - FunctionReference& operator=(FunctionReference&& other); - NAPI_DISALLOW_ASSIGN_COPY(FunctionReference) - - MaybeOrValue operator()( - const std::initializer_list& args) const; - - MaybeOrValue Call( - const std::initializer_list& args) const; - MaybeOrValue Call(const std::vector& args) const; - MaybeOrValue Call( - napi_value recv, const std::initializer_list& args) const; - MaybeOrValue Call(napi_value recv, - const std::vector& args) const; - MaybeOrValue Call(napi_value recv, - size_t argc, - const napi_value* args) const; - - MaybeOrValue MakeCallback( - napi_value recv, - const std::initializer_list& args, - napi_async_context context = nullptr) const; - MaybeOrValue MakeCallback( - napi_value recv, - const std::vector& args, - napi_async_context context = nullptr) const; - MaybeOrValue MakeCallback( - napi_value recv, - size_t argc, - const napi_value* args, - napi_async_context context = nullptr) const; - - MaybeOrValue New(const std::initializer_list& args) const; - MaybeOrValue New(const std::vector& args) const; - }; + // A reference can be moved but cannot be copied. + Reference(Reference&& other); + Reference& operator=(Reference&& other); + NAPI_DISALLOW_ASSIGN(Reference) + + operator napi_ref() const; + bool operator==(const Reference& other) const; + bool operator!=(const Reference& other) const; + + Napi::Env Env() const; + bool IsEmpty() const; + + // Note when getting the value of a Reference it is usually correct to do so + // within a HandleScope so that the value handle gets cleaned up efficiently. + T Value() const; + + uint32_t Ref() const; + uint32_t Unref() const; + void Reset(); + 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 the environment is no longer valid. Avoid using + // this if at all possible. If you do need to use static data, MAKE SURE to + // warn your users that your addon is NOT threadsafe. + void SuppressDestruct(); + + protected: + Reference(const Reference&); + + /// !cond INTERNAL + napi_env _env; + napi_ref _ref; + /// !endcond + + private: + bool _suppressDestruct; +}; + +class ObjectReference : public Reference { + public: + ObjectReference(); + ObjectReference(napi_env env, napi_ref ref); + + // A reference can be moved but cannot be copied. + ObjectReference(Reference&& other); + ObjectReference& operator=(Reference&& other); + ObjectReference(ObjectReference&& other); + ObjectReference& operator=(ObjectReference&& other); + NAPI_DISALLOW_ASSIGN(ObjectReference) + + MaybeOrValue Get(const char* utf8name) const; + MaybeOrValue Get(const std::string& utf8name) const; + MaybeOrValue Set(const char* utf8name, napi_value value) const; + MaybeOrValue Set(const char* utf8name, Napi::Value value) const; + MaybeOrValue Set(const char* utf8name, const char* utf8value) const; + MaybeOrValue Set(const char* utf8name, bool boolValue) const; + MaybeOrValue Set(const char* utf8name, double numberValue) const; + MaybeOrValue Set(const std::string& utf8name, napi_value value) const; + MaybeOrValue Set(const std::string& utf8name, Napi::Value value) const; + MaybeOrValue Set(const std::string& utf8name, + std::string& utf8value) const; + MaybeOrValue Set(const std::string& utf8name, bool boolValue) const; + MaybeOrValue Set(const std::string& utf8name, double numberValue) const; + + MaybeOrValue Get(uint32_t index) const; + MaybeOrValue Set(uint32_t index, const napi_value value) const; + MaybeOrValue Set(uint32_t index, const Napi::Value value) const; + MaybeOrValue Set(uint32_t index, const char* utf8value) const; + MaybeOrValue Set(uint32_t index, const std::string& utf8value) const; + MaybeOrValue Set(uint32_t index, bool boolValue) const; + MaybeOrValue Set(uint32_t index, double numberValue) const; + + protected: + ObjectReference(const ObjectReference&); +}; + +class FunctionReference : public Reference { + public: + FunctionReference(); + FunctionReference(napi_env env, napi_ref ref); + + // A reference can be moved but cannot be copied. + FunctionReference(Reference&& other); + FunctionReference& operator=(Reference&& other); + FunctionReference(FunctionReference&& other); + FunctionReference& operator=(FunctionReference&& other); + NAPI_DISALLOW_ASSIGN_COPY(FunctionReference) + + MaybeOrValue operator()( + const std::initializer_list& args) const; + + MaybeOrValue Call( + const std::initializer_list& args) const; + MaybeOrValue Call(const std::vector& args) const; + MaybeOrValue Call( + napi_value recv, const std::initializer_list& args) const; + MaybeOrValue Call(napi_value recv, + const std::vector& args) const; + MaybeOrValue Call(napi_value recv, + size_t argc, + const napi_value* args) const; + + MaybeOrValue MakeCallback( + napi_value recv, + const std::initializer_list& args, + napi_async_context context = nullptr) const; + MaybeOrValue MakeCallback( + napi_value recv, + const std::vector& args, + napi_async_context context = nullptr) const; + MaybeOrValue MakeCallback( + napi_value recv, + size_t argc, + const napi_value* args, + napi_async_context context = nullptr) const; + + MaybeOrValue New(const std::initializer_list& args) const; + MaybeOrValue New(const std::vector& args) const; +}; // Shortcuts to creating a new reference with inferred type and refcount = 0. - template - Reference Weak(T value); - ObjectReference Weak(Object value); - FunctionReference Weak(Function value); +template +Reference Weak(T value); +ObjectReference Weak(Object value); +FunctionReference Weak(Function value); // Shortcuts to creating a new reference with inferred type and refcount = 1. - template - Reference Persistent(T value); - ObjectReference Persistent(Object value); - FunctionReference Persistent(Function value); +template +Reference Persistent(T value); +ObjectReference Persistent(Object value); +FunctionReference Persistent(Function value); /// A persistent reference to a JavaScript error object. Use of this class /// depends somewhat on whether C++ exceptions are enabled at compile time. @@ -1770,14 +1839,15 @@ class Date : public Value { /// /// ### Handling Errors Without C++ Exceptions /// -/// If C++ exceptions are disabled (by defining `NAPI_DISABLE_CPP_EXCEPTIONS`) -/// then this class does not extend `std::exception`, and APIs in the `Napi` -/// namespace do not throw C++ exceptions when they fail. Instead, they raise -/// _pending_ JavaScript exceptions and return _empty_ `Value`s. Calling code -/// should check `Value::IsEmpty()` before attempting to use a returned value, -/// and may use methods on the `Env` class to check for, get, and clear a -/// pending JavaScript exception. If the pending exception is not cleared, it -/// will be thrown when the native callback returns to JavaScript. +/// If C++ exceptions are disabled (by defining +/// `NODE_ADDON_API_DISABLE_CPP_EXCEPTIONS`) then this class does not extend +/// `std::exception`, and APIs in the `Napi` namespace do not throw C++ +/// exceptions when they fail. Instead, they raise _pending_ JavaScript +/// exceptions and return _empty_ `Value`s. Calling code should check +/// `Value::IsEmpty()` before attempting to use a returned value, and may use +/// methods on the `Env` class to check for, get, and clear a pending JavaScript +/// exception. If the pending exception is not cleared, it will be thrown when +/// the native callback returns to JavaScript. /// /// #### Example 1B - Throwing a JS exception /// @@ -1811,76 +1881,76 @@ class Date : public Value { /// /// Since the exception was cleared here, it will not be propagated as a /// JavaScript exception after the native callback returns. - class Error : public ObjectReference -#ifdef NAPI_CPP_EXCEPTIONS - , - public std::exception -#endif // NAPI_CPP_EXCEPTIONS - { - public: - static Error New(napi_env env); - static Error New(napi_env env, const char* message); - static Error New(napi_env env, const std::string& message); +class Error : public ObjectReference +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + , + public std::exception +#endif // NODE_ADDON_API_CPP_EXCEPTIONS +{ + public: + static Error New(napi_env env); + static Error New(napi_env env, const char* message); + static Error New(napi_env env, const std::string& message); - static NAPI_NO_RETURN void Fatal(const char* location, const char* message); + static NAPI_NO_RETURN void Fatal(const char* location, const char* message); - Error(); - Error(napi_env env, napi_value value); + Error(); + Error(napi_env env, napi_value value); - // An error can be moved or copied. - Error(Error&& other); - Error& operator=(Error&& other); - Error(const Error&); - Error& operator=(const Error&); + // An error can be moved or copied. + Error(Error&& other); + Error& operator=(Error&& other); + Error(const Error&); + Error& operator=(const Error&); - const std::string& Message() const NAPI_NOEXCEPT; - void ThrowAsJavaScriptException() const; + const std::string& Message() const NAPI_NOEXCEPT; + void ThrowAsJavaScriptException() const; - Object Value() const; + Object Value() const; -#ifdef NAPI_CPP_EXCEPTIONS - const char* what() const NAPI_NOEXCEPT override; -#endif // NAPI_CPP_EXCEPTIONS - - protected: - /// !cond INTERNAL - using create_error_fn = napi_status (*)(napi_env envb, - napi_value code, - napi_value msg, - napi_value* result); - - template - static TError New(napi_env env, - const char* message, - size_t length, - create_error_fn create_error); - /// !endcond - - private: - static inline const char* ERROR_WRAP_VALUE() NAPI_NOEXCEPT; - mutable std::string _message; - }; +#ifdef NODE_ADDON_API_CPP_EXCEPTIONS + const char* what() const NAPI_NOEXCEPT override; +#endif // NODE_ADDON_API_CPP_EXCEPTIONS - class TypeError : public Error { - public: - static TypeError New(napi_env env, const char* message); - static TypeError New(napi_env env, const std::string& message); + protected: + /// !cond INTERNAL + using create_error_fn = napi_status (*)(napi_env envb, + napi_value code, + napi_value msg, + napi_value* result); + + template + static TError New(napi_env env, + const char* message, + size_t length, + create_error_fn create_error); + /// !endcond - TypeError(); - TypeError(napi_env env, napi_value value); - }; + private: + static inline const char* ERROR_WRAP_VALUE() NAPI_NOEXCEPT; + mutable std::string _message; +}; - class RangeError : public Error { - public: - static RangeError New(napi_env env, const char* message); - static RangeError New(napi_env env, const std::string& message); +class TypeError : public Error { + public: + static TypeError New(napi_env env, const char* message); + static TypeError New(napi_env env, const std::string& message); - RangeError(); - RangeError(napi_env env, napi_value value); - }; + TypeError(); + TypeError(napi_env env, napi_value value); +}; + +class RangeError : public Error { + public: + static RangeError New(napi_env env, const char* message); + static RangeError New(napi_env env, const std::string& message); + + RangeError(); + RangeError(napi_env env, napi_value value); +}; #if NAPI_VERSION > 8 - class SyntaxError : public Error { +class SyntaxError : public Error { public: static SyntaxError New(napi_env env, const char* message); static SyntaxError New(napi_env env, const std::string& message); @@ -1890,256 +1960,256 @@ class Date : public Value { }; #endif // NAPI_VERSION > 8 - class CallbackInfo { - public: - CallbackInfo(napi_env env, napi_callback_info info); - ~CallbackInfo(); - - // Disallow copying to prevent multiple free of _dynamicArgs - NAPI_DISALLOW_ASSIGN_COPY(CallbackInfo) - - Napi::Env Env() const; - Value NewTarget() const; - bool IsConstructCall() const; - size_t Length() const; - const Value operator[](size_t index) const; - Value This() const; - void* Data() const; - void SetData(void* data); - explicit operator napi_callback_info() const; - - private: - const size_t _staticArgCount = 6; - napi_env _env; - napi_callback_info _info; - napi_value _this; - size_t _argc; - napi_value* _argv; - napi_value _staticArgs[6]{}; - napi_value* _dynamicArgs; - void* _data; - }; +class CallbackInfo { + public: + CallbackInfo(napi_env env, napi_callback_info info); + ~CallbackInfo(); + + // Disallow copying to prevent multiple free of _dynamicArgs + NAPI_DISALLOW_ASSIGN_COPY(CallbackInfo) + + Napi::Env Env() const; + Value NewTarget() const; + bool IsConstructCall() const; + size_t Length() const; + const Value operator[](size_t index) const; + Value This() const; + void* Data() const; + void SetData(void* data); + explicit operator napi_callback_info() const; - class PropertyDescriptor { - public: - using GetterCallback = Napi::Value (*)(const Napi::CallbackInfo& info); - using SetterCallback = void (*)(const Napi::CallbackInfo& info); + private: + const size_t _staticArgCount = 6; + napi_env _env; + napi_callback_info _info; + napi_value _this; + size_t _argc; + napi_value* _argv; + napi_value _staticArgs[6]{}; + napi_value* _dynamicArgs; + void* _data; +}; + +class PropertyDescriptor { + public: + using GetterCallback = Napi::Value (*)(const Napi::CallbackInfo& info); + using SetterCallback = void (*)(const Napi::CallbackInfo& info); #ifndef NODE_ADDON_API_DISABLE_DEPRECATED - template - static PropertyDescriptor Accessor( - const char* utf8name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - const std::string& utf8name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - napi_value name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Name name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - const char* utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - const std::string& utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - napi_value name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Name name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - const char* utf8name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - const std::string& utf8name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - napi_value name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - Name name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor Accessor( + const char* utf8name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + const std::string& utf8name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + napi_value name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Name name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + const char* utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + const std::string& utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + napi_value name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Name name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + const char* utf8name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + const std::string& utf8name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + napi_value name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + Name name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif // !NODE_ADDON_API_DISABLE_DEPRECATED - template - static PropertyDescriptor Accessor( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - const std::string& utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - Name name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - const std::string& utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - Name name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - const char* utf8name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - Name name, - Getter getter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - const char* utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Accessor( - Napi::Env env, - Napi::Object object, - Name name, - Getter getter, - Setter setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - Napi::Env env, - Napi::Object object, - const char* utf8name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - Napi::Env env, - Napi::Object object, - const std::string& utf8name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor Function( - Napi::Env env, - Napi::Object object, - Name name, - Callable cb, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - static PropertyDescriptor Value( - const char* utf8name, - napi_value value, - napi_property_attributes attributes = napi_default); - static PropertyDescriptor Value( - const std::string& utf8name, - napi_value value, - napi_property_attributes attributes = napi_default); - static PropertyDescriptor Value( - napi_value name, - napi_value value, - napi_property_attributes attributes = napi_default); - static PropertyDescriptor Value( - Name name, - Napi::Value value, - napi_property_attributes attributes = napi_default); - - PropertyDescriptor(napi_property_descriptor desc); - - operator napi_property_descriptor&(); - operator const napi_property_descriptor&() const; - - private: - napi_property_descriptor _desc; - }; + template + static PropertyDescriptor Accessor( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + const std::string& utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + Name name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + const std::string& utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + Name name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + const char* utf8name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + Name name, + Getter getter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + const char* utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Accessor( + Napi::Env env, + Napi::Object object, + Name name, + Getter getter, + Setter setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + Napi::Env env, + Napi::Object object, + const char* utf8name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + Napi::Env env, + Napi::Object object, + const std::string& utf8name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor Function( + Napi::Env env, + Napi::Object object, + Name name, + Callable cb, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + static PropertyDescriptor Value( + const char* utf8name, + napi_value value, + napi_property_attributes attributes = napi_default); + static PropertyDescriptor Value( + const std::string& utf8name, + napi_value value, + napi_property_attributes attributes = napi_default); + static PropertyDescriptor Value( + napi_value name, + napi_value value, + napi_property_attributes attributes = napi_default); + static PropertyDescriptor Value( + Name name, + Napi::Value value, + napi_property_attributes attributes = napi_default); + + PropertyDescriptor(napi_property_descriptor desc); + + operator napi_property_descriptor&(); + operator const napi_property_descriptor&() const; + + private: + napi_property_descriptor _desc; +}; /// Property descriptor for use with `ObjectWrap::DefineClass()`. /// @@ -2147,165 +2217,165 @@ class Date : public Value { /// specific to each `ObjectWrap` subclass. This prevents using descriptors /// from a different class when defining a new class (preventing the callbacks /// from having incorrect `this` pointers). - template - class ClassPropertyDescriptor { - public: - ClassPropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {} +template +class ClassPropertyDescriptor { + public: + ClassPropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {} - operator napi_property_descriptor&() { return _desc; } - operator const napi_property_descriptor&() const { return _desc; } + operator napi_property_descriptor&() { return _desc; } + operator const napi_property_descriptor&() const { return _desc; } - private: - napi_property_descriptor _desc; - }; + private: + napi_property_descriptor _desc; +}; - template - struct MethodCallbackData { - TCallback callback; - void* data; - }; +template +struct MethodCallbackData { + TCallback callback; + void* data; +}; - template - struct AccessorCallbackData { - TGetterCallback getterCallback; - TSetterCallback setterCallback; - void* data; - }; +template +struct AccessorCallbackData { + TGetterCallback getterCallback; + TSetterCallback setterCallback; + void* data; +}; - template - class InstanceWrap { - public: - using InstanceVoidMethodCallback = void (T::*)(const CallbackInfo& info); - using InstanceMethodCallback = Napi::Value (T::*)(const CallbackInfo& info); - using InstanceGetterCallback = Napi::Value (T::*)(const CallbackInfo& info); - using InstanceSetterCallback = void (T::*)(const CallbackInfo& info, - const Napi::Value& value); - - using PropertyDescriptor = ClassPropertyDescriptor; - - static PropertyDescriptor InstanceMethod( - const char* utf8name, - InstanceVoidMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - static PropertyDescriptor InstanceMethod( - const char* utf8name, - InstanceMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); +template +class InstanceWrap { + public: + using InstanceVoidMethodCallback = void (T::*)(const CallbackInfo& info); + using InstanceMethodCallback = Napi::Value (T::*)(const CallbackInfo& info); + using InstanceGetterCallback = Napi::Value (T::*)(const CallbackInfo& info); + using InstanceSetterCallback = void (T::*)(const CallbackInfo& info, + const Napi::Value& value); + + using PropertyDescriptor = ClassPropertyDescriptor; + + static PropertyDescriptor InstanceMethod( + const char* utf8name, + InstanceVoidMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + static PropertyDescriptor InstanceMethod( + const char* utf8name, + InstanceMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - static PropertyDescriptor InstanceMethod( - Symbol name, - InstanceVoidMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - static PropertyDescriptor InstanceMethod( - Symbol name, - InstanceMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor InstanceMethod( + Symbol name, + InstanceVoidMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + static PropertyDescriptor InstanceMethod( + Symbol name, + InstanceMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - template - static PropertyDescriptor InstanceMethod( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor InstanceMethod( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor InstanceMethod( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor InstanceMethod( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - template - static PropertyDescriptor InstanceMethod( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - template - static PropertyDescriptor InstanceMethod( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor InstanceMethod( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + template + static PropertyDescriptor InstanceMethod( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - static PropertyDescriptor InstanceAccessor( - const char* utf8name, - InstanceGetterCallback getter, - InstanceSetterCallback setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor InstanceAccessor( + const char* utf8name, + InstanceGetterCallback getter, + InstanceSetterCallback setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - static PropertyDescriptor InstanceAccessor( - Symbol name, - InstanceGetterCallback getter, - InstanceSetterCallback setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor InstanceAccessor( + Symbol name, + InstanceGetterCallback getter, + InstanceSetterCallback setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - template - static PropertyDescriptor InstanceAccessor( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor InstanceAccessor( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - template - static PropertyDescriptor InstanceAccessor( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor InstanceAccessor( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - static PropertyDescriptor InstanceValue( - const char* utf8name, - Napi::Value value, - napi_property_attributes attributes = napi_default); + static PropertyDescriptor InstanceValue( + const char* utf8name, + Napi::Value value, + napi_property_attributes attributes = napi_default); #ifndef OHOS - static PropertyDescriptor InstanceValue( - Symbol name, - Napi::Value value, - napi_property_attributes attributes = napi_default); + static PropertyDescriptor InstanceValue( + Symbol name, + Napi::Value value, + napi_property_attributes attributes = napi_default); #endif - protected: - static void AttachPropData(napi_env env, - napi_value value, - const napi_property_descriptor* prop); - - private: - using This = InstanceWrap; - - using InstanceVoidMethodCallbackData = - MethodCallbackData; - using InstanceMethodCallbackData = - MethodCallbackData; - using InstanceAccessorCallbackData = - AccessorCallbackData; - - static napi_value InstanceVoidMethodCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value InstanceMethodCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value InstanceGetterCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value InstanceSetterCallbackWrapper(napi_env env, - napi_callback_info info); - - template - static napi_value WrappedMethod(napi_env env, - napi_callback_info info) NAPI_NOEXCEPT; - - template - struct SetterTag {}; - - template - static napi_callback WrapSetter(SetterTag) NAPI_NOEXCEPT { - return &This::WrappedMethod; - } - static napi_callback WrapSetter(SetterTag) NAPI_NOEXCEPT { - return nullptr; - } - }; + protected: + static void AttachPropData(napi_env env, + napi_value value, + const napi_property_descriptor* prop); + + private: + using This = InstanceWrap; + + using InstanceVoidMethodCallbackData = + MethodCallbackData; + using InstanceMethodCallbackData = + MethodCallbackData; + using InstanceAccessorCallbackData = + AccessorCallbackData; + + static napi_value InstanceVoidMethodCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value InstanceMethodCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value InstanceGetterCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value InstanceSetterCallbackWrapper(napi_env env, + napi_callback_info info); + + template + static napi_value WrappedMethod(napi_env env, + napi_callback_info info) NAPI_NOEXCEPT; + + template + struct SetterTag {}; + + template + static napi_callback WrapSetter(SetterTag) NAPI_NOEXCEPT { + return &This::WrappedMethod; + } + static napi_callback WrapSetter(SetterTag) NAPI_NOEXCEPT { + return nullptr; + } +}; /// Base class to be extended by C++ classes exposed to JavaScript; each C++ /// class instance gets "wrapped" by a JavaScript object that is managed by this @@ -2334,204 +2404,211 @@ class Date : public Value { /// void SetSomething(const Napi::CallbackInfo& info, const Napi::Value& /// value); Napi::Value DoSomething(const Napi::CallbackInfo& info); /// } - template - class ObjectWrap : public InstanceWrap, public Reference { - public: - ObjectWrap(const CallbackInfo& callbackInfo); - virtual ~ObjectWrap(); - - static T* Unwrap(Object wrapper); - - // Methods exposed to JavaScript must conform to one of these callback - // signatures. - using StaticVoidMethodCallback = void (*)(const CallbackInfo& info); - using StaticMethodCallback = Napi::Value (*)(const CallbackInfo& info); - using StaticGetterCallback = Napi::Value (*)(const CallbackInfo& info); - using StaticSetterCallback = void (*)(const CallbackInfo& info, - const Napi::Value& value); - - using PropertyDescriptor = ClassPropertyDescriptor; - - static Function DefineClass( - Napi::Env env, - const char* utf8name, - const std::initializer_list& properties, - void* data = nullptr); - static Function DefineClass(Napi::Env env, - const char* utf8name, - const std::vector& properties, - void* data = nullptr); - static PropertyDescriptor StaticMethod( - const char* utf8name, - StaticVoidMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - static PropertyDescriptor StaticMethod( - const char* utf8name, - StaticMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); +template +class ObjectWrap : public InstanceWrap, public Reference { + public: + ObjectWrap(const CallbackInfo& callbackInfo); + virtual ~ObjectWrap(); + + static T* Unwrap(Object wrapper); + + // Methods exposed to JavaScript must conform to one of these callback + // signatures. + using StaticVoidMethodCallback = void (*)(const CallbackInfo& info); + using StaticMethodCallback = Napi::Value (*)(const CallbackInfo& info); + using StaticGetterCallback = Napi::Value (*)(const CallbackInfo& info); + using StaticSetterCallback = void (*)(const CallbackInfo& info, + const Napi::Value& value); + + using PropertyDescriptor = ClassPropertyDescriptor; + + static Function DefineClass( + Napi::Env env, + const char* utf8name, + const std::initializer_list& properties, + void* data = nullptr); + static Function DefineClass(Napi::Env env, + const char* utf8name, + const std::vector& properties, + void* data = nullptr); + static PropertyDescriptor StaticMethod( + const char* utf8name, + StaticVoidMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + static PropertyDescriptor StaticMethod( + const char* utf8name, + StaticMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - static PropertyDescriptor StaticMethod( - Symbol name, - StaticVoidMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); - static PropertyDescriptor StaticMethod( - Symbol name, - StaticMethodCallback method, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor StaticMethod( + Symbol name, + StaticVoidMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); + static PropertyDescriptor StaticMethod( + Symbol name, + StaticMethodCallback method, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - template - static PropertyDescriptor StaticMethod( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticMethod( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - template - static PropertyDescriptor StaticMethod( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticMethod( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - template - static PropertyDescriptor StaticMethod( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticMethod( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - template - static PropertyDescriptor StaticMethod( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticMethod( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - static PropertyDescriptor StaticAccessor( - const char* utf8name, - StaticGetterCallback getter, - StaticSetterCallback setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor StaticAccessor( + const char* utf8name, + StaticGetterCallback getter, + StaticSetterCallback setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - static PropertyDescriptor StaticAccessor( - Symbol name, - StaticGetterCallback getter, - StaticSetterCallback setter, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + static PropertyDescriptor StaticAccessor( + Symbol name, + StaticGetterCallback getter, + StaticSetterCallback setter, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - template - static PropertyDescriptor StaticAccessor( - const char* utf8name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticAccessor( + const char* utf8name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #ifndef OHOS - template - static PropertyDescriptor StaticAccessor( - Symbol name, - napi_property_attributes attributes = napi_default, - void* data = nullptr); + template + static PropertyDescriptor StaticAccessor( + Symbol name, + napi_property_attributes attributes = napi_default, + void* data = nullptr); #endif - static PropertyDescriptor StaticValue( - const char* utf8name, - Napi::Value value, - napi_property_attributes attributes = napi_default); + static PropertyDescriptor StaticValue( + const char* utf8name, + Napi::Value value, + napi_property_attributes attributes = napi_default); #ifndef OHOS - static PropertyDescriptor StaticValue( - Symbol name, - Napi::Value value, - napi_property_attributes attributes = napi_default); + static PropertyDescriptor StaticValue( + Symbol name, + Napi::Value value, + napi_property_attributes attributes = napi_default); #endif - static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& callbackInfo); - virtual void Finalize(Napi::Env env); + static Napi::Value OnCalledAsFunction(const Napi::CallbackInfo& callbackInfo); + virtual void Finalize(Napi::Env env); + virtual void Finalize(BasicEnv env); - private: - using This = ObjectWrap; + private: + using This = ObjectWrap; + + static napi_value ConstructorCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value StaticVoidMethodCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value StaticMethodCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value StaticGetterCallbackWrapper(napi_env env, + napi_callback_info info); + static napi_value StaticSetterCallbackWrapper(napi_env env, + napi_callback_info info); + static void FinalizeCallback(node_addon_api_basic_env env, + void* data, + void* hint); + + static void PostFinalizeCallback(napi_env env, void* data, void* hint); + + static Function DefineClass(Napi::Env env, + const char* utf8name, + const size_t props_count, + const napi_property_descriptor* props, + void* data = nullptr); + + using StaticVoidMethodCallbackData = + MethodCallbackData; + using StaticMethodCallbackData = MethodCallbackData; + + using StaticAccessorCallbackData = + AccessorCallbackData; + + template + static napi_value WrappedMethod(napi_env env, + napi_callback_info info) NAPI_NOEXCEPT; + + template + struct StaticSetterTag {}; + + template + static napi_callback WrapStaticSetter(StaticSetterTag) NAPI_NOEXCEPT { + return &This::WrappedMethod; + } + static napi_callback WrapStaticSetter(StaticSetterTag) + NAPI_NOEXCEPT { + return nullptr; + } - static napi_value ConstructorCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value StaticVoidMethodCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value StaticMethodCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value StaticGetterCallbackWrapper(napi_env env, - napi_callback_info info); - static napi_value StaticSetterCallbackWrapper(napi_env env, - napi_callback_info info); - static void FinalizeCallback(napi_env env, void* data, void* hint); - static Function DefineClass(Napi::Env env, - const char* utf8name, - const size_t props_count, - const napi_property_descriptor* props, - void* data = nullptr); - - using StaticVoidMethodCallbackData = - MethodCallbackData; - using StaticMethodCallbackData = MethodCallbackData; - - using StaticAccessorCallbackData = - AccessorCallbackData; - - template - static napi_value WrappedMethod(napi_env env, - napi_callback_info info) NAPI_NOEXCEPT; - - template - struct StaticSetterTag {}; - - template - static napi_callback WrapStaticSetter(StaticSetterTag) NAPI_NOEXCEPT { - return &This::WrappedMethod; - } - static napi_callback WrapStaticSetter(StaticSetterTag) - NAPI_NOEXCEPT { - return nullptr; - } - - bool _construction_failed = true; - }; + bool _construction_failed = true; + bool _finalized = false; +}; - class HandleScope { - public: - HandleScope(napi_env env, napi_handle_scope scope); - explicit HandleScope(Napi::Env env); - ~HandleScope(); +class HandleScope { + public: + HandleScope(napi_env env, napi_handle_scope scope); + explicit HandleScope(Napi::Env env); + ~HandleScope(); - // Disallow copying to prevent double close of napi_handle_scope - NAPI_DISALLOW_ASSIGN_COPY(HandleScope) + // Disallow copying to prevent double close of napi_handle_scope + NAPI_DISALLOW_ASSIGN_COPY(HandleScope) - operator napi_handle_scope() const; + operator napi_handle_scope() const; - Napi::Env Env() const; + Napi::Env Env() const; - private: - napi_env _env; - napi_handle_scope _scope; - }; + private: + napi_env _env; + napi_handle_scope _scope; +}; - class EscapableHandleScope { - public: - EscapableHandleScope(napi_env env, napi_escapable_handle_scope scope); - explicit EscapableHandleScope(Napi::Env env); - ~EscapableHandleScope(); +class EscapableHandleScope { + public: + EscapableHandleScope(napi_env env, napi_escapable_handle_scope scope); + explicit EscapableHandleScope(Napi::Env env); + ~EscapableHandleScope(); - // Disallow copying to prevent double close of napi_escapable_handle_scope - NAPI_DISALLOW_ASSIGN_COPY(EscapableHandleScope) + // Disallow copying to prevent double close of napi_escapable_handle_scope + NAPI_DISALLOW_ASSIGN_COPY(EscapableHandleScope) - operator napi_escapable_handle_scope() const; + operator napi_escapable_handle_scope() const; - Napi::Env Env() const; - Value Escape(napi_value escapee); + Napi::Env Env() const; + Value Escape(napi_value escapee); - private: - napi_env _env; - napi_escapable_handle_scope _scope; - }; + private: + napi_env _env; + napi_escapable_handle_scope _scope; +}; #if (NAPI_VERSION > 2) - class CallbackScope { +class CallbackScope { public: CallbackScope(napi_env env, napi_callback_scope scope); CallbackScope(napi_env env, napi_async_context context); @@ -2550,94 +2627,94 @@ class Date : public Value { }; #endif - class AsyncContext { - public: - explicit AsyncContext(napi_env env, const char* resource_name); - explicit AsyncContext(napi_env env, - const char* resource_name, - const Object& resource); - virtual ~AsyncContext(); +class AsyncContext { + public: + explicit AsyncContext(napi_env env, const char* resource_name); + explicit AsyncContext(napi_env env, + const char* resource_name, + const Object& resource); + virtual ~AsyncContext(); - AsyncContext(AsyncContext&& other); - AsyncContext& operator=(AsyncContext&& other); - NAPI_DISALLOW_ASSIGN_COPY(AsyncContext) + AsyncContext(AsyncContext&& other); + AsyncContext& operator=(AsyncContext&& other); + NAPI_DISALLOW_ASSIGN_COPY(AsyncContext) - operator napi_async_context() const; + operator napi_async_context() const; - Napi::Env Env() const; + Napi::Env Env() const; - private: - napi_env _env; - napi_async_context _context; - }; + private: + napi_env _env; + napi_async_context _context; +}; #if NAPI_HAS_THREADS - class AsyncWorker { - public: - virtual ~AsyncWorker(); - - NAPI_DISALLOW_ASSIGN_COPY(AsyncWorker) - - operator napi_async_work() const; - - Napi::Env Env() const; - - void Queue(); - void Cancel(); - void SuppressDestruct(); - - ObjectReference& Receiver(); - FunctionReference& Callback(); - - virtual void OnExecute(Napi::Env env); - virtual void OnWorkComplete(Napi::Env env, napi_status status); - - protected: - explicit AsyncWorker(const Function& callback); - explicit AsyncWorker(const Function& callback, const char* resource_name); - explicit AsyncWorker(const Function& callback, - const char* resource_name, - const Object& resource); - explicit AsyncWorker(const Object& receiver, const Function& callback); - explicit AsyncWorker(const Object& receiver, - const Function& callback, - const char* resource_name); - explicit AsyncWorker(const Object& receiver, - const Function& callback, - const char* resource_name, - const Object& resource); - - explicit AsyncWorker(Napi::Env env); - explicit AsyncWorker(Napi::Env env, const char* resource_name); - explicit AsyncWorker(Napi::Env env, - const char* resource_name, - const Object& resource); - - virtual void Execute() = 0; - virtual void OnOK(); - virtual void OnError(const Error& e); - virtual void Destroy(); - virtual std::vector GetResult(Napi::Env env); - - void SetError(const std::string& error); - - private: - static inline void OnAsyncWorkExecute(napi_env env, void* asyncworker); - static inline void OnAsyncWorkComplete(napi_env env, - napi_status status, - void* asyncworker); - - napi_env _env; - napi_async_work _work; - ObjectReference _receiver; - FunctionReference _callback; - std::string _error; - bool _suppress_destruct; - }; +class AsyncWorker { + public: + virtual ~AsyncWorker(); + + NAPI_DISALLOW_ASSIGN_COPY(AsyncWorker) + + operator napi_async_work() const; + + Napi::Env Env() const; + + void Queue(); + void Cancel(); + void SuppressDestruct(); + + ObjectReference& Receiver(); + FunctionReference& Callback(); + + virtual void OnExecute(Napi::Env env); + virtual void OnWorkComplete(Napi::Env env, napi_status status); + + protected: + explicit AsyncWorker(const Function& callback); + explicit AsyncWorker(const Function& callback, const char* resource_name); + explicit AsyncWorker(const Function& callback, + const char* resource_name, + const Object& resource); + explicit AsyncWorker(const Object& receiver, const Function& callback); + explicit AsyncWorker(const Object& receiver, + const Function& callback, + const char* resource_name); + explicit AsyncWorker(const Object& receiver, + const Function& callback, + const char* resource_name, + const Object& resource); + + explicit AsyncWorker(Napi::Env env); + explicit AsyncWorker(Napi::Env env, const char* resource_name); + explicit AsyncWorker(Napi::Env env, + const char* resource_name, + const Object& resource); + + virtual void Execute() = 0; + virtual void OnOK(); + virtual void OnError(const Error& e); + virtual void Destroy(); + virtual std::vector GetResult(Napi::Env env); + + void SetError(const std::string& error); + + private: + static inline void OnAsyncWorkExecute(napi_env env, void* asyncworker); + static inline void OnAsyncWorkComplete(napi_env env, + napi_status status, + void* asyncworker); + + napi_env _env; + napi_async_work _work; + ObjectReference _receiver; + FunctionReference _callback; + std::string _error; + bool _suppress_destruct; +}; #endif // NAPI_HAS_THREADS #if (NAPI_VERSION > 3 && NAPI_HAS_THREADS) - class ThreadSafeFunction { +class ThreadSafeFunction { public: // This API may only be called from the main thread. template @@ -3210,21 +3287,21 @@ class AsyncProgressQueueWorker #ifndef OHOS // Memory management. - class MemoryManagement { - public: - static int64_t AdjustExternalMemory(Env env, int64_t change_in_bytes); - }; +class MemoryManagement { + public: + static int64_t AdjustExternalMemory(BasicEnv env, int64_t change_in_bytes); +}; #endif // Version management - class VersionManagement { - public: - static uint32_t GetNapiVersion(Env env); - static const napi_node_version* GetNodeVersion(Env env); - }; +class VersionManagement { + public: + static uint32_t GetNapiVersion(BasicEnv env); + static const napi_node_version* GetNodeVersion(BasicEnv env); +}; #if NAPI_VERSION > 5 - template +template class Addon : public InstanceWrap { public: static inline Object Init(Env env, Object exports); @@ -3243,7 +3320,7 @@ class Addon : public InstanceWrap { #endif // NAPI_VERSION > 5 #ifdef NAPI_CPP_CUSTOM_NAMESPACE - } // namespace NAPI_CPP_CUSTOM_NAMESPACE +} // namespace NAPI_CPP_CUSTOM_NAMESPACE #endif } // namespace Napi