@@ -19,11 +19,15 @@ namespace details {
1919
2020#ifdef NAPI_CPP_EXCEPTIONS
2121
22- #define NAPI_THROW (e ) throw e
23-
2422// When C++ exceptions are enabled, Errors are thrown directly. There is no need
25- // to return anything after the throw statement . The variadic parameter is an
23+ // to return anything after the throw statements . The variadic parameter is an
2624// 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+
2731#define NAPI_THROW_IF_FAILED (env, status, ...) \
2832 if ((status) != napi_ok) throw Error::New (env);
2933
@@ -32,19 +36,30 @@ namespace details {
3236
3337#else // NAPI_CPP_EXCEPTIONS
3438
35- #define NAPI_THROW (e ) (e).ThrowAsJavaScriptException();
36-
3739// When C++ exceptions are disabled, Errors are thrown as JavaScript exceptions,
3840// which are pending until the callback returns to JS. The variadic parameter
3941// 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+
4057#define NAPI_THROW_IF_FAILED (env, status, ...) \
4158 if ((status) != napi_ok) { \
4259 Error::New (env).ThrowAsJavaScriptException (); \
4360 return __VA_ARGS__; \
4461 }
4562
46- // We need a _VOID version of this macro to avoid warnings resulting from
47- // leaving the NAPI_THROW_IF_FAILED `...` argument empty.
4863#define NAPI_THROW_IF_FAILED_VOID (env, status ) \
4964 if ((status) != napi_ok) { \
5065 Error::New (env).ThrowAsJavaScriptException (); \
@@ -1312,8 +1327,8 @@ inline DataView DataView::New(napi_env env,
13121327 size_t byteOffset) {
13131328 if (byteOffset > arrayBuffer.ByteLength ()) {
13141329 NAPI_THROW (RangeError::New (env,
1315- " Start offset is outside the bounds of the buffer" ));
1316- return DataView ();
1330+ " Start offset is outside the bounds of the buffer" ),
1331+ DataView () );
13171332 }
13181333 return New (env, arrayBuffer, byteOffset,
13191334 arrayBuffer.ByteLength () - byteOffset);
@@ -1324,8 +1339,8 @@ inline DataView DataView::New(napi_env env,
13241339 size_t byteOffset,
13251340 size_t byteLength) {
13261341 if (byteOffset + byteLength > arrayBuffer.ByteLength ()) {
1327- NAPI_THROW (RangeError::New (env, " Invalid DataView length" ));
1328- return DataView ();
1342+ NAPI_THROW (RangeError::New (env, " Invalid DataView length" ),
1343+ DataView () );
13291344 }
13301345 napi_value value;
13311346 napi_status status = napi_create_dataview (
@@ -1451,8 +1466,7 @@ inline T DataView::ReadData(size_t byteOffset) const {
14511466 if (byteOffset + sizeof (T) > _length ||
14521467 byteOffset + sizeof (T) < byteOffset) { // overflow
14531468 NAPI_THROW (RangeError::New (_env,
1454- " Offset is outside the bounds of the DataView" ));
1455- return 0 ;
1469+ " Offset is outside the bounds of the DataView" ), 0 );
14561470 }
14571471
14581472 return *reinterpret_cast <T*>(static_cast <uint8_t *>(_data) + byteOffset);
@@ -1462,9 +1476,8 @@ template <typename T>
14621476inline void DataView::WriteData (size_t byteOffset, T value) const {
14631477 if (byteOffset + sizeof (T) > _length ||
14641478 byteOffset + sizeof (T) < byteOffset) { // overflow
1465- NAPI_THROW (RangeError::New (_env,
1479+ NAPI_THROW_VOID (RangeError::New (_env,
14661480 " Offset is outside the bounds of the DataView" ));
1467- return ;
14681481 }
14691482
14701483 *reinterpret_cast <T*>(static_cast <uint8_t *>(_data) + byteOffset) = value;
@@ -1600,7 +1613,7 @@ inline TypedArrayOf<T>::TypedArrayOf(napi_env env,
16001613 : TypedArray(env, value, type, length), _data(data) {
16011614 if (!(type == TypedArrayTypeForPrimitiveType<T>() ||
16021615 (type == napi_uint8_clamped_array && std::is_same<T, uint8_t >::value))) {
1603- NAPI_THROW (TypeError::New (env, " Array type must match the template parameter. "
1616+ NAPI_THROW_VOID (TypeError::New (env, " Array type must match the template parameter. "
16041617 " (Uint8 arrays may optionally have the \" clamped\" array type.)" ));
16051618 }
16061619}
@@ -2034,8 +2047,20 @@ inline const std::string& Error::Message() const NAPI_NOEXCEPT {
20342047inline void Error::ThrowAsJavaScriptException () const {
20352048 HandleScope scope (_env);
20362049 if (!IsEmpty ()) {
2050+
2051+ // We intentionally don't use `NAPI_THROW_*` macros here to ensure
2052+ // that there is no possible recursion as `ThrowAsJavaScriptException`
2053+ // is part of `NAPI_THROW_*` macro definition for noexcept.
2054+
20372055 napi_status status = napi_throw (_env, Value ());
2038- NAPI_THROW_IF_FAILED_VOID (_env, status);
2056+
2057+ #ifdef NAPI_CPP_EXCEPTIONS
2058+ if (status != napi_ok) {
2059+ throw Error::New (_env);
2060+ }
2061+ #else // NAPI_CPP_EXCEPTIONS
2062+ NAPI_FATAL_IF_FAILED (status, " Error::ThrowAsJavaScriptException" , " napi_throw" );
2063+ #endif // NAPI_CPP_EXCEPTIONS
20392064 }
20402065}
20412066
0 commit comments