Skip to content

Commit 784e07c

Browse files
authored
napi: Property & class definition improvements (nodejs#97)
- Rename napi_create_constructor to napi_define_class and include support for defining static properties on the class at the same time - Rename napi_define_property to napi_define_properties to allow for defining multiple properties at the same time - Update tests for the changes
1 parent 758fde2 commit 784e07c

23 files changed

Lines changed: 149 additions & 128 deletions

File tree

src/node_jsvmapi.cc

Lines changed: 91 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -596,24 +596,23 @@ napi_status napi_create_function(
596596
return GET_RETURN_STATUS();
597597
}
598598

599-
napi_status napi_create_constructor(
599+
napi_status napi_define_class(
600600
napi_env e,
601601
const char* utf8name,
602-
napi_callback cb,
602+
napi_callback constructor,
603603
void* data,
604604
int property_count,
605-
napi_property_descriptor* properties,
605+
const napi_property_descriptor* properties,
606606
napi_value* result) {
607607
NAPI_PREAMBLE(e);
608608
CHECK_ARG(result);
609609

610610
v8::Isolate *isolate = v8impl::V8IsolateFromJsEnv(e);
611611
v8::Local<v8::Context> context = isolate->GetCurrentContext();
612-
v8::Local<v8::Object> retval;
613612

614613
v8::EscapableHandleScope scope(isolate);
615614
v8::Local<v8::Object> cbdata =
616-
v8impl::CreateFunctionCallbackData(e, cb, data);
615+
v8impl::CreateFunctionCallbackData(e, constructor, data);
617616

618617
RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure);
619618

@@ -627,8 +626,16 @@ napi_status napi_create_constructor(
627626
CHECK_NEW_FROM_UTF8(isolate, namestring, utf8name);
628627
tpl->SetClassName(namestring);
629628

629+
int staticPropertyCount = 0;
630630
for (int i = 0; i < property_count; i++) {
631-
napi_property_descriptor* p = properties + i;
631+
const napi_property_descriptor* p = properties + i;
632+
633+
if ((p->attributes & napi_static_property) != 0) {
634+
// Static properties are handled separately below.
635+
staticPropertyCount++;
636+
continue;
637+
}
638+
632639
v8::Local<v8::String> propertyname;
633640
CHECK_NEW_FROM_UTF8(isolate, propertyname, p->utf8name);
634641

@@ -671,8 +678,23 @@ napi_status napi_create_constructor(
671678
}
672679
}
673680

674-
retval = scope.Escape(tpl->GetFunction());
675-
*result = v8impl::JsValueFromV8LocalValue(retval);
681+
*result = v8impl::JsValueFromV8LocalValue(scope.Escape(tpl->GetFunction()));
682+
683+
if (staticPropertyCount > 0) {
684+
std::vector<napi_property_descriptor> staticDescriptors;
685+
staticDescriptors.reserve(staticPropertyCount);
686+
687+
for (int i = 0; i < property_count; i++) {
688+
const napi_property_descriptor* p = properties + i;
689+
if ((p->attributes & napi_static_property) != 0) {
690+
staticDescriptors.push_back(*p);
691+
}
692+
}
693+
694+
napi_status status = napi_define_properties(
695+
e, *result, staticDescriptors.size(), staticDescriptors.data());
696+
if (status != napi_ok) return status;
697+
}
676698

677699
return GET_RETURN_STATUS();
678700
}
@@ -851,77 +873,80 @@ napi_status napi_get_element(napi_env e,
851873
return GET_RETURN_STATUS();
852874
}
853875

854-
napi_status napi_define_property(napi_env e, napi_value o,
855-
napi_property_descriptor* p) {
876+
napi_status napi_define_properties(napi_env e, napi_value o,
877+
int property_count, const napi_property_descriptor* properties) {
856878
NAPI_PREAMBLE(e);
857879

858880
v8::Isolate *isolate = v8impl::V8IsolateFromJsEnv(e);
859881
v8::Local<v8::Context> context = isolate->GetCurrentContext();
860-
v8::Local<v8::Object> obj;
861-
CHECK_TO_OBJECT(context, obj, o);
882+
v8::Local<v8::Object> obj = v8impl::V8LocalValueFromJsValue(o).As<v8::Object>();
862883

863-
v8::Local<v8::Name> name;
864-
CHECK_NEW_FROM_UTF8(isolate, name, p->utf8name);
884+
for (int i = 0; i < property_count; i++) {
885+
const napi_property_descriptor* p = &properties[i];
865886

866-
v8::PropertyAttribute attributes =
867-
static_cast<v8::PropertyAttribute>(p->attributes);
887+
v8::Local<v8::Name> name;
888+
CHECK_NEW_FROM_UTF8(isolate, name, p->utf8name);
868889

869-
if (p->method) {
870-
v8::Local<v8::Object> cbdata = v8impl::CreateFunctionCallbackData(
871-
e, p->method, p->data);
890+
v8::PropertyAttribute attributes =
891+
static_cast<v8::PropertyAttribute>(p->attributes & ~napi_static_property);
872892

873-
RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure);
893+
if (p->method) {
894+
v8::Local<v8::Object> cbdata = v8impl::CreateFunctionCallbackData(
895+
e, p->method, p->data);
874896

875-
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(
876-
isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
897+
RETURN_STATUS_IF_FALSE(!cbdata.IsEmpty(), napi_generic_failure);
877898

878-
auto define_maybe = obj->DefineOwnProperty(
879-
context,
880-
name,
881-
t->GetFunction(),
882-
attributes);
899+
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(
900+
isolate, v8impl::FunctionCallbackWrapper::Invoke, cbdata);
883901

884-
// IsNothing seems like a serious failure,
885-
// should we return a different error code if the define failed?
886-
if (define_maybe.IsNothing() || !define_maybe.FromMaybe(false))
887-
{
888-
return napi_set_last_error(napi_generic_failure);
902+
auto define_maybe = obj->DefineOwnProperty(
903+
context,
904+
name,
905+
t->GetFunction(),
906+
attributes);
907+
908+
// IsNothing seems like a serious failure,
909+
// should we return a different error code if the define failed?
910+
if (define_maybe.IsNothing() || !define_maybe.FromMaybe(false))
911+
{
912+
return napi_set_last_error(napi_generic_failure);
913+
}
889914
}
890-
}
891-
else if (p->getter || p->setter) {
892-
v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
893-
e, p->getter, p->setter, p->data);
894-
895-
auto set_maybe = obj->SetAccessor(
896-
context,
897-
name,
898-
v8impl::GetterCallbackWrapper::Invoke,
899-
p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
900-
cbdata,
901-
v8::AccessControl::DEFAULT,
902-
attributes);
903-
904-
// IsNothing seems like a serious failure,
905-
// should we return a different error code if the set failed?
906-
if (set_maybe.IsNothing() || !set_maybe.FromMaybe(false))
907-
{
908-
return napi_set_last_error(napi_generic_failure);
915+
else if (p->getter || p->setter) {
916+
v8::Local<v8::Object> cbdata = v8impl::CreateAccessorCallbackData(
917+
e, p->getter, p->setter, p->data);
918+
919+
auto set_maybe = obj->SetAccessor(
920+
context,
921+
name,
922+
v8impl::GetterCallbackWrapper::Invoke,
923+
p->setter ? v8impl::SetterCallbackWrapper::Invoke : nullptr,
924+
cbdata,
925+
v8::AccessControl::DEFAULT,
926+
attributes);
927+
928+
// IsNothing seems like a serious failure,
929+
// should we return a different error code if the set failed?
930+
if (set_maybe.IsNothing() || !set_maybe.FromMaybe(false))
931+
{
932+
return napi_set_last_error(napi_generic_failure);
933+
}
909934
}
910-
}
911-
else {
912-
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
913-
914-
auto define_maybe = obj->DefineOwnProperty(
915-
context,
916-
name,
917-
value,
918-
attributes);
919-
920-
// IsNothing seems like a serious failure,
921-
// should we return a different error code if the define failed?
922-
if (define_maybe.IsNothing() || !define_maybe.FromMaybe(false))
923-
{
924-
return napi_set_last_error(napi_generic_failure);
935+
else {
936+
v8::Local<v8::Value> value = v8impl::V8LocalValueFromJsValue(p->value);
937+
938+
auto define_maybe = obj->DefineOwnProperty(
939+
context,
940+
name,
941+
value,
942+
attributes);
943+
944+
// IsNothing seems like a serious failure,
945+
// should we return a different error code if the define failed?
946+
if (define_maybe.IsNothing() || !define_maybe.FromMaybe(false))
947+
{
948+
return napi_set_last_error(napi_generic_failure);
949+
}
925950
}
926951
}
927952

src/node_jsvmapi.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,10 @@ NODE_EXTERN napi_status napi_has_element(napi_env e, napi_value object,
185185
uint32_t i, bool* result);
186186
NODE_EXTERN napi_status napi_get_element(napi_env e, napi_value object,
187187
uint32_t i, napi_value* result);
188-
NODE_EXTERN napi_status napi_define_property(napi_env e, napi_value object,
189-
napi_property_descriptor* property);
188+
NODE_EXTERN napi_status napi_define_properties(napi_env e,
189+
napi_value object,
190+
int property_count,
191+
const napi_property_descriptor* properties);
190192

191193
// Methods to work with Arrays
192194
NODE_EXTERN napi_status napi_is_array(napi_env e, napi_value v, bool* result);
@@ -262,13 +264,13 @@ NODE_EXTERN napi_status napi_wrap(napi_env e, napi_value jsObject, void* nativeO
262264
napi_weakref* handle);
263265
NODE_EXTERN napi_status napi_unwrap(napi_env e, napi_value jsObject, void** result);
264266

265-
NODE_EXTERN napi_status napi_create_constructor(napi_env e,
266-
const char* utf8name,
267-
napi_callback cb,
268-
void* data,
269-
int property_count,
270-
napi_property_descriptor* properties,
271-
napi_value* result);
267+
NODE_EXTERN napi_status napi_define_class(napi_env e,
268+
const char* utf8name,
269+
napi_callback constructor,
270+
void* data,
271+
int property_count,
272+
const napi_property_descriptor* properties,
273+
napi_value* result);
272274

273275
// Methods to control object lifespan
274276
NODE_EXTERN napi_status napi_create_persistent(napi_env e, napi_value v,

src/node_jsvmapi_types.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ enum napi_property_attributes {
2121
napi_default = 0,
2222
napi_read_only = 1 << 0,
2323
napi_dont_enum = 1 << 1,
24-
napi_dont_delete = 1 << 2
24+
napi_dont_delete = 1 << 2,
25+
26+
// Used with napi_define_class to distinguish static properties
27+
// from instance properties. Ignored by napi_define_properties.
28+
napi_static_property = 1 << 10,
2529
};
2630

2731
struct napi_property_descriptor {

test/addons-abi/1_hello_world/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ void Method(napi_env env, napi_callback_info info) {
1212
void Init(napi_env env, napi_value exports, napi_value module) {
1313
napi_status status;
1414
napi_property_descriptor desc = { "hello", Method };
15-
status = napi_define_property(env, exports, &desc);
15+
status = napi_define_properties(env, exports, 1, &desc);
1616
if (status != napi_ok) return;
1717
}
1818

test/addons-abi/2_function_arguments/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ void Add(napi_env env, napi_callback_info info) {
4949
void Init(napi_env env, napi_value exports, napi_value module) {
5050
napi_status status;
5151
napi_property_descriptor addDescriptor = { "add", Add };
52-
status = napi_define_property(env, exports, &addDescriptor);
52+
status = napi_define_properties(env, exports, 1, &addDescriptor);
5353
if (status != napi_ok) return;
5454
}
5555

test/addons-abi/3_callbacks/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ void RunCallback(napi_env env, const napi_callback_info info) {
2424
void Init(napi_env env, napi_value exports, napi_value module) {
2525
napi_status status;
2626
napi_property_descriptor desc = { "exports", RunCallback };
27-
status = napi_define_property(env, module, &desc);
27+
status = napi_define_properties(env, module, 1, &desc);
2828
if (status != napi_ok) return;
2929
}
3030

test/addons-abi/4_object_factory/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ void CreateObject(napi_env env, const napi_callback_info info) {
2525
void Init(napi_env env, napi_value exports, napi_value module) {
2626
napi_status status;
2727
napi_property_descriptor desc = { "exports", CreateObject };
28-
status = napi_define_property(env, module, &desc);
28+
status = napi_define_properties(env, module, 1, &desc);
2929
if (status != napi_ok) return;
3030
}
3131

test/addons-abi/5_function_factory/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ void CreateFunction(napi_env env, napi_callback_info info) {
3333
void Init(napi_env env, napi_value exports, napi_value module) {
3434
napi_status status;
3535
napi_property_descriptor desc = { "exports", CreateFunction };
36-
status = napi_define_property(env, module, &desc);
36+
status = napi_define_properties(env, module, 1, &desc);
3737
if (status != napi_ok) return;
3838
}
3939

test/addons-abi/6_object_wrap/myobject.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ void MyObject::Init(napi_env env, napi_value exports) {
2121
};
2222

2323
napi_value cons;
24-
status = napi_create_constructor(env, "MyObject", New, nullptr, 3, properties, &cons);
24+
status = napi_define_class(env, "MyObject", New, nullptr, 3, properties, &cons);
2525
if (status != napi_ok) return;
2626

2727
status = napi_create_persistent(env, cons, &constructor);

test/addons-abi/7_factory_wrap/binding.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ void Init(napi_env env, napi_value exports, napi_value module) {
2222
if (status != napi_ok) return;
2323

2424
napi_property_descriptor desc = { "exports", CreateObject };
25-
status = napi_define_property(env, module, &desc);
25+
status = napi_define_properties(env, module, 1, &desc);
2626
if (status != napi_ok) return;
2727
}
2828

0 commit comments

Comments
 (0)