Skip to content

Commit 13547ba

Browse files
committed
Update to new error helper signatures in n-api
Update to use new signatures Update copies of n-api files so they match. I've not done a direct copy because more work is needed given that the n-api files now use node internals. I have updated so that they are consistent and will build ok with respect to this specific chaange. I took this approach to minimize the time the wrapper is broken by the breaking change on the n-api side. PR-URL: nodejs/node-addon-api#78 Reviewed-By: Kyle Farnung <[email protected]>
1 parent 94a456c commit 13547ba

File tree

4 files changed

+122
-22
lines changed

4 files changed

+122
-22
lines changed

napi-inl.h

+4-4
Original file line numberDiff line numberDiff line change
@@ -1452,10 +1452,10 @@ inline Error Error::New(napi_env env) {
14521452
case napi_string_expected:
14531453
case napi_boolean_expected:
14541454
case napi_number_expected:
1455-
status = napi_create_type_error(env, message, &error);
1455+
status = napi_create_type_error(env, nullptr, message, &error);
14561456
break;
14571457
default:
1458-
status = napi_create_error(env, message, &error);
1458+
status = napi_create_error(env, nullptr, message, &error);
14591459
break;
14601460
}
14611461
assert(status == napi_ok);
@@ -1556,7 +1556,7 @@ inline TError Error::New(napi_env env,
15561556
NAPI_THROW_IF_FAILED(env, status, TError());
15571557

15581558
napi_value error;
1559-
status = create_error(env, str, &error);
1559+
status = create_error(env, nullptr, str, &error);
15601560
NAPI_THROW_IF_FAILED(env, status, TError());
15611561

15621562
return TError(env, error);
@@ -2467,7 +2467,7 @@ inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
24672467
if (status != napi_ok) return nullptr;
24682468

24692469
if (!isConstructCall) {
2470-
napi_throw_type_error(env, "Class constructors cannot be invoked without 'new'");
2470+
napi_throw_type_error(env, nullptr, "Class constructors cannot be invoked without 'new'");
24712471
return nullptr;
24722472
}
24732473

napi.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1085,7 +1085,7 @@ namespace Napi {
10851085

10861086
protected:
10871087
/// !cond INTERNAL
1088-
typedef napi_status (*create_error_fn)(napi_env envb, napi_value msg, napi_value* result);
1088+
typedef napi_status (*create_error_fn)(napi_env envb, napi_value code, napi_value msg, napi_value* result);
10891089

10901090
template <typename TError>
10911091
static TError New(napi_env env,

src/node_api.cc

+105-14
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,61 @@ napi_status napi_create_symbol(napi_env env,
15231523
return GET_RETURN_STATUS(env);
15241524
}
15251525

1526+
static napi_status set_error_code(napi_env env,
1527+
v8::Local<v8::Value> error,
1528+
napi_value code,
1529+
const char* code_cstring) {
1530+
if ((code != nullptr) || (code_cstring != nullptr)) {
1531+
v8::Isolate* isolate = env->isolate;
1532+
v8::Local<v8::Context> context = isolate->GetCurrentContext();
1533+
v8::Local<v8::Object> err_object = error.As<v8::Object>();
1534+
1535+
v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue(code);
1536+
if (code != nullptr) {
1537+
code_value = v8impl::V8LocalValueFromJsValue(code);
1538+
RETURN_STATUS_IF_FALSE(env, code_value->IsString(), napi_string_expected);
1539+
} else {
1540+
CHECK_NEW_FROM_UTF8(env, code_value, code_cstring);
1541+
}
1542+
1543+
v8::Local<v8::Name> code_key;
1544+
CHECK_NEW_FROM_UTF8(env, code_key, "code");
1545+
1546+
v8::Maybe<bool> set_maybe = err_object->Set(context, code_key, code_value);
1547+
RETURN_STATUS_IF_FALSE(env,
1548+
set_maybe.FromMaybe(false),
1549+
napi_generic_failure);
1550+
1551+
// now update the name to be "name [code]" where name is the
1552+
// original name and code is the code associated with the Error
1553+
v8::Local<v8::String> name_string;
1554+
CHECK_NEW_FROM_UTF8(env, name_string, "");
1555+
v8::Local<v8::Name> name_key;
1556+
CHECK_NEW_FROM_UTF8(env, name_key, "name");
1557+
1558+
auto maybe_name = err_object->Get(context, name_key);
1559+
if (!maybe_name.IsEmpty()) {
1560+
v8::Local<v8::Value> name = maybe_name.ToLocalChecked();
1561+
if (name->IsString()) {
1562+
name_string = v8::String::Concat(name_string, name.As<v8::String>());
1563+
}
1564+
}
1565+
name_string = v8::String::Concat(name_string,
1566+
FIXED_ONE_BYTE_STRING(isolate, " ["));
1567+
name_string = v8::String::Concat(name_string, code_value.As<v8::String>());
1568+
name_string = v8::String::Concat(name_string,
1569+
FIXED_ONE_BYTE_STRING(isolate, "]"));
1570+
1571+
set_maybe = err_object->Set(context, name_key, name_string);
1572+
RETURN_STATUS_IF_FALSE(env,
1573+
set_maybe.FromMaybe(false),
1574+
napi_generic_failure);
1575+
}
1576+
return napi_ok;
1577+
}
1578+
15261579
napi_status napi_create_error(napi_env env,
1580+
napi_value code,
15271581
napi_value msg,
15281582
napi_value* result) {
15291583
NAPI_PREAMBLE(env);
@@ -1533,13 +1587,18 @@ napi_status napi_create_error(napi_env env,
15331587
v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
15341588
RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
15351589

1536-
*result = v8impl::JsValueFromV8LocalValue(v8::Exception::Error(
1537-
message_value.As<v8::String>()));
1590+
v8::Local<v8::Value> error_obj =
1591+
v8::Exception::Error(message_value.As<v8::String>());
1592+
napi_status status = set_error_code(env, error_obj, code, nullptr);
1593+
if (status != napi_ok) return status;
1594+
1595+
*result = v8impl::JsValueFromV8LocalValue(error_obj);
15381596

15391597
return GET_RETURN_STATUS(env);
15401598
}
15411599

15421600
napi_status napi_create_type_error(napi_env env,
1601+
napi_value code,
15431602
napi_value msg,
15441603
napi_value* result) {
15451604
NAPI_PREAMBLE(env);
@@ -1549,13 +1608,18 @@ napi_status napi_create_type_error(napi_env env,
15491608
v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
15501609
RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
15511610

1552-
*result = v8impl::JsValueFromV8LocalValue(v8::Exception::TypeError(
1553-
message_value.As<v8::String>()));
1611+
v8::Local<v8::Value> error_obj =
1612+
v8::Exception::TypeError(message_value.As<v8::String>());
1613+
napi_status status = set_error_code(env, error_obj, code, nullptr);
1614+
if (status != napi_ok) return status;
1615+
1616+
*result = v8impl::JsValueFromV8LocalValue(error_obj);
15541617

15551618
return GET_RETURN_STATUS(env);
15561619
}
15571620

15581621
napi_status napi_create_range_error(napi_env env,
1622+
napi_value code,
15591623
napi_value msg,
15601624
napi_value* result) {
15611625
NAPI_PREAMBLE(env);
@@ -1565,8 +1629,12 @@ napi_status napi_create_range_error(napi_env env,
15651629
v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue(msg);
15661630
RETURN_STATUS_IF_FALSE(env, message_value->IsString(), napi_string_expected);
15671631

1568-
*result = v8impl::JsValueFromV8LocalValue(v8::Exception::RangeError(
1569-
message_value.As<v8::String>()));
1632+
v8::Local<v8::Value> error_obj =
1633+
v8::Exception::RangeError(message_value.As<v8::String>());
1634+
napi_status status = set_error_code(env, error_obj, code, nullptr);
1635+
if (status != napi_ok) return status;
1636+
1637+
*result = v8impl::JsValueFromV8LocalValue(error_obj);
15701638

15711639
return GET_RETURN_STATUS(env);
15721640
}
@@ -1739,40 +1807,58 @@ napi_status napi_throw(napi_env env, napi_value error) {
17391807
return napi_clear_last_error(env);
17401808
}
17411809

1742-
napi_status napi_throw_error(napi_env env, const char* msg) {
1810+
napi_status napi_throw_error(napi_env env,
1811+
const char* code,
1812+
const char* msg) {
17431813
NAPI_PREAMBLE(env);
17441814

17451815
v8::Isolate* isolate = env->isolate;
17461816
v8::Local<v8::String> str;
17471817
CHECK_NEW_FROM_UTF8(env, str, msg);
17481818

1749-
isolate->ThrowException(v8::Exception::Error(str));
1819+
v8::Local<v8::Value> error_obj = v8::Exception::Error(str);
1820+
napi_status status = set_error_code(env, error_obj, nullptr, code);
1821+
if (status != napi_ok) return status;
1822+
1823+
isolate->ThrowException(error_obj);
17501824
// any VM calls after this point and before returning
17511825
// to the javascript invoker will fail
17521826
return napi_clear_last_error(env);
17531827
}
17541828

1755-
napi_status napi_throw_type_error(napi_env env, const char* msg) {
1829+
napi_status napi_throw_type_error(napi_env env,
1830+
const char* code,
1831+
const char* msg) {
17561832
NAPI_PREAMBLE(env);
17571833

17581834
v8::Isolate* isolate = env->isolate;
17591835
v8::Local<v8::String> str;
17601836
CHECK_NEW_FROM_UTF8(env, str, msg);
17611837

1762-
isolate->ThrowException(v8::Exception::TypeError(str));
1838+
v8::Local<v8::Value> error_obj = v8::Exception::TypeError(str);
1839+
napi_status status = set_error_code(env, error_obj, nullptr, code);
1840+
if (status != napi_ok) return status;
1841+
1842+
isolate->ThrowException(error_obj);
17631843
// any VM calls after this point and before returning
17641844
// to the javascript invoker will fail
17651845
return napi_clear_last_error(env);
17661846
}
17671847

1768-
napi_status napi_throw_range_error(napi_env env, const char* msg) {
1848+
napi_status napi_throw_range_error(napi_env env,
1849+
const char* code,
1850+
const char* msg) {
17691851
NAPI_PREAMBLE(env);
17701852

17711853
v8::Isolate* isolate = env->isolate;
17721854
v8::Local<v8::String> str;
17731855
CHECK_NEW_FROM_UTF8(env, str, msg);
17741856

1775-
isolate->ThrowException(v8::Exception::RangeError(str));
1857+
v8::Local<v8::Value> error_obj = v8::Exception::RangeError(str);
1858+
napi_status status = set_error_code(env, error_obj, nullptr, code);
1859+
if (status != napi_ok) return status;
1860+
1861+
isolate->ThrowException(error_obj);
17761862
// any VM calls after this point and before returning
17771863
// to the javascript invoker will fail
17781864
return napi_clear_last_error(env);
@@ -2392,7 +2478,9 @@ napi_status napi_instanceof(napi_env env,
23922478
CHECK_TO_OBJECT(env, context, ctor, constructor);
23932479

23942480
if (!ctor->IsFunction()) {
2395-
napi_throw_type_error(env, "constructor must be a function");
2481+
napi_throw_type_error(env,
2482+
"ERR_NAPI_CONS_FUNCTION",
2483+
"Constructor must be a function");
23962484

23972485
return napi_set_last_error(env, napi_function_expected);
23982486
}
@@ -2460,7 +2548,10 @@ napi_status napi_instanceof(napi_env env,
24602548

24612549
v8::Local<v8::Value> prototype_property = maybe_prototype.ToLocalChecked();
24622550
if (!prototype_property->IsObject()) {
2463-
napi_throw_type_error(env, "constructor.prototype must be an object");
2551+
napi_throw_type_error(
2552+
env,
2553+
"ERR_NAPI_CONS_PROTOTYPE_OBJECT",
2554+
"Constructor.prototype must be an object");
24642555

24652556
return napi_set_last_error(env, napi_object_expected);
24662557
}

src/node_api.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -142,12 +142,15 @@ NAPI_EXTERN napi_status napi_create_function(napi_env env,
142142
void* data,
143143
napi_value* result);
144144
NAPI_EXTERN napi_status napi_create_error(napi_env env,
145+
napi_value code,
145146
napi_value msg,
146147
napi_value* result);
147148
NAPI_EXTERN napi_status napi_create_type_error(napi_env env,
149+
napi_value code,
148150
napi_value msg,
149151
napi_value* result);
150152
NAPI_EXTERN napi_status napi_create_range_error(napi_env env,
153+
napi_value code,
151154
napi_value msg,
152155
napi_value* result);
153156

@@ -404,9 +407,15 @@ NAPI_EXTERN napi_status napi_escape_handle(napi_env env,
404407

405408
// Methods to support error handling
406409
NAPI_EXTERN napi_status napi_throw(napi_env env, napi_value error);
407-
NAPI_EXTERN napi_status napi_throw_error(napi_env env, const char* msg);
408-
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env, const char* msg);
409-
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env, const char* msg);
410+
NAPI_EXTERN napi_status napi_throw_error(napi_env env,
411+
const char* code,
412+
const char* msg);
413+
NAPI_EXTERN napi_status napi_throw_type_error(napi_env env,
414+
const char* code,
415+
const char* msg);
416+
NAPI_EXTERN napi_status napi_throw_range_error(napi_env env,
417+
const char* code,
418+
const char* msg);
410419
NAPI_EXTERN napi_status napi_is_error(napi_env env,
411420
napi_value value,
412421
bool* result);

0 commit comments

Comments
 (0)