diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc index fe3d8fbc977..5d18980fc76 100644 --- a/src/js_native_api_v8.cc +++ b/src/js_native_api_v8.cc @@ -306,12 +306,16 @@ class CallbackWrapperBase : public CallbackWrapper { napi_env env = _bundle->env; napi_callback cb = _bundle->cb; - napi_value result; + napi_value result = nullptr; + bool exceptionOccurred = false; env->CallIntoModule([&](napi_env env) { result = cb(env, cbinfo_wrapper); + }, [&](napi_env env, v8::Local value) { + exceptionOccurred = true; + env->isolate->ThrowException(value); }); - if (result != nullptr) { + if (!exceptionOccurred && (result != nullptr)) { this->SetReturnValue(result); } } diff --git a/test/js-native-api/test_function/test.js b/test/js-native-api/test_function/test.js index 988f128404e..972adcd79f5 100644 --- a/test/js-native-api/test_function/test.js +++ b/test/js-native-api/test_function/test.js @@ -42,3 +42,11 @@ assert.deepStrictEqual(test_function.TestCreateFunctionParameters(), { cbIsNull: 'Invalid argument', resultIsNull: 'Invalid argument' }); + +assert.throws( + () => test_function.TestBadReturnExceptionPending(), + { + code: 'throwing exception', + name: 'Error' + } +); diff --git a/test/js-native-api/test_function/test_function.c b/test/js-native-api/test_function/test_function.c index 26445f4736d..107727872a0 100644 --- a/test/js-native-api/test_function/test_function.c +++ b/test/js-native-api/test_function/test_function.c @@ -138,6 +138,19 @@ static napi_value MakeTrackedFunction(napi_env env, napi_callback_info info) { return result; } +static napi_value TestBadReturnExceptionPending(napi_env env, napi_callback_info info) { + napi_throw_error(env, "throwing exception", "throwing exception"); + + // addons should only ever return a valid napi_value even if an + // exception occurs, but we have seen that the C++ wrapper + // with exceptions enabled sometimes returns an invalid value + // when an exception is thrown. Test that we ignore the return + // value then an exeption is pending. We use 0xFFFFFFFF as a value + // that should never be a valid napi_value and node seems to + // crash if it is not ignored indicating that it is indeed invalid. + return (napi_value)(0xFFFFFFFFF); +} + EXTERN_C_START napi_value Init(napi_env env, napi_value exports) { napi_value fn1; @@ -164,6 +177,12 @@ napi_value Init(napi_env env, napi_value exports) { env, "TestCreateFunctionParameters", NAPI_AUTO_LENGTH, TestCreateFunctionParameters, NULL, &fn5)); + napi_value fn6; + NODE_API_CALL(env, + napi_create_function( + env, "TestBadReturnExceptionPending", NAPI_AUTO_LENGTH, + TestBadReturnExceptionPending, NULL, &fn6)); + NODE_API_CALL(env, napi_set_named_property(env, exports, "TestCall", fn1)); NODE_API_CALL(env, napi_set_named_property(env, exports, "TestName", fn2)); NODE_API_CALL(env, @@ -175,6 +194,10 @@ napi_value Init(napi_env env, napi_value exports) { napi_set_named_property( env, exports, "TestCreateFunctionParameters", fn5)); + NODE_API_CALL(env, + napi_set_named_property( + env, exports, "TestBadReturnExceptionPending", fn6)); + return exports; } EXTERN_C_END