1818#include " uv.h"
1919#include " node_api.h"
2020#include " node_internals.h"
21+ #include " util.h"
2122
2223#define NAPI_VERSION 1
2324
@@ -1527,7 +1528,61 @@ napi_status napi_create_symbol(napi_env env,
15271528 return GET_RETURN_STATUS (env);
15281529}
15291530
1531+ static napi_status set_error_code (napi_env env,
1532+ v8::Local<v8::Value> error,
1533+ napi_value code,
1534+ const char * code_cstring) {
1535+ if ((code != nullptr ) || (code_cstring != nullptr )) {
1536+ v8::Isolate* isolate = env->isolate ;
1537+ v8::Local<v8::Context> context = isolate->GetCurrentContext ();
1538+ v8::Local<v8::Object> err_object = error.As <v8::Object>();
1539+
1540+ v8::Local<v8::Value> code_value = v8impl::V8LocalValueFromJsValue (code);
1541+ if (code != nullptr ) {
1542+ code_value = v8impl::V8LocalValueFromJsValue (code);
1543+ RETURN_STATUS_IF_FALSE (env, code_value->IsString (), napi_string_expected);
1544+ } else {
1545+ CHECK_NEW_FROM_UTF8 (env, code_value, code_cstring);
1546+ }
1547+
1548+ v8::Local<v8::Name> code_key;
1549+ CHECK_NEW_FROM_UTF8 (env, code_key, " code" );
1550+
1551+ v8::Maybe<bool > set_maybe = err_object->Set (context, code_key, code_value);
1552+ RETURN_STATUS_IF_FALSE (env,
1553+ set_maybe.FromMaybe (false ),
1554+ napi_generic_failure);
1555+
1556+ // now update the name to be "name [code]" where name is the
1557+ // original name and code is the code associated with the Error
1558+ v8::Local<v8::String> name_string;
1559+ CHECK_NEW_FROM_UTF8 (env, name_string, " " );
1560+ v8::Local<v8::Name> name_key;
1561+ CHECK_NEW_FROM_UTF8 (env, name_key, " name" );
1562+
1563+ auto maybe_name = err_object->Get (context, name_key);
1564+ if (!maybe_name.IsEmpty ()) {
1565+ v8::Local<v8::Value> name = maybe_name.ToLocalChecked ();
1566+ if (name->IsString ()) {
1567+ name_string = v8::String::Concat (name_string, name.As <v8::String>());
1568+ }
1569+ }
1570+ name_string = v8::String::Concat (name_string,
1571+ FIXED_ONE_BYTE_STRING (isolate, " [" ));
1572+ name_string = v8::String::Concat (name_string, code_value.As <v8::String>());
1573+ name_string = v8::String::Concat (name_string,
1574+ FIXED_ONE_BYTE_STRING (isolate, " ]" ));
1575+
1576+ set_maybe = err_object->Set (context, name_key, name_string);
1577+ RETURN_STATUS_IF_FALSE (env,
1578+ set_maybe.FromMaybe (false ),
1579+ napi_generic_failure);
1580+ }
1581+ return napi_ok;
1582+ }
1583+
15301584napi_status napi_create_error (napi_env env,
1585+ napi_value code,
15311586 napi_value msg,
15321587 napi_value* result) {
15331588 NAPI_PREAMBLE (env);
@@ -1537,13 +1592,18 @@ napi_status napi_create_error(napi_env env,
15371592 v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue (msg);
15381593 RETURN_STATUS_IF_FALSE (env, message_value->IsString (), napi_string_expected);
15391594
1540- *result = v8impl::JsValueFromV8LocalValue (v8::Exception::Error (
1541- message_value.As <v8::String>()));
1595+ v8::Local<v8::Value> error_obj =
1596+ v8::Exception::Error (message_value.As <v8::String>());
1597+ napi_status status = set_error_code (env, error_obj, code, nullptr );
1598+ if (status != napi_ok) return status;
1599+
1600+ *result = v8impl::JsValueFromV8LocalValue (error_obj);
15421601
15431602 return GET_RETURN_STATUS (env);
15441603}
15451604
15461605napi_status napi_create_type_error (napi_env env,
1606+ napi_value code,
15471607 napi_value msg,
15481608 napi_value* result) {
15491609 NAPI_PREAMBLE (env);
@@ -1553,13 +1613,18 @@ napi_status napi_create_type_error(napi_env env,
15531613 v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue (msg);
15541614 RETURN_STATUS_IF_FALSE (env, message_value->IsString (), napi_string_expected);
15551615
1556- *result = v8impl::JsValueFromV8LocalValue (v8::Exception::TypeError (
1557- message_value.As <v8::String>()));
1616+ v8::Local<v8::Value> error_obj =
1617+ v8::Exception::TypeError (message_value.As <v8::String>());
1618+ napi_status status = set_error_code (env, error_obj, code, nullptr );
1619+ if (status != napi_ok) return status;
1620+
1621+ *result = v8impl::JsValueFromV8LocalValue (error_obj);
15581622
15591623 return GET_RETURN_STATUS (env);
15601624}
15611625
15621626napi_status napi_create_range_error (napi_env env,
1627+ napi_value code,
15631628 napi_value msg,
15641629 napi_value* result) {
15651630 NAPI_PREAMBLE (env);
@@ -1569,8 +1634,12 @@ napi_status napi_create_range_error(napi_env env,
15691634 v8::Local<v8::Value> message_value = v8impl::V8LocalValueFromJsValue (msg);
15701635 RETURN_STATUS_IF_FALSE (env, message_value->IsString (), napi_string_expected);
15711636
1572- *result = v8impl::JsValueFromV8LocalValue (v8::Exception::RangeError (
1573- message_value.As <v8::String>()));
1637+ v8::Local<v8::Value> error_obj =
1638+ v8::Exception::RangeError (message_value.As <v8::String>());
1639+ napi_status status = set_error_code (env, error_obj, code, nullptr );
1640+ if (status != napi_ok) return status;
1641+
1642+ *result = v8impl::JsValueFromV8LocalValue (error_obj);
15741643
15751644 return GET_RETURN_STATUS (env);
15761645}
@@ -1743,40 +1812,58 @@ napi_status napi_throw(napi_env env, napi_value error) {
17431812 return napi_clear_last_error (env);
17441813}
17451814
1746- napi_status napi_throw_error (napi_env env, const char * msg) {
1815+ napi_status napi_throw_error (napi_env env,
1816+ const char * code,
1817+ const char * msg) {
17471818 NAPI_PREAMBLE (env);
17481819
17491820 v8::Isolate* isolate = env->isolate ;
17501821 v8::Local<v8::String> str;
17511822 CHECK_NEW_FROM_UTF8 (env, str, msg);
17521823
1753- isolate->ThrowException (v8::Exception::Error (str));
1824+ v8::Local<v8::Value> error_obj = v8::Exception::Error (str);
1825+ napi_status status = set_error_code (env, error_obj, nullptr , code);
1826+ if (status != napi_ok) return status;
1827+
1828+ isolate->ThrowException (error_obj);
17541829 // any VM calls after this point and before returning
17551830 // to the javascript invoker will fail
17561831 return napi_clear_last_error (env);
17571832}
17581833
1759- napi_status napi_throw_type_error (napi_env env, const char * msg) {
1834+ napi_status napi_throw_type_error (napi_env env,
1835+ const char * code,
1836+ const char * msg) {
17601837 NAPI_PREAMBLE (env);
17611838
17621839 v8::Isolate* isolate = env->isolate ;
17631840 v8::Local<v8::String> str;
17641841 CHECK_NEW_FROM_UTF8 (env, str, msg);
17651842
1766- isolate->ThrowException (v8::Exception::TypeError (str));
1843+ v8::Local<v8::Value> error_obj = v8::Exception::TypeError (str);
1844+ napi_status status = set_error_code (env, error_obj, nullptr , code);
1845+ if (status != napi_ok) return status;
1846+
1847+ isolate->ThrowException (error_obj);
17671848 // any VM calls after this point and before returning
17681849 // to the javascript invoker will fail
17691850 return napi_clear_last_error (env);
17701851}
17711852
1772- napi_status napi_throw_range_error (napi_env env, const char * msg) {
1853+ napi_status napi_throw_range_error (napi_env env,
1854+ const char * code,
1855+ const char * msg) {
17731856 NAPI_PREAMBLE (env);
17741857
17751858 v8::Isolate* isolate = env->isolate ;
17761859 v8::Local<v8::String> str;
17771860 CHECK_NEW_FROM_UTF8 (env, str, msg);
17781861
1779- isolate->ThrowException (v8::Exception::RangeError (str));
1862+ v8::Local<v8::Value> error_obj = v8::Exception::RangeError (str);
1863+ napi_status status = set_error_code (env, error_obj, nullptr , code);
1864+ if (status != napi_ok) return status;
1865+
1866+ isolate->ThrowException (error_obj);
17801867 // any VM calls after this point and before returning
17811868 // to the javascript invoker will fail
17821869 return napi_clear_last_error (env);
@@ -2415,7 +2502,9 @@ napi_status napi_instanceof(napi_env env,
24152502 CHECK_TO_OBJECT (env, context, ctor, constructor);
24162503
24172504 if (!ctor->IsFunction ()) {
2418- napi_throw_type_error (env, " constructor must be a function" );
2505+ napi_throw_type_error (env,
2506+ " ERR_NAPI_CONS_FUNCTION" ,
2507+ " Constructor must be a function" );
24192508
24202509 return napi_set_last_error (env, napi_function_expected);
24212510 }
@@ -2483,7 +2572,10 @@ napi_status napi_instanceof(napi_env env,
24832572
24842573 v8::Local<v8::Value> prototype_property = maybe_prototype.ToLocalChecked ();
24852574 if (!prototype_property->IsObject ()) {
2486- napi_throw_type_error (env, " constructor.prototype must be an object" );
2575+ napi_throw_type_error (
2576+ env,
2577+ " ERR_NAPI_CONS_PROTOTYPE_OBJECT" ,
2578+ " Constructor.prototype must be an object" );
24872579
24882580 return napi_set_last_error (env, napi_object_expected);
24892581 }
0 commit comments