Skip to content

Commit 5f8738a

Browse files
committed
Fix reporting of API error messages
When a call to an N-API function caused an error for some reason other than a JS exception, the fallback error message "Error in native callback" was always reported because of incorrect logic in `Napi::Error::New()`. Then that fix exposed a bug in `napi_get_last_error_info()`, which I have fixed here and also at nodejs/node#13087
1 parent a20a867 commit 5f8738a

File tree

4 files changed

+24
-14
lines changed

4 files changed

+24
-14
lines changed

napi-inl.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1355,17 +1355,17 @@ inline void Buffer<T>::EnsureInfo() const {
13551355
inline Error Error::New(napi_env env) {
13561356
napi_status status;
13571357
napi_value error = nullptr;
1358-
if (Napi::Env(env).IsExceptionPending()) {
1359-
status = napi_get_and_clear_last_exception(env, &error);
1360-
assert(status == napi_ok);
1361-
}
1362-
else {
1363-
// No JS exception is pending, so check for NAPI error info.
1364-
const napi_extended_error_info* info;
1365-
status = napi_get_last_error_info(env, &info);
1366-
assert(status == napi_ok);
13671358

1368-
if (status == napi_ok) {
1359+
const napi_extended_error_info* info;
1360+
status = napi_get_last_error_info(env, &info);
1361+
assert(status == napi_ok);
1362+
1363+
if (status == napi_ok) {
1364+
if (info->error_code == napi_pending_exception) {
1365+
status = napi_get_and_clear_last_exception(env, &error);
1366+
assert(status == napi_ok);
1367+
}
1368+
else {
13691369
const char* error_message = info->error_message != nullptr ?
13701370
info->error_message : "Error in native callback";
13711371
napi_value message;

src/node_api.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,7 +755,7 @@ napi_status napi_get_last_error_info(napi_env env,
755755
error_messages[env->last_error.error_code];
756756

757757
*result = &(env->last_error);
758-
return napi_clear_last_error(env);
758+
return napi_ok;
759759
}
760760

761761
napi_status napi_create_function(napi_env env,

test/error.cc

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ using namespace Napi;
44

55
namespace {
66

7-
void ThrowError(const CallbackInfo& info) {
7+
void ThrowApiError(const CallbackInfo& info) {
8+
// Attempting to call an empty function value will throw an API error.
9+
Function(info.Env(), nullptr).Call({});
10+
}
11+
12+
void ThrowJSError(const CallbackInfo& info) {
813
std::string message = info[0].As<String>().Utf8Value();
914
throw Error::New(info.Env(), message);
1015
}
@@ -76,7 +81,8 @@ void CatchAndRethrowErrorThatEscapesScope(const CallbackInfo& info) {
7681

7782
Object InitError(Env env) {
7883
Object exports = Object::New(env);
79-
exports["throwError"] = Function::New(env, ThrowError);
84+
exports["throwApiError"] = Function::New(env, ThrowApiError);
85+
exports["throwJSError"] = Function::New(env, ThrowJSError);
8086
exports["throwTypeError"] = Function::New(env, ThrowTypeError);
8187
exports["throwRangeError"] = Function::New(env, ThrowRangeError);
8288
exports["catchError"] = Function::New(env, CatchError);

test/error.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ const buildType = process.config.target_defaults.default_configuration;
33
const binding = require(`./build/${buildType}/binding.node`);
44
const assert = require('assert');
55

6-
assert.throws(() => binding.error.throwError('test'), err => {
6+
assert.throws(() => binding.error.throwApiError('test'), err => {
7+
return err instanceof Error && err.message.includes('Invalid');
8+
});
9+
10+
assert.throws(() => binding.error.throwJSError('test'), err => {
711
return err instanceof Error && err.message === 'test';
812
});
913

0 commit comments

Comments
 (0)