@@ -90,20 +90,7 @@ using namespace Zig;
90
90
/* You should not use this throw scope directly -- if you need */ \
91
91
/* to throw or clear exceptions, make your own scope */ \
92
92
auto napi_preamble_throw_scope__ = DECLARE_THROW_SCOPE(_env->vm ()); \
93
- NAPI_RETURN_IF_EXCEPTION (_env)
94
-
95
- // Every NAPI function should use this at the start. It does the following:
96
- // - if NAPI_VERBOSE is 1, log that the function was called
97
- // - if env is nullptr, return napi_invalid_arg
98
- // - if there is a pending exception, return napi_pending_exception
99
- // No do..while is used as this declares a variable that other macros need to use
100
- #define NAPI_PREAMBLE (_env ) \
101
- NAPI_LOG_CURRENT_FUNCTION; \
102
- NAPI_CHECK_ARG (_env, _env); \
103
- /* You should not use this throw scope directly -- if you need */ \
104
- /* to throw or clear exceptions, make your own scope */ \
105
- auto napi_preamble_throw_scope__ = DECLARE_THROW_SCOPE(_env->vm ()); \
106
- NAPI_RETURN_IF_EXCEPTION (_env)
93
+ NAPI_RETURN_IF_VM_EXCEPTION (_env)
107
94
108
95
// Only use this for functions that need their own throw or catch scope. Functions that call into
109
96
// JS code that might throw should use NAPI_RETURN_IF_EXCEPTION.
@@ -136,7 +123,17 @@ using namespace Zig;
136
123
} while (0 )
137
124
138
125
// Return an error code if an exception was thrown after NAPI_PREAMBLE
139
- #define NAPI_RETURN_IF_EXCEPTION (_env ) RETURN_IF_EXCEPTION(napi_preamble_throw_scope__, napi_set_last_error(_env, napi_pending_exception))
126
+ #define NAPI_RETURN_IF_VM_EXCEPTION (_env ) RETURN_IF_EXCEPTION(napi_preamble_throw_scope__, napi_set_last_error((_env), napi_pending_exception))
127
+
128
+ #define NAPI_RETURN_IF_EXCEPTION_WITH_SCOPE (_env, _scope ) \
129
+ do { \
130
+ RETURN_IF_EXCEPTION ((_scope), napi_set_last_error ((_env), napi_pending_exception)); \
131
+ if ((_env)->hasPendingException ()) { \
132
+ return napi_set_last_error ((_env), napi_pending_exception); \
133
+ } \
134
+ } while (0 )
135
+
136
+ #define NAPI_RETURN_IF_EXCEPTION (_env ) NAPI_RETURN_IF_EXCEPTION_WITH_SCOPE((_env), napi_preamble_throw_scope__)
140
137
141
138
// Return indicating that no error occurred in a NAPI function, and an exception is not expected
142
139
#define NAPI_RETURN_SUCCESS (_env ) \
@@ -918,6 +915,7 @@ extern "C" napi_status napi_create_function(napi_env env, const char* utf8name,
918
915
void * data, napi_value* result)
919
916
{
920
917
NAPI_PREAMBLE (env);
918
+ NAPI_RETURN_IF_EXCEPTION (env);
921
919
NAPI_CHECK_ARG (env, result);
922
920
NAPI_CHECK_ARG (env, cb);
923
921
@@ -961,18 +959,17 @@ napi_define_properties(napi_env env, napi_value object, size_t property_count,
961
959
const napi_property_descriptor* properties)
962
960
{
963
961
NAPI_PREAMBLE_NO_THROW_SCOPE (env);
964
- NAPI_CHECK_ARG (env, object);
965
- NAPI_RETURN_EARLY_IF_FALSE (env, properties || property_count == 0 , napi_invalid_arg);
966
-
967
962
Zig::GlobalObject* globalObject = toJS (env);
968
963
JSC::VM& vm = JSC::getVM (globalObject);
964
+ auto throwScope = DECLARE_THROW_SCOPE (vm);
965
+ NAPI_RETURN_IF_EXCEPTION_WITH_SCOPE (env, throwScope);
966
+ NAPI_CHECK_ARG (env, object);
967
+ NAPI_RETURN_EARLY_IF_FALSE (env, properties || property_count == 0 , napi_invalid_arg);
969
968
970
969
JSValue objectValue = toJS (object);
971
970
JSC::JSObject* objectObject = objectValue.getObject ();
972
971
NAPI_RETURN_EARLY_IF_FALSE (env, objectObject, napi_object_expected);
973
972
974
- auto throwScope = DECLARE_THROW_SCOPE (vm);
975
-
976
973
for (size_t i = 0 ; i < property_count; i++) {
977
974
Napi::defineProperty (env, objectObject, properties[i], true , throwScope);
978
975
@@ -1003,7 +1000,6 @@ static napi_status throwErrorWithCStrings(napi_env env, const char* code_utf8, c
1003
1000
{
1004
1001
auto * globalObject = toJS (env);
1005
1002
auto & vm = JSC::getVM (globalObject);
1006
- auto scope = DECLARE_THROW_SCOPE (vm);
1007
1003
1008
1004
if (!msg_utf8) {
1009
1005
return napi_set_last_error (env, napi_invalid_arg);
@@ -1012,8 +1008,8 @@ static napi_status throwErrorWithCStrings(napi_env env, const char* code_utf8, c
1012
1008
WTF::String code = code_utf8 ? WTF::String::fromUTF8 (code_utf8) : WTF::String ();
1013
1009
WTF::String message = WTF::String::fromUTF8 (msg_utf8);
1014
1010
1015
- auto * error = createErrorWithCode (vm, globalObject, code, message, type);
1016
- scope. throwException (globalObject, error);
1011
+ JSC::ErrorInstance * error = createErrorWithCode (vm, globalObject, code, message, type);
1012
+ env-> scheduleException ( error);
1017
1013
return napi_set_last_error (env, napi_ok);
1018
1014
}
1019
1015
@@ -1254,9 +1250,13 @@ extern "C" napi_status napi_is_exception_pending(napi_env env, bool* result)
1254
1250
NAPI_CHECK_ENV_NOT_IN_GC (env);
1255
1251
NAPI_CHECK_ARG (env, result);
1256
1252
1257
- auto globalObject = toJS (env);
1258
- auto scope = DECLARE_THROW_SCOPE (JSC::getVM (globalObject));
1259
- *result = scope.exception () != nullptr ;
1253
+ if (env->hasPendingException ()) {
1254
+ *result = true ;
1255
+ } else {
1256
+ auto globalObject = toJS (env);
1257
+ auto scope = DECLARE_THROW_SCOPE (JSC::getVM (globalObject));
1258
+ *result = scope.exception () != nullptr ;
1259
+ }
1260
1260
// skip macros as they assume we made a throw scope in the preamble
1261
1261
return napi_set_last_error (env, napi_ok);
1262
1262
}
@@ -1275,6 +1275,9 @@ extern "C" napi_status napi_get_and_clear_last_exception(napi_env env,
1275
1275
auto scope = DECLARE_CATCH_SCOPE (JSC::getVM (globalObject));
1276
1276
if (scope.exception ()) [[unlikely]] {
1277
1277
*result = toNapi (JSValue (scope.exception ()->value ()), globalObject);
1278
+ } else if (std::optional<JSValue> pending = env->pendingException ()) {
1279
+ *result = toNapi (pending.value (), globalObject);
1280
+ env->clearPendingException ();
1278
1281
} else {
1279
1282
*result = toNapi (JSC::jsUndefined (), globalObject);
1280
1283
}
@@ -1300,16 +1303,15 @@ extern "C" napi_status napi_fatal_exception(napi_env env,
1300
1303
1301
1304
extern " C" napi_status napi_throw (napi_env env, napi_value error)
1302
1305
{
1303
- NAPI_PREAMBLE_NO_THROW_SCOPE (env);
1306
+ NAPI_PREAMBLE (env);
1307
+ NAPI_CHECK_ENV_NOT_IN_GC (env);
1308
+ NAPI_RETURN_IF_EXCEPTION (env);
1309
+ if (env->isFinishingFinalizers ()) {
1310
+ return napi_set_last_error (env, env->napiModule ().nm_version >= 10 ? napi_cannot_run_js : napi_pending_exception);
1311
+ }
1304
1312
NAPI_CHECK_ARG (env, error);
1305
- auto globalObject = toJS (env);
1306
- JSC::VM& vm = JSC::getVM (globalObject);
1307
- auto throwScope = DECLARE_THROW_SCOPE (vm);
1308
-
1309
- JSValue value = toJS (error);
1310
- JSC::throwException (globalObject, throwScope, value);
1311
-
1312
- return napi_set_last_error (env, napi_ok);
1313
+ env->scheduleException (toJS (error));
1314
+ NAPI_RETURN_SUCCESS (env);
1313
1315
}
1314
1316
1315
1317
extern " C" napi_status node_api_symbol_for (napi_env env,
@@ -1486,7 +1488,7 @@ extern "C" JS_EXPORT napi_status node_api_create_buffer_from_arraybuffer(napi_en
1486
1488
if (!impl || byte_offset + byte_length > impl->byteLength ()) [[unlikely]] {
1487
1489
auto * error = createErrorWithCode (JSC::getVM (globalObject), globalObject, " ERR_OUT_OF_RANGE" _s, " The byte offset + length is out of range" _s, JSC::ErrorType::RangeError);
1488
1490
RETURN_IF_EXCEPTION (scope, napi_set_last_error (env, napi_pending_exception));
1489
- scope. throwException (globalObject, error);
1491
+ env-> scheduleException ( error);
1490
1492
return napi_set_last_error (env, napi_pending_exception);
1491
1493
}
1492
1494
@@ -2112,9 +2114,9 @@ napi_status napi_get_value_string_any_encoding(napi_env env, napi_value napiValu
2112
2114
2113
2115
Zig::GlobalObject* globalObject = toJS (env);
2114
2116
JSString* jsString = jsValue.toString (globalObject);
2115
- NAPI_RETURN_IF_EXCEPTION (env);
2117
+ NAPI_RETURN_IF_VM_EXCEPTION (env);
2116
2118
const auto view = jsString->view (globalObject);
2117
- NAPI_RETURN_IF_EXCEPTION (env);
2119
+ NAPI_RETURN_IF_VM_EXCEPTION (env);
2118
2120
2119
2121
if (buf == nullptr ) {
2120
2122
// they just want to know the length
@@ -2530,7 +2532,7 @@ extern "C" napi_status napi_run_script(napi_env env, napi_value script,
2530
2532
JSValue value = JSC::evaluate (globalObject, sourceCode, globalObject->globalThis (), returnedException);
2531
2533
2532
2534
if (returnedException) {
2533
- throwScope. throwException (globalObject, returnedException);
2535
+ env-> scheduleException ( returnedException. get () );
2534
2536
return napi_set_last_error (env, napi_pending_exception);
2535
2537
}
2536
2538
@@ -2707,6 +2709,10 @@ extern "C" napi_status napi_call_function(napi_env env, napi_value recv,
2707
2709
const napi_value* argv,
2708
2710
napi_value* result)
2709
2711
{
2712
+ if (env->throwPendingException ()) {
2713
+ return napi_set_last_error (env, napi_pending_exception);
2714
+ }
2715
+
2710
2716
NAPI_PREAMBLE (env);
2711
2717
NAPI_RETURN_EARLY_IF_FALSE (env, argc == 0 || argv, napi_invalid_arg);
2712
2718
NAPI_CHECK_ARG (env, func);
@@ -2863,4 +2869,15 @@ extern "C" JSGlobalObject* NapiEnv__globalObject(napi_env env)
2863
2869
return env->globalObject ();
2864
2870
}
2865
2871
2872
+ extern " C" bool NapiEnv__getAndClearPendingException (napi_env env, JSC::EncodedJSValue* exception)
2873
+ {
2874
+ if (std::optional<JSC::JSValue> pending = env->pendingException ()) {
2875
+ *exception = JSValue::encode (*pending);
2876
+ env->clearPendingException ();
2877
+ return true ;
2878
+ }
2879
+
2880
+ return false ;
2881
+ }
2882
+
2866
2883
}
0 commit comments