1# Class property and descriptor
2
3Property descriptor for use with `Napi::ObjectWrap<T>` and 
4`Napi::InstanceWrap<T>`. This is different from the standalone
5`Napi::PropertyDescriptor` because it is specific to each 
6`Napi::ObjectWrap<T>` and `Napi::InstanceWrap<T>` subclasses.
7This prevents using descriptors from a different class when defining a new
8class (preventing the callbacks from having incorrect `this` pointers).
9
10`Napi::ClassPropertyDescriptor` is a helper class created with
11`Napi::ObjectWrap<T>` and `Napi::InstanceWrap<T>`. For more reference about it
12see:
13
14- [InstanceWrap](./instance_wrap.md)
15- [ObjectWrap](./object_wrap.md)
16
17## Example
18
19```cpp
20#include <napi.h>
21
22class Example : public Napi::ObjectWrap<Example> {
23  public:
24    static Napi::Object Init(Napi::Env env, Napi::Object exports);
25    Example(const Napi::CallbackInfo &info);
26
27  private:
28    double _value;
29    Napi::Value GetValue(const Napi::CallbackInfo &info);
30    void SetValue(const Napi::CallbackInfo &info, const Napi::Value &value);
31};
32
33Napi::Object Example::Init(Napi::Env env, Napi::Object exports) {
34    Napi::Function func = DefineClass(env, "Example", {
35        // Register a class instance accessor with getter and setter functions.
36        InstanceAccessor<&Example::GetValue, &Example::SetValue>("value"),
37        // We can also register a readonly accessor by omitting the setter.
38        InstanceAccessor<&Example::GetValue>("readOnlyProp")
39    });
40
41    Napi::FunctionReference *constructor = new Napi::FunctionReference();
42    *constructor = Napi::Persistent(func);
43    env.SetInstanceData(constructor);
44    exports.Set("Example", func);
45
46    return exports;
47}
48
49Example::Example(const Napi::CallbackInfo &info) : Napi::ObjectWrap<Example>(info) {
50    Napi::Env env = info.Env();
51    // ...
52    Napi::Number value = info[0].As<Napi::Number>();
53    this->_value = value.DoubleValue();
54}
55
56Napi::Value Example::GetValue(const Napi::CallbackInfo &info) {
57    Napi::Env env = info.Env();
58    return Napi::Number::New(env, this->_value);
59}
60
61void Example::SetValue(const Napi::CallbackInfo &info, const Napi::Value &value) {
62    Napi::Env env = info.Env();
63    // ...
64    Napi::Number arg = value.As<Napi::Number>();
65    this->_value = arg.DoubleValue();
66}
67
68// Initialize native add-on
69Napi::Object Init (Napi::Env env, Napi::Object exports) {
70    Example::Init(env, exports);
71    return exports;
72}
73
74// Register and initialize native add-on
75NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init)
76```
77
78The above code can be used from JavaScript as follows:
79
80```js
81'use strict';
82
83const { Example } = require('bindings')('addon');
84
85const example = new Example(11);
86console.log(example.value);
87// It prints 11
88example.value = 19;
89console.log(example.value);
90// It prints 19
91example.readOnlyProp = 500;
92console.log(example.readOnlyProp);
93// Unchanged. It prints 19
94```
95
96## Methods
97
98### Constructor
99
100Creates new instance of `Napi::ClassPropertyDescriptor` descriptor object.
101
102```cpp
103Napi::ClassPropertyDescriptor(napi_property_descriptor desc) : _desc(desc) {}
104```
105
106- `[in] desc`: The `napi_property_descriptor`
107
108Returns new instance of `Napi::ClassPropertyDescriptor` that is used as property descriptor
109inside the `Napi::ObjectWrap<T>` class.
110
111### Operator
112
113```cpp
114operator napi_property_descriptor&() { return _desc; }
115```
116
117Returns the original Node-API `napi_property_descriptor` wrapped inside the `Napi::ClassPropertyDescriptor`
118
119```cpp
120operator const napi_property_descriptor&() const { return _desc; }
121```
122
123Returns the original Node-API `napi_property_descriptor` wrapped inside the `Napi::ClassPropertyDescriptor`
124