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