diff --git a/napi-inl.h b/napi-inl.h index 0547a910e..e1a92ee80 100644 --- a/napi-inl.h +++ b/napi-inl.h @@ -1373,17 +1373,17 @@ inline void Buffer::EnsureInfo() const { inline Error Error::New(napi_env env) { napi_status status; napi_value error = nullptr; - if (Napi::Env(env).IsExceptionPending()) { - status = napi_get_and_clear_last_exception(env, &error); - assert(status == napi_ok); - } - else { - // No JS exception is pending, so check for NAPI error info. - const napi_extended_error_info* info; - status = napi_get_last_error_info(env, &info); - assert(status == napi_ok); - if (status == napi_ok) { + const napi_extended_error_info* info; + status = napi_get_last_error_info(env, &info); + assert(status == napi_ok); + + if (status == napi_ok) { + if (info->error_code == napi_pending_exception) { + status = napi_get_and_clear_last_exception(env, &error); + assert(status == napi_ok); + } + else { const char* error_message = info->error_message != nullptr ? info->error_message : "Error in native callback"; napi_value message; diff --git a/src/node_api.cc b/src/node_api.cc index bde59c6ad..6dcd0a7c7 100644 --- a/src/node_api.cc +++ b/src/node_api.cc @@ -755,7 +755,7 @@ napi_status napi_get_last_error_info(napi_env env, error_messages[env->last_error.error_code]; *result = &(env->last_error); - return napi_clear_last_error(env); + return napi_ok; } napi_status napi_create_function(napi_env env, diff --git a/test/error.cc b/test/error.cc index 356c7174d..c4c13e172 100644 --- a/test/error.cc +++ b/test/error.cc @@ -4,7 +4,12 @@ using namespace Napi; namespace { -void ThrowError(const CallbackInfo& info) { +void ThrowApiError(const CallbackInfo& info) { + // Attempting to call an empty function value will throw an API error. + Function(info.Env(), nullptr).Call({}); +} + +void ThrowJSError(const CallbackInfo& info) { std::string message = info[0].As().Utf8Value(); throw Error::New(info.Env(), message); } @@ -76,7 +81,8 @@ void CatchAndRethrowErrorThatEscapesScope(const CallbackInfo& info) { Object InitError(Env env) { Object exports = Object::New(env); - exports["throwError"] = Function::New(env, ThrowError); + exports["throwApiError"] = Function::New(env, ThrowApiError); + exports["throwJSError"] = Function::New(env, ThrowJSError); exports["throwTypeError"] = Function::New(env, ThrowTypeError); exports["throwRangeError"] = Function::New(env, ThrowRangeError); exports["catchError"] = Function::New(env, CatchError); diff --git a/test/error.js b/test/error.js index f9430dbd3..f82793f30 100644 --- a/test/error.js +++ b/test/error.js @@ -3,7 +3,11 @@ const buildType = process.config.target_defaults.default_configuration; const binding = require(`./build/${buildType}/binding.node`); const assert = require('assert'); -assert.throws(() => binding.error.throwError('test'), err => { +assert.throws(() => binding.error.throwApiError('test'), err => { + return err instanceof Error && err.message.includes('Invalid'); +}); + +assert.throws(() => binding.error.throwJSError('test'), err => { return err instanceof Error && err.message === 'test'; });