Skip to content

Commit

Permalink
doc: ClassPropertyDescriptor example
Browse files Browse the repository at this point in the history
PR-URL: #507
Reviewed-By: Nicola Del Gobbo <nicoladelgobbo@gmail.com>
Reviewed-By: Gabriel Schulhof <gabriel.schulhof@intel.com>
Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
  • Loading branch information
ross-weir authored and Gabriel Schulhof committed Jul 10, 2019
1 parent c32d7db commit cab3b1e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 2 deletions.
84 changes: 83 additions & 1 deletion doc/class_property_descriptor.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,93 @@
# Class propertry and descriptor
# Class property and descriptor

Property descriptor for use with `Napi::ObjectWrap::DefineClass()`.
This is different from the standalone `Napi::PropertyDescriptor` because it is
specific to each `Napi::ObjectWrap<T>` subclass.
This prevents using descriptors from a different class when defining a new class
(preventing the callbacks from having incorrect `this` pointers).

## Example

```cpp
#include <napi.h>

class Example : public Napi::ObjectWrap<Example> {
public:
static Napi::Object Init(Napi::Env env, Napi::Object exports);
Example(const Napi::CallbackInfo &info);

private:
static Napi::FunctionReference constructor;
double _value;
Napi::Value GetValue(const Napi::CallbackInfo &info);
Napi::Value SetValue(const Napi::CallbackInfo &info);
};

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)
});

constructor = Napi::Persistent(func);
constructor.SuppressDestruct();
exports.Set("Example", func);

return exports;
}

Example::Example(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Example>(info) {
Napi::Env env = info.Env();
// ...
Napi::Number value = info[0].As<Napi::Number>();
this->_value = value.DoubleValue();
}

Napi::FunctionReference Example::constructor;

Napi::Value Example::GetValue(const Napi::CallbackInfo &info) {
Napi::Env env = info.Env();
return Napi::Number::New(env, this->_value);
}

Napi::Value Example::SetValue(const Napi::CallbackInfo &info, const Napi::Value &value) {
Napi::Env env = info.Env();
// ...
Napi::Number arg = value.As<Napi::Number>();
this->_value = arg.DoubleValue();
return this->GetValue(info);
}

// Initialize native add-on
Napi::Object Init (Napi::Env env, Napi::Object exports) {
Example::Init(env, exports);
return exports;
}

// Register and initialize native add-on
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
```
The above code can be used from JavaScript as follows:
```js
'use strict';
const { Example } = require('bindings')('addon');
const example = new Example(11);
console.log(example.value);
// It prints 11
example.value = 19;
console.log(example.value);
// It prints 19
example.readOnlyProp = 500;
console.log(example.readOnlyProp);
// Unchanged. It prints 19
```

## Methods

### Constructor
Expand Down
2 changes: 1 addition & 1 deletion doc/object_wrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Napi::Object Init (Napi::Env env, Napi::Object exports) {
return exports;
}

// Regisgter and initialize native add-on
// Register and initialize native add-on
NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
```
Expand Down

0 comments on commit cab3b1e

Please sign in to comment.