Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: expose macros that throw errors #448

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions doc/error_handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
gabrielschulhof marked this conversation as resolved.
Show resolved Hide resolved
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.
62 changes: 0 additions & 62 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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_
58 changes: 58 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down