Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

objectwrap: implement missing descriptor definitions for symbols #280

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions napi-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -2739,6 +2739,40 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
Symbol name,
StaticVoidMethodCallback method,
napi_property_attributes attributes,
void* data) {
// TODO: Delete when the class is destroyed
StaticVoidMethodCallbackData* callbackData = new StaticVoidMethodCallbackData({ method, data });

napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.method = T::StaticVoidMethodCallbackWrapper;
desc.data = callbackData;
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticMethod(
Symbol name,
StaticMethodCallback method,
napi_property_attributes attributes,
void* data) {
// TODO: Delete when the class is destroyed
StaticMethodCallbackData* callbackData = new StaticMethodCallbackData({ method, data });

napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.method = T::StaticMethodCallbackWrapper;
desc.data = callbackData;
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
const char* utf8name,
Expand All @@ -2759,6 +2793,26 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticAccessor(
Symbol name,
StaticGetterCallback getter,
StaticSetterCallback setter,
napi_property_attributes attributes,
void* data) {
// TODO: Delete when the class is destroyed
StaticAccessorCallbackData* callbackData =
new StaticAccessorCallbackData({ getter, setter, data });

napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.getter = getter != nullptr ? T::StaticGetterCallbackWrapper : nullptr;
desc.setter = setter != nullptr ? T::StaticSetterCallbackWrapper : nullptr;
desc.data = callbackData;
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceMethod(
const char* utf8name,
Expand Down Expand Up @@ -2849,6 +2903,26 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceAccessor(
Symbol name,
InstanceGetterCallback getter,
InstanceSetterCallback setter,
napi_property_attributes attributes,
void* data) {
// TODO: Delete when the class is destroyed
InstanceAccessorCallbackData* callbackData =
new InstanceAccessorCallbackData({ getter, setter, data });

napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.getter = getter != nullptr ? T::InstanceGetterCallbackWrapper : nullptr;
desc.setter = setter != nullptr ? T::InstanceSetterCallbackWrapper : nullptr;
desc.data = callbackData;
desc.attributes = attributes;
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8name,
Napi::Value value, napi_property_attributes attributes) {
Expand All @@ -2859,6 +2933,16 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(const char* utf8nam
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::StaticValue(Symbol name,
Napi::Value value, napi_property_attributes attributes) {
napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.value = value;
desc.attributes = static_cast<napi_property_attributes>(attributes | napi_static);
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
const char* utf8name,
Expand All @@ -2871,6 +2955,18 @@ inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
return desc;
}

template <typename T>
inline ClassPropertyDescriptor<T> ObjectWrap<T>::InstanceValue(
Symbol name,
Napi::Value value,
napi_property_attributes attributes) {
napi_property_descriptor desc = napi_property_descriptor();
desc.name = name;
desc.value = value;
desc.attributes = attributes;
return desc;
}

template <typename T>
inline napi_value ObjectWrap<T>::ConstructorCallbackWrapper(
napi_env env,
Expand Down
24 changes: 24 additions & 0 deletions napi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1395,11 +1395,24 @@ namespace Napi {
StaticMethodCallback method,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor StaticMethod(Symbol name,
StaticVoidMethodCallback method,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor StaticMethod(Symbol name,
StaticMethodCallback method,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor StaticAccessor(const char* utf8name,
StaticGetterCallback getter,
StaticSetterCallback setter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor StaticAccessor(Symbol name,
StaticGetterCallback getter,
StaticSetterCallback setter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor InstanceMethod(const char* utf8name,
InstanceVoidMethodCallback method,
napi_property_attributes attributes = napi_default,
Expand All @@ -1421,12 +1434,23 @@ namespace Napi {
InstanceSetterCallback setter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor InstanceAccessor(Symbol name,
InstanceGetterCallback getter,
InstanceSetterCallback setter,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
static PropertyDescriptor StaticValue(const char* utf8name,
Napi::Value value,
napi_property_attributes attributes = napi_default);
static PropertyDescriptor StaticValue(Symbol name,
Napi::Value value,
napi_property_attributes attributes = napi_default);
static PropertyDescriptor InstanceValue(const char* utf8name,
Napi::Value value,
napi_property_attributes attributes = napi_default);
static PropertyDescriptor InstanceValue(Symbol name,
Napi::Value value,
napi_property_attributes attributes = napi_default);

private:
static napi_value ConstructorCallbackWrapper(napi_env env, napi_callback_info info);
Expand Down
120 changes: 86 additions & 34 deletions test/objectwrap.cc
Original file line number Diff line number Diff line change
@@ -1,66 +1,118 @@
#include <napi.h>

class TestIter : public Napi::ObjectWrap<TestIter> {
public:
TestIter(const Napi::CallbackInfo& info) : Napi::ObjectWrap<TestIter>(info) {}
Napi::ObjectReference testStaticContextRef;

Napi::Value Next(const Napi::CallbackInfo& info) {
auto object = Napi::Object::New(info.Env());
object.Set("done", Napi::Boolean::New(info.Env(), true));
return object;
}
Napi::Value StaticGetter(const Napi::CallbackInfo& info) {
return testStaticContextRef.Value().Get("value");
}

static Napi::FunctionReference Initialize(Napi::Env env) {
return Napi::Persistent(DefineClass(env, "TestIter", {
InstanceMethod("next", &TestIter::Next),
}));
}
};
void StaticSetter(const Napi::CallbackInfo& info, const Napi::Value& value) {
testStaticContextRef.Value().Set("value", value);
}

Napi::Value TestStaticMethod(const Napi::CallbackInfo& info) {
std::string str = info[0].ToString();
return Napi::String::New(info.Env(), str + " static");
}

Napi::Value TestStaticMethodInternal(const Napi::CallbackInfo& info) {
std::string str = info[0].ToString();
return Napi::String::New(info.Env(), str + " static internal");
}

class Test : public Napi::ObjectWrap<Test> {
public:
Test(const Napi::CallbackInfo& info) :
Napi::ObjectWrap<Test>(info),
Constructor(TestIter::Initialize(info.Env())) {
Napi::ObjectWrap<Test>(info) {
}

void SetMethod(const Napi::CallbackInfo& info) {
value = info[0].As<Napi::Number>();
void Setter(const Napi::CallbackInfo& info, const Napi::Value& value) {
value_ = value.ToString();
}

Napi::Value GetMethod(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), value);
Napi::Value Getter(const Napi::CallbackInfo& info) {
return Napi::String::New(info.Env(), value_);
}

Napi::Value Iter(const Napi::CallbackInfo& info) {
return Constructor.New({});
Napi::Value TestMethod(const Napi::CallbackInfo& info) {
std::string str = info[0].ToString();
return Napi::String::New(info.Env(), str + " instance");
}

void Setter(const Napi::CallbackInfo& info, const Napi::Value& new_value) {
value = new_value.As<Napi::Number>();
Napi::Value TestMethodInternal(const Napi::CallbackInfo& info) {
std::string str = info[0].ToString();
return Napi::String::New(info.Env(), str + " instance internal");
}

Napi::Value Getter(const Napi::CallbackInfo& info) {
return Napi::Number::New(info.Env(), value);
Napi::Value ToStringTag(const Napi::CallbackInfo& info) {
return Napi::String::From(info.Env(), "TestTag");
}

// creates dummy array, returns `([value])[Symbol.iterator]()`
Napi::Value Iterator(const Napi::CallbackInfo& info) {
Napi::Array array = Napi::Array::New(info.Env());
array.Set(array.Length(), Napi::String::From(info.Env(), value_));
return array.Get(Napi::Symbol::WellKnown(info.Env(), "iterator")).As<Napi::Function>().Call(array, {});
}

static void Initialize(Napi::Env env, Napi::Object exports) {

Napi::Symbol kTestStaticValueInternal = Napi::Symbol::New(env, "kTestStaticValueInternal");
Napi::Symbol kTestStaticAccessorInternal = Napi::Symbol::New(env, "kTestStaticAccessorInternal");
Napi::Symbol kTestStaticMethodInternal = Napi::Symbol::New(env, "kTestStaticMethodInternal");

Napi::Symbol kTestValueInternal = Napi::Symbol::New(env, "kTestValueInternal");
Napi::Symbol kTestAccessorInternal = Napi::Symbol::New(env, "kTestAccessorInternal");
Napi::Symbol kTestMethodInternal = Napi::Symbol::New(env, "kTestMethodInternal");

exports.Set("Test", DefineClass(env, "Test", {
InstanceMethod("test_set_method", &Test::SetMethod),
InstanceMethod("test_get_method", &Test::GetMethod),
InstanceMethod(Napi::Symbol::WellKnown(env, "iterator"), &Test::Iter),
InstanceAccessor("test_getter_only", &Test::Getter, nullptr),
InstanceAccessor("test_setter_only", nullptr, &Test::Setter),
InstanceAccessor("test_getter_setter", &Test::Getter, &Test::Setter),

// expose symbols for testing
StaticValue("kTestStaticValueInternal", kTestStaticValueInternal),
StaticValue("kTestStaticAccessorInternal", kTestStaticAccessorInternal),
StaticValue("kTestStaticMethodInternal", kTestStaticMethodInternal),
StaticValue("kTestValueInternal", kTestValueInternal),
StaticValue("kTestAccessorInternal", kTestAccessorInternal),
StaticValue("kTestMethodInternal", kTestMethodInternal),

// test data
StaticValue("testStaticValue", Napi::String::New(env, "value"), napi_enumerable),
StaticValue(kTestStaticValueInternal, Napi::Number::New(env, 5), napi_default),

StaticAccessor("testStaticGetter", &StaticGetter, nullptr, napi_enumerable),
StaticAccessor("testStaticSetter", nullptr, &StaticSetter, napi_default),
StaticAccessor("testStaticGetSet", &StaticGetter, &StaticSetter, napi_enumerable),
StaticAccessor(kTestStaticAccessorInternal, &StaticGetter, &StaticSetter, napi_enumerable),

StaticMethod("testStaticMethod", &TestStaticMethod, napi_enumerable),
StaticMethod(kTestStaticMethodInternal, &TestStaticMethodInternal, napi_default),

InstanceValue("testValue", Napi::Boolean::New(env, true), napi_enumerable),
InstanceValue(kTestValueInternal, Napi::Boolean::New(env, false), napi_enumerable),

InstanceAccessor("testGetter", &Test::Getter, nullptr, napi_enumerable),
InstanceAccessor("testSetter", nullptr, &Test::Setter, napi_default),
InstanceAccessor("testGetSet", &Test::Getter, &Test::Setter, napi_enumerable),
InstanceAccessor(kTestAccessorInternal, &Test::Getter, &Test::Setter, napi_enumerable),

InstanceMethod("testMethod", &Test::TestMethod, napi_enumerable),
InstanceMethod(kTestMethodInternal, &Test::TestMethodInternal, napi_default),

// conventions
InstanceAccessor(Napi::Symbol::WellKnown(env, "toStringTag"), &Test::ToStringTag, nullptr, napi_enumerable),
InstanceMethod(Napi::Symbol::WellKnown(env, "iterator"), &Test::Iterator, napi_default),

}));
}

private:
uint32_t value;
Napi::FunctionReference Constructor;
std::string value_;
};

Napi::Object InitObjectWrap(Napi::Env env) {
testStaticContextRef = Napi::Persistent(Napi::Object::New(env));
testStaticContextRef.SuppressDestruct();

Napi::Object exports = Napi::Object::New(env);
Test::Initialize(env, exports);
return exports;
Expand Down
Loading