1# Add-on Structure
2
3Class `Napi::Addon<T>` inherits from class [`Napi::InstanceWrap<T>`][].
4
5Creating add-ons that work correctly when loaded multiple times from the same
6source package into multiple Node.js threads and/or multiple times into the same
7Node.js thread requires that all global data they hold be associated with the
8environment in which they run. It is not safe to store global data in static
9variables because doing so does not take into account the fact that an add-on
10may be loaded into multiple threads nor that an add-on may be loaded multiple
11times into a single thread.
12
13The `Napi::Addon<T>` class can be used to define an entire add-on. Instances of
14`Napi::Addon<T>` subclasses become instances of the add-on, stored safely by
15Node.js on its various threads and into its various contexts. Thus, any data
16stored in the instance variables of a `Napi::Addon<T>` subclass instance are
17stored safely by Node.js. Functions exposed to JavaScript using
18`Napi::Addon<T>::InstanceMethod` and/or `Napi::Addon<T>::DefineAddon` are
19instance methods of the `Napi::Addon` subclass and thus have access to data
20stored inside the instance.
21
22`Napi::Addon<T>::DefineProperties` may be used to attach `Napi::Addon<T>`
23subclass instance methods to objects other than the one that will be returned to
24Node.js as the add-on instance.
25
26The `Napi::Addon<T>` class can be used together with the `NODE_API_ADDON()` and
27`NODE_API_NAMED_ADDON()` macros to define add-ons.
28
29## Example
30
31```cpp
32#include <napi.h>
33
34class ExampleAddon : public Napi::Addon<ExampleAddon> {
35 public:
36  ExampleAddon(Napi::Env env, Napi::Object exports) {
37    // In the constructor we declare the functions the add-on makes available
38    // to JavaScript.
39    DefineAddon(exports, {
40      InstanceMethod("increment", &ExampleAddon::Increment),
41
42      // We can also attach plain objects to `exports`, and instance methods as
43      // properties of those sub-objects.
44      InstanceValue("subObject", DefineProperties(Napi::Object::New(env), {
45        InstanceMethod("decrement", &ExampleAddon::Decrement)
46      }), napi_enumerable)
47    });
48  }
49 private:
50
51  // This method has access to the data stored in the environment because it is
52  // an instance method of `ExampleAddon` and because it was listed among the
53  // property descriptors passed to `DefineAddon()` in the constructor.
54  Napi::Value Increment(const Napi::CallbackInfo& info) {
55    return Napi::Number::New(info.Env(), ++value);
56  }
57
58  // This method has access to the data stored in the environment because it is
59  // an instance method of `ExampleAddon` and because it was exposed to
60  // JavaScript by calling `DefineProperties()` with the object onto which it is
61  // attached.
62  Napi::Value Decrement(const Napi::CallbackInfo& info) {
63    return Napi::Number::New(info.Env(), --value);
64  }
65
66  // Data stored in these variables is unique to each instance of the add-on.
67  uint32_t value = 42;
68};
69
70// The macro announces that instances of the class `ExampleAddon` will be
71// created for each instance of the add-on that must be loaded into Node.js.
72NODE_API_ADDON(ExampleAddon)
73```
74
75The above code can be used from JavaScript as follows:
76
77```js
78'use strict'
79
80const exampleAddon = require('bindings')('example_addon');
81console.log(exampleAddon.increment()); // prints 43
82console.log(exampleAddon.increment()); // prints 44
83console.log(exampleAddon.subObject.decrement()); // prints 43
84```
85
86When Node.js loads an instance of the add-on, a new instance of the class is
87created. Its constructor receives the environment `Napi::Env env` and the
88exports object `Napi::Object exports`. It can then use the method `DefineAddon`
89to either attach methods, accessors, and/or values to the `exports` object or to
90create its own `exports` object and attach methods, accessors, and/or values to
91it.
92
93**Note:** `Napi::Addon<T>` uses `Napi::Env::SetInstanceData()` internally. This
94means that the add-on should only use `Napi::Env::GetInstanceData` explicitly to
95retrieve the instance of the `Napi::Addon<T>` class. Variables whose scope would
96otherwise be global should be stored as instance variables in the
97`Napi::Addon<T>` class.
98
99Functions created with `Napi::Function::New()`, accessors created with
100`PropertyDescriptor::Accessor()`, and values can also be attached. If their
101implementation requires the `ExampleAddon` instance, it can be retrieved from
102the `Napi::Env env` with `GetInstanceData()`:
103
104```cpp
105void ExampleBinding(const Napi::CallbackInfo& info) {
106  ExampleAddon* addon = info.Env().GetInstanceData<ExampleAddon>();
107}
108```
109
110## Methods
111
112### Constructor
113
114Creates a new instance of the add-on.
115
116```cpp
117Napi::Addon(Napi::Env env, Napi::Object exports);
118```
119
120- `[in] env`: The environment into which the add-on is being loaded.
121- `[in] exports`: The exports object received from JavaScript.
122
123Typically, the constructor calls `DefineAddon()` to attach methods, accessors,
124and/or values to `exports`. The constructor may also create a new object and
125pass it to `DefineAddon()` as its first parameter if it wishes to replace the
126`exports` object as provided by Node.js.
127
128### DefineAddon
129
130Defines an add-on instance with functions, accessors, and/or values.
131
132```cpp
133template <typename T>
134void Napi::Addon<T>::DefineAddon(Napi::Object exports,
135                   const std::initializer_list<PropertyDescriptor>& properties);
136```
137
138* `[in] exports`: The object to return to Node.js as an instance of the add-on.
139* `[in] properties`: Initializer list of add-on property descriptors of the
140methods, property accessors, and values that define the add-on. They will be
141set on `exports`.
142See: [`Class property and descriptor`](class_property_descriptor.md).
143
144### DefineProperties
145
146Defines function, accessor, and/or value properties on an object using add-on
147instance methods.
148
149```cpp
150template <typename T>
151Napi::Object
152Napi::Addon<T>::DefineProperties(Napi::Object object,
153                   const std::initializer_list<PropertyDescriptor>& properties);
154```
155
156* `[in] object`: The object that will receive the new properties.
157* `[in] properties`: Initializer list of property descriptors of the methods,
158property accessors, and values to attach to `object`.
159See: [`Class property and descriptor`](class_property_descriptor.md).
160
161Returns `object`.
162
163[`Napi::InstanceWrap<T>`]: ./instance_wrap.md
164