Skip to content

Commit

Permalink
node-api: handle pending exception in cb wrapper
Browse files Browse the repository at this point in the history
fixes: nodejs/node-addon-api#1025

The functionreference test from the node-api tests
was reporting a failed v8 check when Node.js was compiled
as debug. The failure was because an exception was
pending but the C++ wrappers were returning
a return value that was invalid.

Signed-off-by: Michael Dawson <mdawson@devrus.com>

PR-URL: #39476
Fixes: nodejs/node-addon-api#1025
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
  • Loading branch information
mhdawson authored and danielleadams committed Aug 16, 2021
1 parent b1b6f20 commit b585858
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 2 deletions.
8 changes: 6 additions & 2 deletions src/js_native_api_v8.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<v8::Value> value) {
exceptionOccurred = true;
env->isolate->ThrowException(value);
});

if (result != nullptr) {
if (!exceptionOccurred && (result != nullptr)) {
this->SetReturnValue(result);
}
}
Expand Down
8 changes: 8 additions & 0 deletions test/js-native-api/test_function/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
);
23 changes: 23 additions & 0 deletions test/js-native-api/test_function/test_function.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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

0 comments on commit b585858

Please sign in to comment.