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