| # Add-on Structure |
| |
| Class `Napi::Addon<T>` inherits from class [`Napi::InstanceWrap<T>`][]. |
| |
| Creating add-ons that work correctly when loaded multiple times from the same |
| source package into multiple Node.js threads and/or multiple times into the same |
| Node.js thread requires that all global data they hold be associated with the |
| environment in which they run. It is not safe to store global data in static |
| variables because doing so does not take into account the fact that an add-on |
| may be loaded into multiple threads nor that an add-on may be loaded multiple |
| times into a single thread. |
| |
| The `Napi::Addon<T>` class can be used to define an entire add-on. Instances of |
| `Napi::Addon<T>` subclasses become instances of the add-on, stored safely by |
| Node.js on its various threads and into its various contexts. Thus, any data |
| stored in the instance variables of a `Napi::Addon<T>` subclass instance are |
| stored safely by Node.js. Functions exposed to JavaScript using |
| `Napi::Addon<T>::InstanceMethod` and/or `Napi::Addon<T>::DefineAddon` are |
| instance methods of the `Napi::Addon` subclass and thus have access to data |
| stored inside the instance. |
| |
| `Napi::Addon<T>::DefineProperties` may be used to attach `Napi::Addon<T>` |
| subclass instance methods to objects other than the one that will be returned to |
| Node.js as the add-on instance. |
| |
| The `Napi::Addon<T>` class can be used together with the `NODE_API_ADDON()` and |
| `NODE_API_NAMED_ADDON()` macros to define add-ons. |
| |
| ## Example |
| |
| ```cpp |
| #include <napi.h> |
| |
| class ExampleAddon : public Napi::Addon<ExampleAddon> { |
| public: |
| ExampleAddon(Napi::Env env, Napi::Object exports) { |
| // In the constructor we declare the functions the add-on makes available |
| // to JavaScript. |
| DefineAddon(exports, { |
| InstanceMethod("increment", &ExampleAddon::Increment), |
| |
| // We can also attach plain objects to `exports`, and instance methods as |
| // properties of those sub-objects. |
| InstanceValue("subObject", DefineProperties(Napi::Object::New(env), { |
| InstanceMethod("decrement", &ExampleAddon::Decrement) |
| }), napi_enumerable) |
| }); |
| } |
| private: |
| |
| // This method has access to the data stored in the environment because it is |
| // an instance method of `ExampleAddon` and because it was listed among the |
| // property descriptors passed to `DefineAddon()` in the constructor. |
| Napi::Value Increment(const Napi::CallbackInfo& info) { |
| return Napi::Number::New(info.Env(), ++value); |
| } |
| |
| // This method has access to the data stored in the environment because it is |
| // an instance method of `ExampleAddon` and because it was exposed to |
| // JavaScript by calling `DefineProperties()` with the object onto which it is |
| // attached. |
| Napi::Value Decrement(const Napi::CallbackInfo& info) { |
| return Napi::Number::New(info.Env(), --value); |
| } |
| |
| // Data stored in these variables is unique to each instance of the add-on. |
| uint32_t value = 42; |
| }; |
| |
| // The macro announces that instances of the class `ExampleAddon` will be |
| // created for each instance of the add-on that must be loaded into Node.js. |
| NODE_API_ADDON(ExampleAddon) |
| ``` |
| |
| The above code can be used from JavaScript as follows: |
| |
| ```js |
| 'use strict' |
| |
| const exampleAddon = require('bindings')('example_addon'); |
| console.log(exampleAddon.increment()); // prints 43 |
| console.log(exampleAddon.increment()); // prints 44 |
| console.log(exampleAddon.subObject.decrement()); // prints 43 |
| ``` |
| |
| When Node.js loads an instance of the add-on, a new instance of the class is |
| created. Its constructor receives the environment `Napi::Env env` and the |
| exports object `Napi::Object exports`. It can then use the method `DefineAddon` |
| to either attach methods, accessors, and/or values to the `exports` object or to |
| create its own `exports` object and attach methods, accessors, and/or values to |
| it. |
| |
| **Note:** `Napi::Addon<T>` uses `Napi::Env::SetInstanceData()` internally. This |
| means that the add-on should only use `Napi::Env::GetInstanceData` explicitly to |
| retrieve the instance of the `Napi::Addon<T>` class. Variables whose scope would |
| otherwise be global should be stored as instance variables in the |
| `Napi::Addon<T>` class. |
| |
| Functions created with `Napi::Function::New()`, accessors created with |
| `PropertyDescriptor::Accessor()`, and values can also be attached. If their |
| implementation requires the `ExampleAddon` instance, it can be retrieved from |
| the `Napi::Env env` with `GetInstanceData()`: |
| |
| ```cpp |
| void ExampleBinding(const Napi::CallbackInfo& info) { |
| ExampleAddon* addon = info.Env().GetInstanceData<ExampleAddon>(); |
| } |
| ``` |
| |
| ## Methods |
| |
| ### Constructor |
| |
| Creates a new instance of the add-on. |
| |
| ```cpp |
| Napi::Addon(Napi::Env env, Napi::Object exports); |
| ``` |
| |
| - `[in] env`: The environment into which the add-on is being loaded. |
| - `[in] exports`: The exports object received from JavaScript. |
| |
| Typically, the constructor calls `DefineAddon()` to attach methods, accessors, |
| and/or values to `exports`. The constructor may also create a new object and |
| pass it to `DefineAddon()` as its first parameter if it wishes to replace the |
| `exports` object as provided by Node.js. |
| |
| ### DefineAddon |
| |
| Defines an add-on instance with functions, accessors, and/or values. |
| |
| ```cpp |
| template <typename T> |
| void Napi::Addon<T>::DefineAddon(Napi::Object exports, |
| const std::initializer_list<PropertyDescriptor>& properties); |
| ``` |
| |
| * `[in] exports`: The object to return to Node.js as an instance of the add-on. |
| * `[in] properties`: Initializer list of add-on property descriptors of the |
| methods, property accessors, and values that define the add-on. They will be |
| set on `exports`. |
| See: [`Class property and descriptor`](class_property_descriptor.md). |
| |
| ### DefineProperties |
| |
| Defines function, accessor, and/or value properties on an object using add-on |
| instance methods. |
| |
| ```cpp |
| template <typename T> |
| Napi::Object |
| Napi::Addon<T>::DefineProperties(Napi::Object object, |
| const std::initializer_list<PropertyDescriptor>& properties); |
| ``` |
| |
| * `[in] object`: The object that will receive the new properties. |
| * `[in] properties`: Initializer list of property descriptors of the methods, |
| property accessors, and values to attach to `object`. |
| See: [`Class property and descriptor`](class_property_descriptor.md). |
| |
| Returns `object`. |
| |
| [`Napi::InstanceWrap<T>`]: ./instance_wrap.md |