Skip to content

Commit fcf173d

Browse files
Gabriel Schulhofmhdawson
authored andcommitted
src: expose macros that throw errors
Macros `NAPI_THROW`, `NAPI_THROW_IF_FAILED`, and `NAPI_FATAL_IF_FAILED` have so far been used only in the implementation of node-addon-api. Nevertheless, they are useful in cases where direct N-API calls must be interspersed between normal node-addon-api usage. The greatest value they provide is that they convert non-`napi_ok` `napi_status` values into errors that can be thrown, and that they throw the errors respecting whether C++ exceptions are enabled or not. PR-URL: #448 Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com> Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@NickNaso.local>
1 parent b409a2f commit fcf173d

File tree

3 files changed

+89
-62
lines changed

3 files changed

+89
-62
lines changed

doc/error_handling.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,34 @@ if (env.IsExceptionPending()) {
153153

154154
Since the exception was cleared here, it will not be propagated as a JavaScript
155155
exception after the native callback returns.
156+
157+
## Calling N-API directly from a **node-addon-api** addon
158+
159+
**node-addon-api** provides macros for throwing errors in response to non-OK
160+
`napi_status` results when calling [N-API](https://nodejs.org/docs/latest/api/n-api.html)
161+
functions from within a native addon. These macros are defined differently
162+
depending on whether C++ exceptions are enabled or not, but are available for
163+
use in either case.
164+
165+
### `NAPI_THROW(e, ...)`
166+
167+
This macro accepts a `Napi::Error`, throws it, and returns the value given as
168+
the last parameter. If C++ exceptions are enabled (by defining
169+
`NAPI_CPP_EXCEPTIONS` during the build), the return value will be ignored.
170+
171+
### `NAPI_THROW_IF_FAILED(env, status, ...)`
172+
173+
This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error
174+
from the `napi_status`, throws it, and returns the value given as the last
175+
parameter. If C++ exceptions are enabled (by defining `NAPI_CPP_EXCEPTIONS`
176+
during the build), the return value will be ignored.
177+
178+
### `NAPI_THROW_IF_FAILED_VOID(env, status)`
179+
180+
This macro accepts a `Napi::Env` and a `napi_status`. It constructs an error
181+
from the `napi_status`, throws it, and returns.
182+
183+
### `NAPI_FATAL_IF_FAILED(status, location, message)`
184+
185+
This macro accepts a `napi_status`, a C string indicating the location where the
186+
error occurred, and a second C string for the message to display.

napi-inl.h

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -17,64 +17,6 @@ namespace Napi {
1717
// Helpers to handle functions exposed from C++.
1818
namespace details {
1919

20-
#ifdef NAPI_CPP_EXCEPTIONS
21-
22-
// When C++ exceptions are enabled, Errors are thrown directly. There is no need
23-
// to return anything after the throw statements. The variadic parameter is an
24-
// optional return value that is ignored.
25-
// We need _VOID versions of the macros to avoid warnings resulting from
26-
// leaving the NAPI_THROW_* `...` argument empty.
27-
28-
#define NAPI_THROW(e, ...) throw e
29-
#define NAPI_THROW_VOID(e) throw e
30-
31-
#define NAPI_THROW_IF_FAILED(env, status, ...) \
32-
if ((status) != napi_ok) throw Error::New(env);
33-
34-
#define NAPI_THROW_IF_FAILED_VOID(env, status) \
35-
if ((status) != napi_ok) throw Error::New(env);
36-
37-
#else // NAPI_CPP_EXCEPTIONS
38-
39-
// When C++ exceptions are disabled, Errors are thrown as JavaScript exceptions,
40-
// which are pending until the callback returns to JS. The variadic parameter
41-
// is an optional return value; usually it is an empty result.
42-
// We need _VOID versions of the macros to avoid warnings resulting from
43-
// leaving the NAPI_THROW_* `...` argument empty.
44-
45-
#define NAPI_THROW(e, ...) \
46-
do { \
47-
(e).ThrowAsJavaScriptException(); \
48-
return __VA_ARGS__; \
49-
} while (0)
50-
51-
#define NAPI_THROW_VOID(e) \
52-
do { \
53-
(e).ThrowAsJavaScriptException(); \
54-
return; \
55-
} while (0)
56-
57-
#define NAPI_THROW_IF_FAILED(env, status, ...) \
58-
if ((status) != napi_ok) { \
59-
Error::New(env).ThrowAsJavaScriptException(); \
60-
return __VA_ARGS__; \
61-
}
62-
63-
#define NAPI_THROW_IF_FAILED_VOID(env, status) \
64-
if ((status) != napi_ok) { \
65-
Error::New(env).ThrowAsJavaScriptException(); \
66-
return; \
67-
}
68-
69-
#endif // NAPI_CPP_EXCEPTIONS
70-
71-
#define NAPI_FATAL_IF_FAILED(status, location, message) \
72-
do { \
73-
if ((status) != napi_ok) { \
74-
Error::Fatal((location), (message)); \
75-
} \
76-
} while (0)
77-
7820
// Attach a data item to an object and delete it when the object gets
7921
// garbage-collected.
8022
// TODO: Replace this code with `napi_add_finalizer()` whenever it becomes
@@ -3705,10 +3647,6 @@ inline const napi_node_version* VersionManagement::GetNodeVersion(Env env) {
37053647
return result;
37063648
}
37073649

3708-
// These macros shouldn't be useful in user code.
3709-
#undef NAPI_THROW
3710-
#undef NAPI_THROW_IF_FAILED
3711-
37123650
} // namespace Napi
37133651

37143652
#endif // SRC_NAPI_INL_H_

napi.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,64 @@ static_assert(sizeof(char16_t) == sizeof(wchar_t), "Size mismatch between char16
3838
#define NAPI_NOEXCEPT noexcept
3939
#endif
4040

41+
#ifdef NAPI_CPP_EXCEPTIONS
42+
43+
// When C++ exceptions are enabled, Errors are thrown directly. There is no need
44+
// to return anything after the throw statements. The variadic parameter is an
45+
// optional return value that is ignored.
46+
// We need _VOID versions of the macros to avoid warnings resulting from
47+
// leaving the NAPI_THROW_* `...` argument empty.
48+
49+
#define NAPI_THROW(e, ...) throw e
50+
#define NAPI_THROW_VOID(e) throw e
51+
52+
#define NAPI_THROW_IF_FAILED(env, status, ...) \
53+
if ((status) != napi_ok) throw Error::New(env);
54+
55+
#define NAPI_THROW_IF_FAILED_VOID(env, status) \
56+
if ((status) != napi_ok) throw Error::New(env);
57+
58+
#else // NAPI_CPP_EXCEPTIONS
59+
60+
// When C++ exceptions are disabled, Errors are thrown as JavaScript exceptions,
61+
// which are pending until the callback returns to JS. The variadic parameter
62+
// is an optional return value; usually it is an empty result.
63+
// We need _VOID versions of the macros to avoid warnings resulting from
64+
// leaving the NAPI_THROW_* `...` argument empty.
65+
66+
#define NAPI_THROW(e, ...) \
67+
do { \
68+
(e).ThrowAsJavaScriptException(); \
69+
return __VA_ARGS__; \
70+
} while (0)
71+
72+
#define NAPI_THROW_VOID(e) \
73+
do { \
74+
(e).ThrowAsJavaScriptException(); \
75+
return; \
76+
} while (0)
77+
78+
#define NAPI_THROW_IF_FAILED(env, status, ...) \
79+
if ((status) != napi_ok) { \
80+
Error::New(env).ThrowAsJavaScriptException(); \
81+
return __VA_ARGS__; \
82+
}
83+
84+
#define NAPI_THROW_IF_FAILED_VOID(env, status) \
85+
if ((status) != napi_ok) { \
86+
Error::New(env).ThrowAsJavaScriptException(); \
87+
return; \
88+
}
89+
90+
#endif // NAPI_CPP_EXCEPTIONS
91+
92+
#define NAPI_FATAL_IF_FAILED(status, location, message) \
93+
do { \
94+
if ((status) != napi_ok) { \
95+
Error::Fatal((location), (message)); \
96+
} \
97+
} while (0)
98+
4199
////////////////////////////////////////////////////////////////////////////////
42100
/// N-API C++ Wrapper Classes
43101
///

0 commit comments

Comments
 (0)