@@ -36,6 +36,70 @@ class napi_env__ {
36
36
napi_extended_error_info last_error;
37
37
};
38
38
39
+ #define RETURN_STATUS_IF_FALSE (env, condition, status ) \
40
+ do { \
41
+ if (!(condition)) { \
42
+ return napi_set_last_error ((env), (status)); \
43
+ } \
44
+ } while (0 )
45
+
46
+ #define CHECK_ENV (env ) \
47
+ if ((env) == nullptr ) { \
48
+ node::FatalError (__func__, " environment(env) must not be null" ); \
49
+ }
50
+
51
+ #define CHECK_ARG (env, arg ) \
52
+ RETURN_STATUS_IF_FALSE ((env), ((arg) != nullptr), napi_invalid_arg)
53
+
54
+ #define CHECK_MAYBE_EMPTY (env, maybe, status ) \
55
+ RETURN_STATUS_IF_FALSE ((env), !((maybe).IsEmpty()), (status))
56
+
57
+ #define CHECK_MAYBE_NOTHING (env, maybe, status ) \
58
+ RETURN_STATUS_IF_FALSE ((env), !((maybe).IsNothing()), (status))
59
+
60
+ // NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
61
+ #define NAPI_PREAMBLE (env ) \
62
+ CHECK_ENV ((env)); \
63
+ RETURN_STATUS_IF_FALSE ((env), (env)->last_exception.IsEmpty(), \
64
+ napi_pending_exception); \
65
+ napi_clear_last_error ((env)); \
66
+ v8impl::TryCatch try_catch ((env))
67
+
68
+ #define CHECK_TO_TYPE (env, type, context, result, src, status ) \
69
+ do { \
70
+ auto maybe = v8impl::V8LocalValueFromJsValue ((src))->To ##type ((context)); \
71
+ CHECK_MAYBE_EMPTY ((env), maybe, (status)); \
72
+ (result) = maybe.ToLocalChecked (); \
73
+ } while (0 )
74
+
75
+ #define CHECK_TO_OBJECT (env, context, result, src ) \
76
+ CHECK_TO_TYPE ((env), Object, (context), (result), (src), napi_object_expected)
77
+
78
+ #define CHECK_TO_STRING (env, context, result, src ) \
79
+ CHECK_TO_TYPE ((env), String, (context), (result), (src), napi_string_expected)
80
+
81
+ #define CHECK_TO_NUMBER (env, context, result, src ) \
82
+ CHECK_TO_TYPE ((env), Number, (context), (result), (src), napi_number_expected)
83
+
84
+ #define CHECK_TO_BOOL (env, context, result, src ) \
85
+ CHECK_TO_TYPE ((env), Boolean, (context), (result), (src), \
86
+ napi_boolean_expected)
87
+
88
+ #define CHECK_NEW_FROM_UTF8_LEN (env, result, str, len ) \
89
+ do { \
90
+ auto str_maybe = v8::String::NewFromUtf8 ( \
91
+ (env)->isolate , (str), v8::NewStringType::kInternalized , (len)); \
92
+ CHECK_MAYBE_EMPTY ((env), str_maybe, napi_generic_failure); \
93
+ (result) = str_maybe.ToLocalChecked (); \
94
+ } while (0 )
95
+
96
+ #define CHECK_NEW_FROM_UTF8 (env, result, str ) \
97
+ CHECK_NEW_FROM_UTF8_LEN ((env), (result), (str), -1)
98
+
99
+ #define GET_RETURN_STATUS (env ) \
100
+ (!try_catch.HasCaught() ? napi_ok \
101
+ : napi_set_last_error((env), napi_pending_exception))
102
+
39
103
namespace v8impl {
40
104
41
105
// convert from n-api property attributes to v8::PropertyAttribute
@@ -127,6 +191,22 @@ v8::Local<v8::Value> V8LocalValueFromJsValue(napi_value v) {
127
191
return local;
128
192
}
129
193
194
+ static inline napi_status V8NameFromPropertyDescriptor (napi_env env,
195
+ const napi_property_descriptor* p,
196
+ v8::Local<v8::Name>* result) {
197
+ if (p->utf8name != nullptr ) {
198
+ CHECK_NEW_FROM_UTF8 (env, *result, p->utf8name );
199
+ } else {
200
+ v8::Local<v8::Value> property_value =
201
+ v8impl::V8LocalValueFromJsValue (p->name );
202
+
203
+ RETURN_STATUS_IF_FALSE (env, property_value->IsName (), napi_name_expected);
204
+ *result = property_value.As <v8::Name>();
205
+ }
206
+
207
+ return napi_ok;
208
+ }
209
+
130
210
// Adapter for napi_finalize callbacks.
131
211
class Finalizer {
132
212
protected:
@@ -361,13 +441,19 @@ class CallbackWrapperBase : public CallbackWrapper {
361
441
v8::Local<v8::External>::Cast (
362
442
_cbdata->GetInternalField (kInternalFieldIndex ))->Value ());
363
443
v8::Isolate* isolate = _cbinfo.GetIsolate ();
444
+
364
445
napi_env env = static_cast <napi_env>(
365
446
v8::Local<v8::External>::Cast (
366
447
_cbdata->GetInternalField (kEnvIndex ))->Value ());
367
448
368
449
// Make sure any errors encountered last time we were in N-API are gone.
369
450
napi_clear_last_error (env);
370
- cb (env, cbinfo_wrapper);
451
+
452
+ napi_value result = cb (env, cbinfo_wrapper);
453
+
454
+ if (result != nullptr ) {
455
+ this ->SetReturnValue (result);
456
+ }
371
457
372
458
if (!env->last_exception .IsEmpty ()) {
373
459
isolate->ThrowException (
@@ -608,75 +694,12 @@ void napi_module_register(napi_module* mod) {
608
694
node::node_module_register (nm);
609
695
}
610
696
611
- #define RETURN_STATUS_IF_FALSE (env, condition, status ) \
612
- do { \
613
- if (!(condition)) { \
614
- return napi_set_last_error ((env), (status)); \
615
- } \
616
- } while (0 )
617
-
618
- #define CHECK_ENV (env ) \
619
- if ((env) == nullptr ) { \
620
- node::FatalError (__func__, " environment(env) must not be null" ); \
621
- }
622
-
623
- #define CHECK_ARG (env, arg ) \
624
- RETURN_STATUS_IF_FALSE ((env), ((arg) != nullptr ), napi_invalid_arg)
625
-
626
- #define CHECK_MAYBE_EMPTY (env, maybe, status ) \
627
- RETURN_STATUS_IF_FALSE ((env), !((maybe).IsEmpty()), (status))
628
-
629
- #define CHECK_MAYBE_NOTHING (env, maybe, status ) \
630
- RETURN_STATUS_IF_FALSE ((env), !((maybe).IsNothing()), (status))
631
-
632
- // NAPI_PREAMBLE is not wrapped in do..while: try_catch must have function scope
633
- #define NAPI_PREAMBLE (env ) \
634
- CHECK_ENV ((env)); \
635
- RETURN_STATUS_IF_FALSE ((env), (env)->last_exception.IsEmpty(), \
636
- napi_pending_exception); \
637
- napi_clear_last_error ((env)); \
638
- v8impl::TryCatch try_catch ((env))
639
-
640
- #define CHECK_TO_TYPE (env, type, context, result, src, status ) \
641
- do { \
642
- auto maybe = v8impl::V8LocalValueFromJsValue ((src))->To ##type ((context)); \
643
- CHECK_MAYBE_EMPTY ((env), maybe, (status)); \
644
- (result) = maybe.ToLocalChecked (); \
645
- } while (0 )
646
-
647
- #define CHECK_TO_OBJECT (env, context, result, src ) \
648
- CHECK_TO_TYPE ((env), Object, (context), (result), (src), napi_object_expected)
649
-
650
- #define CHECK_TO_STRING (env, context, result, src ) \
651
- CHECK_TO_TYPE ((env), String, (context), (result), (src), napi_string_expected)
652
-
653
- #define CHECK_TO_NUMBER (env, context, result, src ) \
654
- CHECK_TO_TYPE ((env), Number, (context), (result), (src), napi_number_expected)
655
-
656
- #define CHECK_TO_BOOL (env, context, result, src ) \
657
- CHECK_TO_TYPE ((env), Boolean , (context), (result), (src), \
658
- napi_boolean_expected)
659
-
660
- #define CHECK_NEW_FROM_UTF8_LEN (env, result, str, len ) \
661
- do { \
662
- auto str_maybe = v8::String::NewFromUtf8 ( \
663
- (env)->isolate , (str), v8::NewStringType::kInternalized , (len)); \
664
- CHECK_MAYBE_EMPTY ((env), str_maybe, napi_generic_failure); \
665
- result = str_maybe.ToLocalChecked (); \
666
- } while (0 )
667
-
668
- #define CHECK_NEW_FROM_UTF8 (env, result, str ) \
669
- CHECK_NEW_FROM_UTF8_LEN ((env), (result), (str), -1 )
670
-
671
- #define GET_RETURN_STATUS (env ) \
672
- (!try_catch.HasCaught() ? napi_ok \
673
- : napi_set_last_error((env), napi_pending_exception))
674
-
675
697
// Warning: Keep in-sync with napi_status enum
676
698
const char * error_messages[] = {nullptr ,
677
699
" Invalid pointer passed as argument" ,
678
700
" An object was expected" ,
679
701
" A string was expected" ,
702
+ " A string or symbol was expected" ,
680
703
" A function was expected" ,
681
704
" A number was expected" ,
682
705
" A boolean was expected" ,
@@ -793,8 +816,14 @@ napi_status napi_define_class(napi_env env,
793
816
continue ;
794
817
}
795
818
796
- v8::Local<v8::String> property_name;
797
- CHECK_NEW_FROM_UTF8 (env, property_name, p->utf8name );
819
+ v8::Local<v8::Name> property_name;
820
+ napi_status status =
821
+ v8impl::V8NameFromPropertyDescriptor (env, p, &property_name);
822
+
823
+ if (status != napi_ok) {
824
+ return napi_set_last_error (env, status);
825
+ }
826
+
798
827
v8::PropertyAttribute attributes =
799
828
v8impl::V8PropertyAttributesFromDescriptor (p);
800
829
@@ -822,7 +851,6 @@ napi_status napi_define_class(napi_env env,
822
851
v8impl::FunctionCallbackWrapper::Invoke,
823
852
cbdata,
824
853
v8::Signature::New (isolate, tpl));
825
- t->SetClassName (property_name);
826
854
827
855
tpl->PrototypeTemplate ()->Set (property_name, t, attributes);
828
856
} else {
@@ -855,18 +883,6 @@ napi_status napi_define_class(napi_env env,
855
883
return GET_RETURN_STATUS (env);
856
884
}
857
885
858
- napi_status napi_set_return_value (napi_env env,
859
- napi_callback_info cbinfo,
860
- napi_value value) {
861
- NAPI_PREAMBLE (env);
862
-
863
- v8impl::CallbackWrapper* info =
864
- reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
865
-
866
- info->SetReturnValue (value);
867
- return GET_RETURN_STATUS (env);
868
- }
869
-
870
886
napi_status napi_get_property_names (napi_env env,
871
887
napi_value object,
872
888
napi_value* result) {
@@ -1102,11 +1118,16 @@ napi_status napi_define_properties(napi_env env,
1102
1118
for (size_t i = 0 ; i < property_count; i++) {
1103
1119
const napi_property_descriptor* p = &properties[i];
1104
1120
1105
- v8::Local<v8::Name> name;
1106
- CHECK_NEW_FROM_UTF8 (env, name, p->utf8name );
1121
+ v8::Local<v8::Name> property_name;
1122
+ napi_status status =
1123
+ v8impl::V8NameFromPropertyDescriptor (env, p, &property_name);
1124
+
1125
+ if (status != napi_ok) {
1126
+ return napi_set_last_error (env, status);
1127
+ }
1107
1128
1108
1129
v8::PropertyAttribute attributes =
1109
- v8impl::V8PropertyAttributesFromDescriptor (p);
1130
+ v8impl::V8PropertyAttributesFromDescriptor (p);
1110
1131
1111
1132
if (p->getter != nullptr || p->setter != nullptr ) {
1112
1133
v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData (
@@ -1117,7 +1138,7 @@ napi_status napi_define_properties(napi_env env,
1117
1138
1118
1139
auto set_maybe = obj->SetAccessor (
1119
1140
context,
1120
- name ,
1141
+ property_name ,
1121
1142
p->getter ? v8impl::GetterCallbackWrapper::Invoke : nullptr ,
1122
1143
p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr ,
1123
1144
cbdata,
@@ -1136,8 +1157,8 @@ napi_status napi_define_properties(napi_env env,
1136
1157
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New (
1137
1158
isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
1138
1159
1139
- auto define_maybe =
1140
- obj-> DefineOwnProperty ( context, name , t->GetFunction (), attributes);
1160
+ auto define_maybe = obj-> DefineOwnProperty (
1161
+ context, property_name , t->GetFunction (), attributes);
1141
1162
1142
1163
if (!define_maybe.FromMaybe (false )) {
1143
1164
return napi_set_last_error (env, napi_generic_failure);
@@ -1146,7 +1167,7 @@ napi_status napi_define_properties(napi_env env,
1146
1167
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue (p->value );
1147
1168
1148
1169
auto define_maybe =
1149
- obj->DefineOwnProperty (context, name , value, attributes);
1170
+ obj->DefineOwnProperty (context, property_name , value, attributes);
1150
1171
1151
1172
if (!define_maybe.FromMaybe (false )) {
1152
1173
return napi_set_last_error (env, napi_invalid_arg);
@@ -1439,33 +1460,24 @@ napi_status napi_get_cb_info(
1439
1460
napi_value* this_arg, // [out] Receives the JS 'this' arg for the call
1440
1461
void ** data) { // [out] Receives the data pointer for the callback.
1441
1462
CHECK_ENV (env);
1442
- CHECK_ARG (env, argc);
1443
- CHECK_ARG (env, argv);
1444
- CHECK_ARG (env, this_arg);
1445
- CHECK_ARG (env, data);
1446
1463
1447
1464
v8impl::CallbackWrapper* info =
1448
1465
reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
1449
1466
1450
- info->Args (argv, std::min (*argc, info->ArgsLength ()));
1451
- *argc = info->ArgsLength ();
1452
- *this_arg = info->This ();
1453
- *data = info->Data ();
1454
-
1455
- return napi_ok;
1456
- }
1457
-
1458
- napi_status napi_get_cb_args_length (napi_env env,
1459
- napi_callback_info cbinfo,
1460
- size_t * result) {
1461
- // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
1462
- CHECK_ENV (env);
1463
- CHECK_ARG (env, result);
1464
-
1465
- v8impl::CallbackWrapper* info =
1466
- reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
1467
+ if (argv != nullptr ) {
1468
+ CHECK_ARG (env, argc);
1469
+ info->Args (argv, std::min (*argc, info->ArgsLength ()));
1470
+ }
1471
+ if (argc != nullptr ) {
1472
+ *argc = info->ArgsLength ();
1473
+ }
1474
+ if (this_arg != nullptr ) {
1475
+ *this_arg = info->This ();
1476
+ }
1477
+ if (data != nullptr ) {
1478
+ *data = info->Data ();
1479
+ }
1467
1480
1468
- *result = info->ArgsLength ();
1469
1481
return napi_ok;
1470
1482
}
1471
1483
@@ -1483,51 +1495,6 @@ napi_status napi_is_construct_call(napi_env env,
1483
1495
return napi_ok;
1484
1496
}
1485
1497
1486
- // copy encoded arguments into provided buffer or return direct pointer to
1487
- // encoded arguments array?
1488
- napi_status napi_get_cb_args (napi_env env,
1489
- napi_callback_info cbinfo,
1490
- napi_value* buf,
1491
- size_t bufsize) {
1492
- // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
1493
- CHECK_ENV (env);
1494
- CHECK_ARG (env, buf);
1495
-
1496
- v8impl::CallbackWrapper* info =
1497
- reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
1498
-
1499
- info->Args (buf, bufsize);
1500
- return napi_ok;
1501
- }
1502
-
1503
- napi_status napi_get_cb_this (napi_env env,
1504
- napi_callback_info cbinfo,
1505
- napi_value* result) {
1506
- // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
1507
- CHECK_ENV (env);
1508
- CHECK_ARG (env, result);
1509
-
1510
- v8impl::CallbackWrapper* info =
1511
- reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
1512
-
1513
- *result = info->This ();
1514
- return napi_ok;
1515
- }
1516
-
1517
- napi_status napi_get_cb_data (napi_env env,
1518
- napi_callback_info cbinfo,
1519
- void ** result) {
1520
- // Omit NAPI_PREAMBLE and GET_RETURN_STATUS because no V8 APIs are called.
1521
- CHECK_ENV (env);
1522
- CHECK_ARG (env, result);
1523
-
1524
- v8impl::CallbackWrapper* info =
1525
- reinterpret_cast <v8impl::CallbackWrapper*>(cbinfo);
1526
-
1527
- *result = info->Data ();
1528
- return napi_ok;
1529
- }
1530
-
1531
1498
napi_status napi_call_function (napi_env env,
1532
1499
napi_value recv,
1533
1500
napi_value func,
0 commit comments