@@ -78,7 +78,7 @@ it still gets the benefits of the ABI stability provided by the C API.
78
78
When using `node-addon-api` instead of the C APIs, start with the API [docs][]
79
79
for `node-addon-api`.
80
80
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
82
82
an excellent orientation and tips for developers just getting started with
83
83
Node-API and `node-addon-api`. Additional media resources can be found on the
84
84
[Node-API Media][] page.
@@ -175,7 +175,8 @@ developers have run into limitations in node-gyp.
175
175
[CMake.js][] is an alternative build system based on [CMake][].
176
176
177
177
CMake.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.
179
180
180
181
### Uploading precompiled binaries
181
182
@@ -237,6 +238,18 @@ Some of the Node-API surface is experimental and requires explicit opt-in:
237
238
In this case the entire API surface, including any experimental APIs, will be
238
239
available to the module code.
239
240
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
+
240
253
## Node-API version matrix
241
254
242
255
Up until version 9, Node-API versions were additive and versioned
@@ -419,7 +432,7 @@ napi_value create_addon(napi_env env) {
419
432
#include <node_api.h>
420
433
#include "addon.h"
421
434
422
- NAPI_MODULE_INIT() {
435
+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
423
436
// This function body is expected to return a `napi_value`.
424
437
// The variables `napi_env env` and `napi_value exports` may be used within
425
438
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
@@ -464,7 +477,7 @@ napiVersion: 6
464
477
-->
465
478
466
479
```c
467
- napi_status napi_set_instance_data(napi_env env,
480
+ napi_status napi_set_instance_data(node_api_nogc_env env,
468
481
void* data,
469
482
napi_finalize finalize_cb,
470
483
void* finalize_hint);
@@ -496,7 +509,7 @@ napiVersion: 6
496
509
-->
497
510
498
511
```c
499
- napi_status napi_get_instance_data(napi_env env,
512
+ napi_status napi_get_instance_data(node_api_nogc_env env,
500
513
void** data);
501
514
```
502
515
@@ -598,6 +611,22 @@ when an instance of a native addon is unloaded. Notification of this event is
598
611
delivered through the callbacks given to [`napi_add_env_cleanup_hook`][] and
599
612
[`napi_set_instance_data`][].
600
613
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
+
601
630
### `napi_value`
602
631
603
632
This 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);
762
791
Unless for reasons discussed in [Object Lifetime Management][], creating a
763
792
handle and/or callback scope inside a `napi_callback` is not necessary.
764
793
765
- #### `napi_finalize `
794
+ #### `node_api_nogc_finalize `
766
795
767
796
<!-- YAML
768
- added: v8.0.0
769
- napiVersion: 1
797
+ added: REPLACEME
770
798
-->
771
799
800
+ > Stability: 1 - Experimental
801
+
772
802
Function pointer type for add-on provided functions that allow the user to be
773
803
notified 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
777
807
finding out when objects that have external data are collected.
778
808
779
809
```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);
783
813
```
784
814
785
815
Unless for reasons discussed in [Object Lifetime Management][], creating a
786
816
handle and/or callback scope inside the function body is not necessary.
787
817
788
818
Since 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.
791
824
792
825
In the case of [`node_api_create_external_string_latin1`][] and
793
826
[`node_api_create_external_string_utf16`][] the `env` parameter may be null,
@@ -796,11 +829,40 @@ shutdown.
796
829
797
830
Change History:
798
831
799
- * experimental (`NAPI_EXPERIMENTAL` is defined):
832
+ * experimental (`NAPI_EXPERIMENTAL` and `NODE_API_EXPERIMENTAL_NOGC_ENV` are
833
+ defined):
800
834
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.
804
866
805
867
#### `napi_async_execute_callback`
806
868
@@ -1002,7 +1064,7 @@ napiVersion: 1
1002
1064
1003
1065
```c
1004
1066
napi_status
1005
- napi_get_last_error_info(napi_env env,
1067
+ napi_get_last_error_info(node_api_nogc_env env,
1006
1068
const napi_extended_error_info** result);
1007
1069
```
1008
1070
@@ -1821,7 +1883,7 @@ napiVersion: 3
1821
1883
-->
1822
1884
1823
1885
```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,
1825
1887
napi_cleanup_hook fun,
1826
1888
void* arg);
1827
1889
```
@@ -1851,7 +1913,7 @@ napiVersion: 3
1851
1913
-->
1852
1914
1853
1915
```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,
1855
1917
void (*fun)(void* arg),
1856
1918
void* arg);
1857
1919
```
@@ -1880,7 +1942,7 @@ changes:
1880
1942
1881
1943
```c
1882
1944
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
1883
- napi_env env,
1945
+ node_api_nogc_env env,
1884
1946
napi_async_cleanup_hook hook,
1885
1947
void* arg,
1886
1948
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
2038
2100
for `NAPI_MODULE` and defining an `Init` function:
2039
2101
2040
2102
```c
2041
- NAPI_MODULE_INIT() {
2103
+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
2042
2104
napi_value answer;
2043
2105
napi_status result;
2044
2106
@@ -2052,6 +2114,9 @@ NAPI_MODULE_INIT() {
2052
2114
}
2053
2115
```
2054
2116
2117
+ The parameters `env` and `exports` are provided to the body of the
2118
+ `NAPI_MODULE_INIT` macro.
2119
+
2055
2120
All Node-API addons are context-aware, meaning they may be loaded multiple
2056
2121
times. There are a few design considerations when declaring such a module.
2057
2122
The documentation on [context-aware addons][] provides more details.
@@ -5420,7 +5485,7 @@ napiVersion: 5
5420
5485
napi_status napi_add_finalizer(napi_env env,
5421
5486
napi_value js_object,
5422
5487
void* finalize_data,
5423
- napi_finalize finalize_cb,
5488
+ node_api_nogc_finalize finalize_cb,
5424
5489
void* finalize_hint,
5425
5490
napi_ref* result);
5426
5491
```
@@ -5458,7 +5523,7 @@ added: v21.0.0
5458
5523
> Stability: 1 - Experimental
5459
5524
5460
5525
```c
5461
- napi_status node_api_post_finalizer(napi_env env,
5526
+ napi_status node_api_post_finalizer(node_api_nogc_env env,
5462
5527
napi_finalize finalize_cb,
5463
5528
void* finalize_data,
5464
5529
void* finalize_hint);
@@ -5528,7 +5593,7 @@ Once created the async worker can be queued
5528
5593
for execution using the [`napi_queue_async_work`][] function:
5529
5594
5530
5595
```c
5531
- napi_status napi_queue_async_work(napi_env env,
5596
+ napi_status napi_queue_async_work(node_api_nogc_env env,
5532
5597
napi_async_work work);
5533
5598
```
5534
5599
@@ -5620,7 +5685,7 @@ napiVersion: 1
5620
5685
-->
5621
5686
5622
5687
```c
5623
- napi_status napi_queue_async_work(napi_env env,
5688
+ napi_status napi_queue_async_work(node_api_nogc_env env,
5624
5689
napi_async_work work);
5625
5690
```
5626
5691
@@ -5641,7 +5706,7 @@ napiVersion: 1
5641
5706
-->
5642
5707
5643
5708
```c
5644
- napi_status napi_cancel_async_work(napi_env env,
5709
+ napi_status napi_cancel_async_work(node_api_nogc_env env,
5645
5710
napi_async_work work);
5646
5711
```
5647
5712
@@ -5845,7 +5910,7 @@ typedef struct {
5845
5910
const char* release;
5846
5911
} napi_node_version;
5847
5912
5848
- napi_status napi_get_node_version(napi_env env,
5913
+ napi_status napi_get_node_version(node_api_nogc_env env,
5849
5914
const napi_node_version** version);
5850
5915
```
5851
5916
@@ -5868,7 +5933,7 @@ napiVersion: 1
5868
5933
-->
5869
5934
5870
5935
```c
5871
- napi_status napi_get_version(napi_env env,
5936
+ napi_status napi_get_version(node_api_nogc_env env,
5872
5937
uint32_t* result);
5873
5938
```
5874
5939
@@ -5901,7 +5966,7 @@ napiVersion: 1
5901
5966
-->
5902
5967
5903
5968
```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,
5905
5970
int64_t change_in_bytes,
5906
5971
int64_t* result);
5907
5972
```
@@ -6118,7 +6183,7 @@ napiVersion: 2
6118
6183
-->
6119
6184
6120
6185
```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,
6122
6187
struct uv_loop_s** loop);
6123
6188
```
6124
6189
@@ -6432,7 +6497,7 @@ napiVersion: 4
6432
6497
6433
6498
```c
6434
6499
NAPI_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);
6436
6501
```
6437
6502
6438
6503
* `[in] env`: The environment that the API is invoked under.
@@ -6458,7 +6523,7 @@ napiVersion: 4
6458
6523
6459
6524
```c
6460
6525
NAPI_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);
6462
6527
```
6463
6528
6464
6529
* `[in] env`: The environment that the API is invoked under.
@@ -6484,7 +6549,7 @@ napiVersion: 9
6484
6549
6485
6550
```c
6486
6551
NAPI_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);
6488
6553
6489
6554
```
6490
6555
@@ -6548,6 +6613,7 @@ the add-on's file name during loading.
6548
6613
[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer
6549
6614
[`Worker`]: worker_threads.md#class-worker
6550
6615
[`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource
6616
+ [`build_with_cmake`]: https://github.com/nodejs/node-addon-examples/tree/main/build_with_cmake
6551
6617
[`global`]: globals.md#global
6552
6618
[`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource
6553
6619
[`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook
@@ -6611,6 +6677,8 @@ the add-on's file name during loading.
6611
6677
[`node_api_create_external_string_latin1`]: #node_api_create_external_string_latin1
6612
6678
[`node_api_create_external_string_utf16`]: #node_api_create_external_string_utf16
6613
6679
[`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
6614
6682
[`node_api_throw_syntax_error`]: #node_api_throw_syntax_error
6615
6683
[`process.release`]: process.md#processrelease
6616
6684
[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref
0 commit comments