@@ -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 can be disabled by an opt-out:
243+
244+ ```c
245+ #define NAPI_EXPERIMENTAL
246+ #define NODE_API_EXPERIMENTAL_<FEATURE_NAME>_OPT_OUT
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
242255Node-API versions are additive and versioned independently from Node.js.
@@ -398,7 +411,7 @@ napi_value create_addon(napi_env env) {
398411#include <node_api.h>
399412#include "addon.h"
400413
401- NAPI_MODULE_INIT() {
414+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
402415 // This function body is expected to return a `napi_value`.
403416 // The variables `napi_env env` and `napi_value exports` may be used within
404417 // the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
@@ -443,7 +456,7 @@ napiVersion: 6
443456-->
444457
445458```c
446- napi_status napi_set_instance_data(napi_env env,
459+ napi_status napi_set_instance_data(node_api_nogc_env env,
447460 void* data,
448461 napi_finalize finalize_cb,
449462 void* finalize_hint);
@@ -475,7 +488,7 @@ napiVersion: 6
475488-->
476489
477490```c
478- napi_status napi_get_instance_data(napi_env env,
491+ napi_status napi_get_instance_data(node_api_nogc_env env,
479492 void** data);
480493```
481494
@@ -577,6 +590,22 @@ when an instance of a native addon is unloaded. Notification of this event is
577590delivered through the callbacks given to [`napi_add_env_cleanup_hook`][] and
578591[`napi_set_instance_data`][].
579592
593+ ### `node_api_nogc_env`
594+
595+ > Stability: 1 - Experimental
596+
597+ This variant of `napi_env` is passed to synchronous finalizers
598+ ([`node_api_nogc_finalize`][]). There is a subset of Node-APIs which accept
599+ a parameter of type `node_api_nogc_env` as their first argument. These APIs do
600+ not access the state of the JavaScript engine and are thus safe to call from
601+ synchronous finalizers. Passing a parameter of type `napi_env` to these APIs is
602+ allowed, however, passing a parameter of type `node_api_nogc_env` to APIs that
603+ access the JavaScript engine state is not allowed. Attempting to do so without
604+ a cast will produce a compiler warning or an error when add-ons are compiled
605+ with flags which cause them to emit warnings and/or errors when incorrect
606+ pointer types are passed into a function. Calling such APIs from a synchronous
607+ finalizer will ultimately result in the termination of the application.
608+
580609### `napi_value`
581610
582611This is an opaque pointer that is used to represent a JavaScript value.
@@ -741,32 +770,36 @@ typedef napi_value (*napi_callback)(napi_env, napi_callback_info);
741770Unless for reasons discussed in [Object Lifetime Management][], creating a
742771handle and/or callback scope inside a `napi_callback` is not necessary.
743772
744- #### `napi_finalize `
773+ #### `node_api_nogc_finalize `
745774
746775<!-- YAML
747- added: v8.0.0
748- napiVersion: 1
776+ added: REPLACEME
749777-->
750778
779+ > Stability: 1 - Experimental
780+
751781Function pointer type for add-on provided functions that allow the user to be
752782notified when externally-owned data is ready to be cleaned up because the
753- object with which it was associated with has been garbage-collected. The user
754- must provide a function satisfying the following signature which would get
755- called upon the object's collection. Currently, `napi_finalize ` can be used for
783+ object it was associated with has been garbage-collected. The user must provide
784+ a function satisfying the following signature which would get called upon the
785+ object's collection. Currently, `node_api_nogc_finalize ` can be used for
756786finding out when objects that have external data are collected.
757787
758788```c
759- typedef void (*napi_finalize)(napi_env env,
760- void* finalize_data,
761- void* finalize_hint);
789+ typedef void (*node_api_nogc_finalize)(node_api_nogc_env env,
790+ void* finalize_data,
791+ void* finalize_hint);
762792```
763793
764794Unless for reasons discussed in [Object Lifetime Management][], creating a
765795handle and/or callback scope inside the function body is not necessary.
766796
767797Since these functions may be called while the JavaScript engine is in a state
768- where it cannot execute JavaScript code, some Node-API calls may return
769- `napi_pending_exception` even when there is no exception pending.
798+ where it cannot execute JavaScript code, only Node-APIs which accept a
799+ `node_api_nogc_env` as their first parameter may be called.
800+ [`node_api_post_finalizer`][] can be used to schedule Node-API calls that
801+ require access to the JavaScript engine's state to run after the current
802+ garbage collection cycle has completed.
770803
771804In the case of [`node_api_create_external_string_latin1`][] and
772805[`node_api_create_external_string_utf16`][] the `env` parameter may be null,
@@ -775,11 +808,39 @@ shutdown.
775808
776809Change History:
777810
811+ * experimental (`NAPI_EXPERIMENTAL`):
812+
813+ Only Node-API calls that accept a `node_api_nogc_env` as their first
814+ parameter may be called, otherwise the application will be terminated with an
815+ appropriate error message. This feature can be turned off by defining
816+ `NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT`.
817+
818+ #### `napi_finalize`
819+
820+ <!-- YAML
821+ added: v8.0.0
822+ napiVersion: 1
823+ -->
824+
825+ Function pointer type for add-on provided function that allow the user to
826+ schedule a group of calls to Node-APIs in response to a garbage collection
827+ event, after the garbage collection cycle has completed. These function
828+ pointers can be used with [`node_api_post_finalizer`][].
829+
830+ ```c
831+ typedef void (*napi_finalize)(napi_env env,
832+ void* finalize_data,
833+ void* finalize_hint);
834+ ```
835+
836+ Change History:
837+
778838* experimental (`NAPI_EXPERIMENTAL` is defined):
779839
780- Node-API calls made from a finalizer will return `napi_cannot_run_js` when
781- the JavaScript engine is unable to execute JavaScript, and will return
782- `napi_exception_pending` if there is a pending exception.
840+ A function of this type may no longer be used as a finalizer, except with
841+ [`node_api_post_finalizer`][]. [`node_api_nogc_finalize`][] must be used
842+ instead. This feature can be turned off by defining
843+ `NODE_API_EXPERIMENTAL_NOGC_ENV_OPT_OUT`.
783844
784845#### `napi_async_execute_callback`
785846
@@ -979,7 +1040,7 @@ napiVersion: 1
9791040
9801041```c
9811042napi_status
982- napi_get_last_error_info(napi_env env,
1043+ napi_get_last_error_info(node_api_nogc_env env,
9831044 const napi_extended_error_info** result);
9841045```
9851046
@@ -1798,7 +1859,7 @@ napiVersion: 3
17981859-->
17991860
18001861```c
1801- NODE_EXTERN napi_status napi_add_env_cleanup_hook(napi_env env,
1862+ NODE_EXTERN napi_status napi_add_env_cleanup_hook(node_api_nogc_env env,
18021863 napi_cleanup_hook fun,
18031864 void* arg);
18041865```
@@ -1828,7 +1889,7 @@ napiVersion: 3
18281889-->
18291890
18301891```c
1831- NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(napi_env env,
1892+ NAPI_EXTERN napi_status napi_remove_env_cleanup_hook(node_api_nogc_env env,
18321893 void (*fun)(void* arg),
18331894 void* arg);
18341895```
@@ -1857,7 +1918,7 @@ changes:
18571918
18581919```c
18591920NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
1860- napi_env env,
1921+ node_api_nogc_env env,
18611922 napi_async_cleanup_hook hook,
18621923 void* arg,
18631924 napi_async_cleanup_hook_handle* remove_handle);
@@ -2015,7 +2076,7 @@ You can also use the `NAPI_MODULE_INIT` macro, which acts as a shorthand
20152076for `NAPI_MODULE` and defining an `Init` function:
20162077
20172078```c
2018- NAPI_MODULE_INIT() {
2079+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
20192080 napi_value answer;
20202081 napi_status result;
20212082
@@ -2029,6 +2090,9 @@ NAPI_MODULE_INIT() {
20292090}
20302091```
20312092
2093+ The parameters `env` and `exports` are provided to the body of the
2094+ `NAPI_MODULE_INIT` macro.
2095+
20322096All Node-API addons are context-aware, meaning they may be loaded multiple
20332097times. There are a few design considerations when declaring such a module.
20342098The documentation on [context-aware addons][] provides more details.
@@ -5391,7 +5455,7 @@ napiVersion: 5
53915455napi_status napi_add_finalizer(napi_env env,
53925456 napi_value js_object,
53935457 void* finalize_data,
5394- napi_finalize finalize_cb,
5458+ node_api_nogc_finalize finalize_cb,
53955459 void* finalize_hint,
53965460 napi_ref* result);
53975461```
@@ -5429,7 +5493,7 @@ added: v18.19.0
54295493> Stability: 1 - Experimental
54305494
54315495```c
5432- napi_status node_api_post_finalizer(napi_env env,
5496+ napi_status node_api_post_finalizer(node_api_nogc_env env,
54335497 napi_finalize finalize_cb,
54345498 void* finalize_data,
54355499 void* finalize_hint);
@@ -5499,7 +5563,7 @@ Once created the async worker can be queued
54995563for execution using the [`napi_queue_async_work`][] function:
55005564
55015565```c
5502- napi_status napi_queue_async_work(napi_env env,
5566+ napi_status napi_queue_async_work(node_api_nogc_env env,
55035567 napi_async_work work);
55045568```
55055569
@@ -5591,7 +5655,7 @@ napiVersion: 1
55915655-->
55925656
55935657```c
5594- napi_status napi_queue_async_work(napi_env env,
5658+ napi_status napi_queue_async_work(node_api_nogc_env env,
55955659 napi_async_work work);
55965660```
55975661
@@ -5612,7 +5676,7 @@ napiVersion: 1
56125676-->
56135677
56145678```c
5615- napi_status napi_cancel_async_work(napi_env env,
5679+ napi_status napi_cancel_async_work(node_api_nogc_env env,
56165680 napi_async_work work);
56175681```
56185682
@@ -5816,7 +5880,7 @@ typedef struct {
58165880 const char* release;
58175881} napi_node_version;
58185882
5819- napi_status napi_get_node_version(napi_env env,
5883+ napi_status napi_get_node_version(node_api_nogc_env env,
58205884 const napi_node_version** version);
58215885```
58225886
@@ -5839,7 +5903,7 @@ napiVersion: 1
58395903-->
58405904
58415905```c
5842- napi_status napi_get_version(napi_env env,
5906+ napi_status napi_get_version(node_api_nogc_env env,
58435907 uint32_t* result);
58445908```
58455909
@@ -5872,7 +5936,7 @@ napiVersion: 1
58725936-->
58735937
58745938```c
5875- NAPI_EXTERN napi_status napi_adjust_external_memory(napi_env env,
5939+ NAPI_EXTERN napi_status napi_adjust_external_memory(node_api_nogc_env env,
58765940 int64_t change_in_bytes,
58775941 int64_t* result);
58785942```
@@ -6089,7 +6153,7 @@ napiVersion: 2
60896153-->
60906154
60916155```c
6092- NAPI_EXTERN napi_status napi_get_uv_event_loop(napi_env env,
6156+ NAPI_EXTERN napi_status napi_get_uv_event_loop(node_api_nogc_env env,
60936157 struct uv_loop_s** loop);
60946158```
60956159
@@ -6403,7 +6467,7 @@ napiVersion: 4
64036467
64046468```c
64056469NAPI_EXTERN napi_status
6406- napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func);
6470+ napi_ref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func);
64076471```
64086472
64096473* `[in] env`: The environment that the API is invoked under.
@@ -6429,7 +6493,7 @@ napiVersion: 4
64296493
64306494```c
64316495NAPI_EXTERN napi_status
6432- napi_unref_threadsafe_function(napi_env env, napi_threadsafe_function func);
6496+ napi_unref_threadsafe_function(node_api_nogc_env env, napi_threadsafe_function func);
64336497```
64346498
64356499* `[in] env`: The environment that the API is invoked under.
@@ -6455,7 +6519,7 @@ napiVersion: 9
64556519
64566520```c
64576521NAPI_EXTERN napi_status
6458- node_api_get_module_file_name(napi_env env, const char** result);
6522+ node_api_get_module_file_name(node_api_nogc_env env, const char** result);
64596523
64606524```
64616525
@@ -6519,6 +6583,7 @@ the add-on's file name during loading.
65196583[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer
65206584[`Worker`]: worker_threads.md#class-worker
65216585[`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource
6586+ [`build_with_cmake`]: https://github.com/nodejs/node-addon-examples/tree/main/build_with_cmake
65226587[`global`]: globals.md#global
65236588[`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource
65246589[`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook
@@ -6582,6 +6647,8 @@ the add-on's file name during loading.
65826647[`node_api_create_external_string_latin1`]: #node_api_create_external_string_latin1
65836648[`node_api_create_external_string_utf16`]: #node_api_create_external_string_utf16
65846649[`node_api_create_syntax_error`]: #node_api_create_syntax_error
6650+ [`node_api_nogc_finalize`]: #node_api_nogc_finalize
6651+ [`node_api_post_finalizer`]: #node_api_post_finalizer
65856652[`node_api_throw_syntax_error`]: #node_api_throw_syntax_error
65866653[`process.release`]: process.md#processrelease
65876654[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref
0 commit comments