diff --git a/doc/error_handling.md b/doc/error_handling.md index d5df55450..9a0ef349e 100644 --- a/doc/error_handling.md +++ b/doc/error_handling.md @@ -153,3 +153,34 @@ if (env.IsExceptionPending()) { Since the exception was cleared here, it will not be propagated as a JavaScript exception after the native callback returns. + +## Calling N-API directly from a **node-addon-api** addon + +**node-addon-api** provides macros for throwing errors in response to non-OK +`napi_status` results when calling [N-API](https://nodejs.org/docs/latest/api/n-api.html) +functions from within a native addon. These macros are defined differently +depending on whether C++ exceptions are enabled or not, but are available for +use in either case. + +### `NAPI_THROW(e, ...)` + +This macro accepts a `Napi::Error`, throws it, and returns the value given as +the last parameter. If C++ exceptions are enabled (by defining +`NAPI_CPP_EXCEPTIONS` during the build), the return value will be ignored. + +### `NAPI_THROW_IF_FAILED(env, status, ...)` + +This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error +from the `napi_status`, throws it, and returns the value given as the last +parameter. If C++ exceptions are enabled (by defining `NAPI_CPP_EXCEPTIONS` +during the build), the return value will be ignored. + +### `NAPI_THROW_IF_FAILED_VOID(env, status)` + +This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error +from the `napi_status`, throws it, and returns. + +### `NAPI_FATAL_IF_FAILED(status, location, message)` + +This macro accepts a `napi_status`, a C string indicating the location where the +error occurred, and a second C string for the message to display. diff --git a/napi-inl.h b/napi-inl.h index 4f532c77b..d5fbb1bf7 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -17,64 +17,6 @@ namespace Napi { // Helpers to handle functions exposed from C++. namespace details { -#ifdef NAPI_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 -// optional return value that is ignored. -// We need _VOID versions of the macros to avoid warnings resulting from -// leaving the NAPI_THROW_* `...` argument empty. - -#define NAPI_THROW(e, ...) throw e -#define NAPI_THROW_VOID(e) throw e - -#define NAPI_THROW_IF_FAILED(env, status, ...) \ - if ((status) != napi_ok) throw Error::New(env); - -#define NAPI_THROW_IF_FAILED_VOID(env, status) \ - if ((status) != napi_ok) throw Error::New(env); - -#else // NAPI_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 -// is an optional return value; usually it is an empty result. -// We need _VOID versions of the macros to avoid warnings resulting from -// leaving the NAPI_THROW_* `...` argument empty. - -#define NAPI_THROW(e, ...) \ - do { \ - (e).ThrowAsJavaScriptException(); \ - return __VA_ARGS__; \ - } while (0) - -#define NAPI_THROW_VOID(e) \ - do { \ - (e).ThrowAsJavaScriptException(); \ - return; \ - } while (0) - -#define NAPI_THROW_IF_FAILED(env, status, ...) \ - if ((status) != napi_ok) { \ - Error::New(env).ThrowAsJavaScriptException(); \ - return __VA_ARGS__; \ - } - -#define NAPI_THROW_IF_FAILED_VOID(env, status) \ - if ((status) != napi_ok) { \ - Error::New(env).ThrowAsJavaScriptException(); \ - return; \ - } - -#endif // NAPI_CPP_EXCEPTIONS - -#define NAPI_FATAL_IF_FAILED(status, location, message) \ - do { \ - if ((status) != napi_ok) { \ - Error::Fatal((location), (message)); \ - } \ - } while (0) - // 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 @@ -3705,10 +3647,6 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) { return result; } -// These macros shouldn't be useful in user code. -#undef NAPI_THROW -#undef NAPI_THROW_IF_FAILED - } // namespace Napi #endif // SRC_NAPI_INL_H_ diff --git a/napi.h b/napi.h index bff387adb..13ac4853f 100644 --- a/napi.h +++ b/napi.h @@ -38,6 +38,64 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), "Size mismatch between char16 #define NAPI_NOEXCEPT noexcept #endif +#ifdef NAPI_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 +// optional return value that is ignored. +// We need _VOID versions of the macros to avoid warnings resulting from +// leaving the NAPI_THROW_* `...` argument empty. + +#define NAPI_THROW(e, ...) throw e +#define NAPI_THROW_VOID(e) throw e + +#define NAPI_THROW_IF_FAILED(env, status, ...) \ + if ((status) != napi_ok) throw Error::New(env); + +#define NAPI_THROW_IF_FAILED_VOID(env, status) \ + if ((status) != napi_ok) throw Error::New(env); + +#else // NAPI_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 +// is an optional return value; usually it is an empty result. +// We need _VOID versions of the macros to avoid warnings resulting from +// leaving the NAPI_THROW_* `...` argument empty. + +#define NAPI_THROW(e, ...) \ + do { \ + (e).ThrowAsJavaScriptException(); \ + return __VA_ARGS__; \ + } while (0) + +#define NAPI_THROW_VOID(e) \ + do { \ + (e).ThrowAsJavaScriptException(); \ + return; \ + } while (0) + +#define NAPI_THROW_IF_FAILED(env, status, ...) \ + if ((status) != napi_ok) { \ + Error::New(env).ThrowAsJavaScriptException(); \ + return __VA_ARGS__; \ + } + +#define NAPI_THROW_IF_FAILED_VOID(env, status) \ + if ((status) != napi_ok) { \ + Error::New(env).ThrowAsJavaScriptException(); \ + return; \ + } + +#endif // NAPI_CPP_EXCEPTIONS + +#define NAPI_FATAL_IF_FAILED(status, location, message) \ + do { \ + if ((status) != napi_ok) { \ + Error::Fatal((location), (message)); \ + } \ + } while (0) + //////////////////////////////////////////////////////////////////////////////// /// N-API C++ Wrapper Classes ///