Skip to content

Commit

Permalink
objectwrap: add template methods
Browse files Browse the repository at this point in the history
ObjectWrap<T> was enhanced to support template methods for
defining properties and methods of JS class. Now C++ methods and
functions may be passed as template parameters for
ObjectWrap<T>::InstanceMethod, ObjectWrap<T>::StaticAccessor, etc.

There are several benefits:

  - no need to allocate extra memory for passing C++ function
    napi callback and use add_finalizer() to free memory;
  - a compiler can see whole chain of calls up to napi callback
    that may allow better optimisation.

Some examples:

```cpp
// Method
InstanceMethod<&MyClass::method>("method");

// Read-write property
InstanceAccessor<&MyClass::get, &MyClass::set>("rw_prop");

// Read-only property
InstanceAccessor<&MyClass::get>("ro_prop");
```

Fixes: #602
PR-URL: #604
Reviewed-By: Chengzhong Wu <[email protected]>
Reviewed-By: Chengzhong Wu <[email protected]>
  • Loading branch information
dmitryash authored and Gabriel Schulhof committed Dec 5, 2019
1 parent cfa71b6 commit ce91e14
Show file tree
Hide file tree
Showing 7 changed files with 694 additions and 11 deletions.
6 changes: 3 additions & 3 deletions doc/class_property_descriptor.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ class Example : public Napi::ObjectWrap<Example> {
Napi::Object Example::Init(Napi::Env env, Napi::Object exports) {
Napi::Function func = DefineClass(env, "Example", {
// Register a class instance accessor with getter and setter functions.
InstanceAccessor("value", &Example::GetValue, &Example::SetValue),
// We can also register a readonly accessor by passing nullptr as the setter.
InstanceAccessor("readOnlyProp", &Example::GetValue, nullptr)
InstanceAccessor<&Example::GetValue, &Example::SetValue>("value"),
// We can also register a readonly accessor by omitting the setter.
InstanceAccessor<&Example::GetValue>("readOnlyProp")
});

constructor = Napi::Persistent(func);
Expand Down
280 changes: 278 additions & 2 deletions doc/object_wrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ class Example : public Napi::ObjectWrap<Example> {
Napi::Object Example::Init(Napi::Env env, Napi::Object exports) {
// This method is used to hook the accessor and method callbacks
Napi::Function func = DefineClass(env, "Example", {
InstanceMethod("GetValue", &Example::GetValue),
InstanceMethod("SetValue", &Example::SetValue)
InstanceMethod<&Example::GetValue>("GetValue"),
InstanceMethod<&Example::SetValue>("SetValue")
});

// Create a peristent reference to the class constructor. This will allow
Expand Down Expand Up @@ -289,6 +289,93 @@ One or more of `napi_property_attributes`.
Returns `Napi::PropertyDescriptor` object that represents a static method of a
JavaScript class.
### StaticMethod
Creates property descriptor that represents a static method of a JavaScript class.
```cpp
template <StaticVoidMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticMethod(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] method`: The native function that represents a static method of a
JavaScript class. This function returns nothing.
- `[in] utf8name`: Null-terminated string that represents the name of a static
method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.

Returns `Napi::PropertyDescriptor` object that represents the static method of a
JavaScript class.

### StaticMethod

Creates property descriptor that represents a static method of a JavaScript class.

```cpp
template <StaticMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticMethod(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] method`: The native function that represents a static method of a
JavaScript class.
- `[in] utf8name`: Null-terminated string that represents the name of a static
method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.
Returns `Napi::PropertyDescriptor` object that represents a static method of a
JavaScript class.
### StaticMethod
Creates property descriptor that represents a static method of a JavaScript class.
```cpp
template <StaticVoidMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticMethod(Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] method`: The native function that represents a static method of a
JavaScript class.
- `[in] name`: Napi:Symbol that represents the name of a static
method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.

Returns `Napi::PropertyDescriptor` object that represents the static method of a
JavaScript class.

### StaticMethod

Creates property descriptor that represents a static method of a JavaScript class.

```cpp
template <StaticMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticMethod(Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] method`: The native function that represents a static method of a
JavaScript class.
- `[in] name`: Napi:Symbol that represents the name of a static.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.
Returns `Napi::PropertyDescriptor` object that represents a static method of a
JavaScript class.
### StaticAccessor
Creates property descriptor that represents a static accessor property of a
Expand Down Expand Up @@ -342,6 +429,57 @@ is invoked.
Returns `Napi::PropertyDescriptor` object that represents a static accessor
property of a JavaScript class.
### StaticAccessor
Creates property descriptor that represents a static accessor property of a
JavaScript class.
```cpp
template <StaticGetterCallback getter, StaticSetterCallback setter=nullptr>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticAccessor(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] getter`: The native function to call when a get access to the property of
a JavaScript class is performed.
- `[in] setter`: The native function to call when a set access to the property of
a JavaScript class is performed.
- `[in] utf8name`: Null-terminated string that represents the name of a static
accessor property for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into getter or setter when
is invoked.

Returns `Napi::PropertyDescriptor` object that represents a static accessor
property of a JavaScript class.

### StaticAccessor

Creates property descriptor that represents a static accessor property of a
JavaScript class.

```cpp
template <StaticGetterCallback getter, StaticSetterCallback setter=nullptr>
static Napi::PropertyDescriptor Napi::ObjectWrap::StaticAccessor(Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] getter`: The native function to call when a get access to the property of
a JavaScript class is performed.
- `[in] setter`: The native function to call when a set access to the property of
a JavaScript class is performed.
- `[in] name`: Napi:Symbol that represents the name of a static accessor.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into getter or setter when
is invoked.
Returns `Napi::PropertyDescriptor` object that represents a static accessor
property of a JavaScript class.
### InstanceMethod
Creates property descriptor that represents an instance method of a JavaScript class.
Expand Down Expand Up @@ -430,6 +568,94 @@ One or more of `napi_property_attributes`.
Returns `Napi::PropertyDescriptor` object that represents an instance method of a
JavaScript class.
### InstanceMethod
Creates property descriptor that represents an instance method of a JavaScript class.
```cpp
template <InstanceVoidMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceMethod(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] method`: The native function that represents an instance method of a
JavaScript class.
- `[in] utf8name`: Null-terminated string that represents the name of an instance
method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.

Returns `Napi::PropertyDescriptor` object that represents an instance method of a
JavaScript class.

### InstanceMethod

Creates property descriptor that represents an instance method of a JavaScript class.

```cpp
template <InstanceMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceMethod(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] method`: The native function that represents an instance method of a
JavaScript class.
- `[in] utf8name`: Null-terminated string that represents the name of an instance
method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.
Returns `Napi::PropertyDescriptor` object that represents an instance method of a
JavaScript class.
### InstanceMethod
Creates property descriptor that represents an instance method of a JavaScript class.
```cpp
template <InstanceVoidMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceMethod(Napi::Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] method`: The native function that represents an instance method of a
JavaScript class.
- `[in] name`: The `Napi::Symbol` object whose value is used to identify the
instance method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.

Returns `Napi::PropertyDescriptor` object that represents an instance method of a
JavaScript class.

### InstanceMethod

Creates property descriptor that represents an instance method of a JavaScript class.

```cpp
template <InstanceMethodCallback method>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceMethod(Napi::Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] method`: The native function that represents an instance method of a
JavaScript class.
- `[in] name`: The `Napi::Symbol` object whose value is used to identify the
instance method for the class.
- `[in] attributes`: The attributes associated with a particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into method when it is invoked.
Returns `Napi::PropertyDescriptor` object that represents an instance method of a
JavaScript class.
### InstanceAccessor
Creates property descriptor that represents an instance accessor property of a
Expand Down Expand Up @@ -482,6 +708,56 @@ One or more of `napi_property_attributes`.
Returns `Napi::PropertyDescriptor` object that represents an instance accessor
property of a JavaScript class.
### InstanceAccessor
Creates property descriptor that represents an instance accessor property of a
JavaScript class.
```cpp
template <InstanceGetterCallback getter, InstanceSetterCallback setter=nullptr>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceAccessor(const char* utf8name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```

- `[in] getter`: The native function to call when a get access to the property of
a JavaScript class is performed.
- `[in] setter`: The native function to call when a set access to the property of
a JavaScript class is performed.
- `[in] utf8name`: Null-terminated string that represents the name of an instance
accessor property for the class.
- `[in] attributes`: The attributes associated with the particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into getter or setter when this is invoked.

Returns `Napi::PropertyDescriptor` object that represents an instance accessor
property of a JavaScript class.

### InstanceAccessor

Creates property descriptor that represents an instance accessor property of a
JavaScript class.

```cpp
template <InstanceGetterCallback getter, InstanceSetterCallback setter=nullptr>
static Napi::PropertyDescriptor Napi::ObjectWrap::InstanceAccessor(Symbol name,
napi_property_attributes attributes = napi_default,
void* data = nullptr);
```
- `[in] getter`: The native function to call when a get access to the property of
a JavaScript class is performed.
- `[in] setter`: The native function to call when a set access to the property of
a JavaScript class is performed.
- `[in] name`: The `Napi::Symbol` object whose value is used to identify the
instance accessor.
- `[in] attributes`: The attributes associated with the particular property.
One or more of `napi_property_attributes`.
- `[in] data`: User-provided data passed into getter or setter when this is invoked.
Returns `Napi::PropertyDescriptor` object that represents an instance accessor
property of a JavaScript class.
### StaticValue
Creates property descriptor that represents an static value property of a
Expand Down
Loading

2 comments on commit ce91e14

@legendecas
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gabrielschulhof There is a duplicated Reviewed-By field in the commit message 😄

@gabrielschulhof
Copy link
Contributor

@gabrielschulhof gabrielschulhof commented on ce91e14 Dec 6, 2019 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.