@@ -78,7 +78,7 @@ it still gets the benefits of the ABI stability provided by the C API.
7878When using `node-addon-api` instead of the C APIs, start with the API [docs][]
7979for `node-addon-api`.
8080
81- The [Node-API Resource](https://nodejs.github.io/node-addon-examples/) offers
81+ The [Node-API Resource](https://nodejs.github.io/node-addon-examples/) offers
8282an excellent orientation and tips for developers just getting started with
8383Node-API and `node-addon-api`. Additional media resources can be found on the
8484[Node-API Media][] page.
@@ -175,7 +175,8 @@ developers have run into limitations in node-gyp.
175175[CMake.js][] is an alternative build system based on [CMake][].
176176
177177CMake.js is a good choice for projects that already use CMake or for
178- developers affected by limitations in node-gyp.
178+ developers affected by limitations in node-gyp. [`build_with_cmake`][] is an
179+ example of a CMake-based native addon project.
179180
180181### Uploading precompiled binaries
181182
@@ -237,6 +238,18 @@ Some of the Node-API surface is experimental and requires explicit opt-in:
237238In this case the entire API surface, including any experimental APIs, will be
238239available to the module code.
239240
241+ Occasionally, experimental features are introduced that affect already-released
242+ and stable APIs. These features are guarded by an additional opt-in:
243+
244+ ```c
245+ #define NAPI_EXPERIMENTAL
246+ #define NODE_API_EXPERIMENTAL_<FEATURE_NAME>
247+ #include <node_api.h>
248+ ```
249+
250+ where `<FEATURE_NAME>` is the name of an experimental feature that affects both
251+ experimental and stable APIs.
252+
240253## Node-API version matrix
241254
242255Up until version 9, Node-API versions were additive and versioned
@@ -419,7 +432,7 @@ napi_value create_addon(napi_env env) {
419432#include <node_api.h>
420433#include "addon.h"
421434
422- NAPI_MODULE_INIT() {
435+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
423436 // This function body is expected to return a `napi_value`.
424437 // The variables `napi_env env` and `napi_value exports` may be used within
425438 // the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
@@ -464,7 +477,7 @@ napiVersion: 6
464477-->
465478
466479```c
467- napi_status napi_set_instance_data(napi_env env,
480+ napi_status napi_set_instance_data(node_api_nogc_env env,
468481 void* data,
469482 napi_finalize finalize_cb,
470483 void* finalize_hint);
@@ -496,7 +509,7 @@ napiVersion: 6
496509-->
497510
498511```c
499- napi_status napi_get_instance_data(napi_env env,
512+ napi_status napi_get_instance_data(node_api_nogc_env env,
500513 void** data);
501514```
502515
@@ -598,6 +611,22 @@ when an instance of a native addon is unloaded. Notification of this event is
598611delivered through the callbacks given to [`napi_add_env_cleanup_hook`][] and
599612[`napi_set_instance_data`][].
600613
614+ ### `node_api_nogc_env`
615+
616+ > Stability: 1 - Experimental
617+
618+ This variant of `napi_env` is passed to synchronous finalizers
619+ ([`node_api_nogc_finalize`][]). There is a subset of Node-APIs which accept
620+ a parameter of type `node_api_nogc_env` as their first argument. These APIs do
621+ not access the state of the JavaScript engine and are thus safe to call from
622+ synchronous finalizers. Passing a parameter of type `napi_env` to these APIs is
623+ allowed, however, passing a parameter of type `node_api_nogc_env` to APIs that
624+ access the JavaScript engine state is not allowed. Attempting to do so without
625+ a cast will produce a compiler warning or an error when add-ons are compiled
626+ with flags which cause them to emit warnings and/or errors when incorrect
627+ pointer types are passed into a function. Calling such APIs from a synchronous
628+ finalizer will ultimately result in the termination of the application.
629+
601630### `napi_value`
602631
603632This is an opaque pointer that is used to represent a JavaScript value.
@@ -762,32 +791,36 @@ typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
762791Unless for reasons discussed in [Object Lifetime Management][], creating a
763792handle and/or callback scope inside a `napi_callback` is not necessary.
764793
765- #### `napi_finalize `
794+ #### `node_api_nogc_finalize `
766795
767796<!-- YAML
768- added: v8.0.0
769- napiVersion: 1
797+ added: REPLACEME
770798-->
771799
800+ > Stability: 1 - Experimental
801+
772802Function pointer type for add-on provided functions that allow the user to be
773803notified when externally-owned data is ready to be cleaned up because the
774- object with which it was associated with has been garbage-collected. The user
775- must provide a function satisfying the following signature which would get
776- called upon the object's collection. Currently, `napi_finalize ` can be used for
804+ object it was associated with has been garbage-collected. The user must provide
805+ a function satisfying the following signature which would get called upon the
806+ object's collection. Currently, `node_api_nogc_finalize ` can be used for
777807finding out when objects that have external data are collected.
778808
779809```c
780- typedef void (*napi_finalize)(napi_env env,
781- void* finalize_data,
782- void* finalize_hint);
810+ typedef void (*node_api_nogc_finalize)(node_api_nogc_env env,
811+ void* finalize_data,
812+ void* finalize_hint);
783813```
784814
785815Unless for reasons discussed in [Object Lifetime Management][], creating a
786816handle and/or callback scope inside the function body is not necessary.
787817
788818Since these functions may be called while the JavaScript engine is in a state
789- where it cannot execute JavaScript code, some Node-API calls may return
790- `napi_pending_exception` even when there is no exception pending.
819+ where it cannot execute JavaScript code, only Node-APIs which accept a
820+ `node_api_nogc_env` as their first parameter may be called.
821+ [`node_api_post_finalizer`][] can be used to schedule Node-API calls that
822+ require access to the JavaScript engine's state to run after the current
823+ garbage collection cycle has completed.
791824
792825In the case of [`node_api_create_external_string_latin1`][] and
793826[`node_api_create_external_string_utf16`][] the `env` parameter may be null,
@@ -796,11 +829,40 @@ shutdown.
796829
797830Change History:
798831
799- * experimental (`NAPI_EXPERIMENTAL` is defined):
832+ * experimental (`NAPI_EXPERIMENTAL` and `NODE_API_EXPERIMENTAL_NOGC_ENV` are
833+ defined):
800834
801- Node-API calls made from a finalizer will return `napi_cannot_run_js` when
802- the JavaScript engine is unable to execute JavaScript, and will return
803- `napi_exception_pending` if there is a pending exception.
835+ Only Node-API calls that accept a `node_api_nogc_env` as their first
836+ parameter may be called, otherwise the application will be terminated with an
837+ appropriate error message.
838+
839+ #### `napi_finalize`
840+
841+ <!-- YAML
842+ added: v8.0.0
843+ napiVersion: 1
844+ -->
845+
846+ Function pointer type for add-on provided function that allow the user to
847+ schedule a group of calls to Node-APIs in response to a garbage collection
848+ event, after the garbage collection cycle has completed. These function
849+ pointers can be used with [`node_api_post_finalizer`][] and
850+ [`napi_set_instance_data`][].
851+
852+ ```c
853+ typedef void (*napi_finalize)(napi_env env,
854+ void* finalize_data,
855+ void* finalize_hint);
856+ ```
857+
858+ Change History:
859+
860+ * experimental (`NAPI_EXPERIMENTAL` and `NODE_API_EXPERIMENTAL_NOGC_ENV` are
861+ defined):
862+
863+ A function of this type may no longer be used as a finalizer, except with
864+ [`node_api_post_finalizer`][] and [`napi_set_instance_data`][].
865+ [`node_api_nogc_finalize`][] must be used instead.
804866
805867#### `napi_async_execute_callback`
806868
@@ -1002,7 +1064,7 @@ napiVersion: 1
10021064
10031065```c
10041066napi_status
1005- napi_get_last_error_info(napi_env env,
1067+ napi_get_last_error_info(node_api_nogc_env env,
10061068 const napi_extended_error_info** result);
10071069```
10081070
@@ -1821,7 +1883,7 @@ napiVersion: 3
18211883-->
18221884
18231885```c
1824- NODE_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env,
1886+ NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_nogc_env env,
18251887 napi_cleanup_hook fun,
18261888 void* arg);
18271889```
@@ -1851,7 +1913,7 @@ napiVersion: 3
18511913-->
18521914
18531915```c
1854- NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env,
1916+ NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_nogc_env env,
18551917 void (*fun)(void* arg),
18561918 void* arg);
18571919```
@@ -1880,7 +1942,7 @@ changes:
18801942
18811943```c
18821944NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
1883- napi_env env,
1945+ node_api_nogc_env env,
18841946 napi_async_cleanup_hook hook,
18851947 void* arg,
18861948 napi_async_cleanup_hook_handle* remove_handle);
@@ -2038,7 +2100,7 @@ You can also use the `NAPI_MODULE_INIT` macro, which acts as a shorthand
20382100for `NAPI_MODULE` and defining an `Init` function:
20392101
20402102```c
2041- NAPI_MODULE_INIT() {
2103+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
20422104 napi_value answer;
20432105 napi_status result;
20442106
@@ -2052,6 +2114,9 @@ NAPI_MODULE_INIT() {
20522114}
20532115```
20542116
2117+ The parameters `env` and `exports` are provided to the body of the
2118+ `NAPI_MODULE_INIT` macro.
2119+
20552120All Node-API addons are context-aware, meaning they may be loaded multiple
20562121times. There are a few design considerations when declaring such a module.
20572122The documentation on [context-aware addons][] provides more details.
@@ -5420,7 +5485,7 @@ napiVersion: 5
54205485napi_status napi_add_finalizer(napi_env env,
54215486 napi_value js_object,
54225487 void* finalize_data,
5423- napi_finalize finalize_cb,
5488+ node_api_nogc_finalize finalize_cb,
54245489 void* finalize_hint,
54255490 napi_ref* result);
54265491```
@@ -5458,7 +5523,7 @@ added: v21.0.0
54585523> Stability: 1 - Experimental
54595524
54605525```c
5461- napi_status node_api_post_finalizer(napi_env env,
5526+ napi_status node_api_post_finalizer(node_api_nogc_env env,
54625527 napi_finalize finalize_cb,
54635528 void* finalize_data,
54645529 void* finalize_hint);
@@ -5528,7 +5593,7 @@ Once created the async worker can be queued
55285593for execution using the [`napi_queue_async_work`][] function:
55295594
55305595```c
5531- napi_status napi_queue_async_work(napi_env env,
5596+ napi_status napi_queue_async_work(node_api_nogc_env env,
55325597 napi_async_work work);
55335598```
55345599
@@ -5620,7 +5685,7 @@ napiVersion: 1
56205685-->
56215686
56225687```c
5623- napi_status napi_queue_async_work(napi_env env,
5688+ napi_status napi_queue_async_work(node_api_nogc_env env,
56245689 napi_async_work work);
56255690```
56265691
@@ -5641,7 +5706,7 @@ napiVersion: 1
56415706-->
56425707
56435708```c
5644- napi_status napi_cancel_async_work(napi_env env,
5709+ napi_status napi_cancel_async_work(node_api_nogc_env env,
56455710 napi_async_work work);
56465711```
56475712
@@ -5845,7 +5910,7 @@ typedef struct {
58455910 const char* release;
58465911} napi_node_version;
58475912
5848- napi_status napi_get_node_version(napi_env env,
5913+ napi_status napi_get_node_version(node_api_nogc_env env,
58495914 const napi_node_version** version);
58505915```
58515916
@@ -5868,7 +5933,7 @@ napiVersion: 1
58685933-->
58695934
58705935```c
5871- napi_status napi_get_version(napi_env env,
5936+ napi_status napi_get_version(node_api_nogc_env env,
58725937 uint32_t* result);
58735938```
58745939
@@ -5901,7 +5966,7 @@ napiVersion: 1
59015966-->
59025967
59035968```c
5904- NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env,
5969+ NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_nogc_env env,
59055970 int64_t change_in_bytes,
59065971 int64_t* result);
59075972```
@@ -6118,7 +6183,7 @@ napiVersion: 2
61186183-->
61196184
61206185```c
6121- NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env,
6186+ NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_nogc_env env,
61226187 struct uv_loop_s** loop);
61236188```
61246189
@@ -6432,7 +6497,7 @@ napiVersion: 4
64326497
64336498```c
64346499NAPI_EXTERN napi_status
6435- napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
6500+ napi_ref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func);
64366501```
64376502
64386503* `[in] env`: The environment that the API is invoked under.
@@ -6458,7 +6523,7 @@ napiVersion: 4
64586523
64596524```c
64606525NAPI_EXTERN napi_status
6461- napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
6526+ napi_unref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func);
64626527```
64636528
64646529* `[in] env`: The environment that the API is invoked under.
@@ -6484,7 +6549,7 @@ napiVersion: 9
64846549
64856550```c
64866551NAPI_EXTERN napi_status
6487- node_api_get_module_file_name(napi_env env, const char** result);
6552+ node_api_get_module_file_name(node_api_nogc_env env, const char** result);
64886553
64896554```
64906555
@@ -6548,6 +6613,7 @@ the add-on's file name during loading.
65486613[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer
65496614[`Worker`]: worker_threads.md#class-worker
65506615[`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource
6616+ [`build_with_cmake`]: https://github.com/nodejs/node-addon-examples/tree/main/build_with_cmake
65516617[`global`]: globals.md#global
65526618[`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource
65536619[`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook
@@ -6611,6 +6677,8 @@ the add-on's file name during loading.
66116677[`node_api_create_external_string_latin1`]: #node_api_create_external_string_latin1
66126678[`node_api_create_external_string_utf16`]: #node_api_create_external_string_utf16
66136679[`node_api_create_syntax_error`]: #node_api_create_syntax_error
6680+ [`node_api_nogc_finalize`]: #node_api_nogc_finalize
6681+ [`node_api_post_finalizer`]: #node_api_post_finalizer
66146682[`node_api_throw_syntax_error`]: #node_api_throw_syntax_error
66156683[`process.release`]: process.md#processrelease
66166684[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref
0 commit comments