Lines Matching +full:hook +full:- +full:run +full:- +full:in +full:- +full:context
3 <!--introduced_in=v0.10.0-->
4 <!-- type=misc -->
6 _Addons_ are dynamically-linked shared objects written in C++. The
10 There are three options for implementing addons: N-API, nan, or direct
12 direct access to functionality which is not exposed by N-API, use N-API.
13 Refer to [C/C++ addons with N-API](n-api.html) for more information on N-API.
15 When not using N-API, implementing addons is complicated,
20 calling functions, etc. V8's API is documented mostly in the
21 `v8.h` header file (`deps/v8/include/v8.h` in the Node.js source
22 tree), which is also available [online][v8-docs].
26 serves as a cross-platform abstraction library, giving easy, POSIX-like
29 also provides a pthreads-like threading abstraction that may be used to
32 avoid blocking the event loop with I/O or other time-intensive tasks by
33 off-loading work via libuv to non-blocking system operations, worker threads
40 other libraries are located in the `deps/` directory in the Node.js source
42 re-exported by Node.js and may be used to various extents by addons. See
46 be used as the starting-point for an addon.
50 This "Hello world" example is a simple addon, written in C++, that is the
96 There is no semi-colon after `NODE_MODULE` as it's not a function (see
102 In the `hello.cc` example, then, the initialization function is `Initialize`
105 When building addons with `node-gyp`, using the macro `NODE_GYP_MODULE_NAME` as
109 ### Context-aware addons
111 There are environments in which Node.js addons may need to be loaded multiple
112 times in multiple contexts. For example, the [Electron][] runtime runs multiple
113 instances of Node.js in a single process. Each instance will have its own
118 A context-aware addon can be constructed by using the macro
121 in the following example:
129 Local<Context> context) {
135 construct a context-aware addon. Unlike `NODE_MODULE()`, which is used to
145 * `Local<Context> context`
147 The choice to build a context-aware addon carries with it the responsibility of
150 in the addon must be properly protected, and must not contain any persistent
152 objects are only valid in one context, and will likely cause a crash when
153 accessed from the wrong context or from a different thread than the one on which
156 The context-aware addon can be structured to avoid global static data by
158 * Define a class which will hold per-addon-instance data and which has a static
165 * Heap-allocate an instance of this class in the addon initializer. This can be
167 * Call `node::AddEnvironmentCleanupHook()`, passing it the above-created
170 * Store the instance of the class in a `v8::External`, and
173 native-backed JavaScript functions. The third parameter of
175 `v8::External` and makes it available in the native callback using the
178 This will ensure that the per-addon-instance data reaches each binding that can
179 be called from JavaScript. The per-addon-instance data must also be passed into
182 The following example illustrates the implementation of a context-aware addon:
193 // Ensure this per-addon-instance data is deleted at environment cleanup.
197 // Per-addon data.
206 // Retrieve the per-addon-instance data.
208 reinterpret_cast<AddonData*>(info.Data().As<External>()->Value());
209 data->call_count++;
210 info.GetReturnValue().Set((double)data->call_count);
213 // Initialize this addon to be context-aware.
214 NODE_MODULE_INIT(/* exports, module, context */) {
215 Isolate* isolate = context->GetIsolate();
221 // Wrap the data in a `v8::External` so we can pass it to the method we
226 // per-addon-instance data we created above by passing `external` as the
228 exports->Set(context,
232 ->GetFunction(context).ToLocalChecked()).FromJust();
237 <!-- YAML
239 - version: v12.19.0
240 pr-url: https://github.com/nodejs/node/pull/34572
242 -->
244 In order to be loaded from multiple Node.js environments,
245 such as a main thread and a Worker thread, an add-on needs to either:
247 * Be an N-API addon, or
248 * Be declared as context-aware using `NODE_MODULE_INIT()` as described above
250 In order to support [`Worker`][] threads, addons need to clean up any resources
260 This function adds a hook that will run before a given Node.js instance shuts
261 down. If necessary, such hooks can be removed before they are run using
263 run in last-in first-out order.
266 and `RemoveEnvironmentCleanupHook()` overloads, where the cleanup hook takes a
284 // Note: In a real-world application, do not rely on static/global data.
294 assert(obj->IsObject());
308 // Initialize this addon to be context-aware.
309 NODE_MODULE_INIT(/* exports, module, context */) {
310 Isolate* isolate = context->GetIsolate();
318 Test in JavaScript by running:
328 `addon.node` file. To do so, create a file called `binding.gyp` in the
329 top-level of the project describing the build configuration of the module
330 using a JSON-like format. This file is used by [node-gyp][], a tool written
344 A version of the `node-gyp` utility is bundled and distributed with
348 use `node-gyp` directly can install it using the command
349 `npm install -g node-gyp`. See the `node-gyp` [installation instructions][] for
350 more information, including platform-specific requirements.
352 Once the `binding.gyp` file has been created, use `node-gyp configure` to
355 (on Windows) in the `build/` directory.
357 Next, invoke the `node-gyp build` command to generate the compiled `addon.node`
361 version of `node-gyp` to perform this same set of actions, generating a
376 it is compiled (i.e. sometimes it may be in `./build/Debug/`), addons can use
379 While the `bindings` package implementation is more sophisticated in how it
395 `#include <...>` statements (e.g. `#include <v8.h>`) and `node-gyp` will locate
399 * When `node-gyp` runs, it will detect the specific release version of Node.js
405 * `node-gyp` can be run using the `--nodedir` flag pointing at a local Node.js
413 files with the `.node` file extension and initialize those as dynamically-linked
420 there is a file `addon.js` in the same directory as the binary `addon.node`,
426 Each of the examples illustrated in this document directly use the
429 the next). With each change, addons may need to be updated and recompiled in
439 ## N-API
441 > Stability: 2 - Stable
443 N-API is an API for building native addons. It is independent from
447 changes in the underlying JavaScript engine and allow modules
448 compiled for one version to run on later versions of Node.js without
450 outlined in this document (node-gyp, etc.). The only difference is the
453 in the N-API are used.
456 provided by N-API carries with it certain
457 [implementation considerations](n-api.html#n_api_implications_of_abi_stability).
459 To use N-API in the above "Hello world" example, replace the content of
463 // hello.cc using N-API
494 The functions available and how to use them are documented in
495 [C/C++ addons with N-API](n-api.html).
500 examples use the V8 APIs. Refer to the online [V8 reference][v8-docs]
518 In cases where there is more than one `.cc` file, simply add the additional
526 built using `node-gyp`:
529 $ node-gyp configure build
567 isolate->ThrowException(Exception::TypeError(
575 if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
576 isolate->ThrowException(Exception::TypeError(
585 args[0].As<Number>()->Value() + args[1].As<Number>()->Value();
588 // Set the return value (using the passed in
623 using v8::Context;
636 Local<Context> context = isolate->GetCurrentContext();
643 cb->Call(context, Null(isolate), argc, argv).ToLocalChecked();
655 This example uses a two-argument form of `Init()` that receives the full
660 To test it, run the following JavaScript:
672 In this example, the callback function is invoked synchronously.
677 illustrated in the following example. An object is created and returned with a
686 using v8::Context;
697 Local<Context> context = isolate->GetCurrentContext();
700 obj->Set(context,
704 args[0]->ToString(context).ToLocalChecked())
719 To test it in JavaScript:
742 using v8::Context;
762 Local<Context> context = isolate->GetCurrentContext();
764 Local<Function> fn = tpl->GetFunction(context).ToLocalChecked();
767 fn->SetName(String::NewFromUtf8(
795 It is also possible to wrap C++ objects/classes in a way that allows new
817 Then, in `myobject.h`, the wrapper class inherits from `node::ObjectWrap`:
848 In `myobject.cc`, implement the various methods that are to be exposed.
858 using v8::Context;
878 Isolate* isolate = exports->GetIsolate();
879 Local<Context> context = isolate->GetCurrentContext();
882 addon_data_tpl->SetInternalFieldCount(1); // 1 field for the MyObject::New()
884 addon_data_tpl->NewInstance(context).ToLocalChecked();
888 tpl->SetClassName(String::NewFromUtf8(
890 tpl->InstanceTemplate()->SetInternalFieldCount(1);
895 Local<Function> constructor = tpl->GetFunction(context).ToLocalChecked();
896 addon_data->SetInternalField(0, constructor);
897 exports->Set(context, String::NewFromUtf8(
904 Local<Context> context = isolate->GetCurrentContext();
908 double value = args[0]->IsUndefined() ?
909 0 : args[0]->NumberValue(context).FromMaybe(0);
911 obj->Wrap(args.This());
918 args.Data().As<Object>()->GetInternalField(0).As<Function>();
920 cons->NewInstance(context, argc, argv).ToLocalChecked();
929 obj->value_ += 1;
931 args.GetReturnValue().Set(Number::New(isolate, obj->value_));
969 The destructor for a wrapper object will run when the object is
970 garbage-collected. For destructor testing, there are command-line flags that
987 First, the `createObject()` method is implemented in `addon.cc`:
1008 MyObject::Init(exports->GetIsolate());
1018 In `myobject.h`, the static method `NewInstance()` is added to handle
1019 instantiating the object. This method takes the place of using `new` in
1052 The implementation in `myobject.cc` is similar to the previous example:
1062 using v8::Context;
1075 // Warning! This is not thread-safe, this addon cannot be used for worker
1088 tpl->SetClassName(String::NewFromUtf8(
1090 tpl->InstanceTemplate()->SetInternalFieldCount(1);
1095 Local<Context> context = isolate->GetCurrentContext();
1096 constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
1105 Local<Context> context = isolate->GetCurrentContext();
1109 double value = args[0]->IsUndefined() ?
1110 0 : args[0]->NumberValue(context).FromMaybe(0);
1112 obj->Wrap(args.This());
1120 cons->NewInstance(context, argc, argv).ToLocalChecked();
1131 Local<Context> context = isolate->GetCurrentContext();
1133 cons->NewInstance(context, argc, argv).ToLocalChecked();
1142 obj->value_ += 1;
1144 args.GetReturnValue().Set(Number::New(isolate, obj->value_));
1192 In addition to wrapping and returning C++ objects, it is possible to pass
1205 using v8::Context;
1220 Local<Context> context = isolate->GetCurrentContext();
1223 args[0]->ToObject(context).ToLocalChecked());
1225 args[1]->ToObject(context).ToLocalChecked());
1227 double sum = obj1->value() + obj2->value();
1232 MyObject::Init(exports->GetIsolate());
1243 In `myobject.h`, a new public method is added to allow access to private values
1286 using v8::Context;
1298 // Warning! This is not thread-safe, this addon cannot be used for worker
1311 tpl->SetClassName(String::NewFromUtf8(
1313 tpl->InstanceTemplate()->SetInternalFieldCount(1);
1315 Local<Context> context = isolate->GetCurrentContext();
1316 constructor.Reset(isolate, tpl->GetFunction(context).ToLocalChecked());
1325 Local<Context> context = isolate->GetCurrentContext();
1329 double value = args[0]->IsUndefined() ?
1330 0 : args[0]->NumberValue(context).FromMaybe(0);
1332 obj->Wrap(args.This());
1340 cons->NewInstance(context, argc, argv).ToLocalChecked();
1351 Local<Context> context = isolate->GetCurrentContext();
1353 cons->NewInstance(context, argc, argv).ToLocalChecked();
1380 [bindings]: https://github.com/TooTallNate/node-bindings
1381 [download]: https://github.com/nodejs/node-addon-examples
1383 [installation instructions]: https://github.com/nodejs/node-gyp#installation
1385 [node-gyp]: https://github.com/nodejs/node-gyp
1387 [v8-docs]: https://v8docs.nodesource.com/