@@ -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 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
+
240
253
## Node-API version matrix
241
254
242
255
Node-API versions are additive and versioned independently from Node.js.
@@ -398,7 +411,7 @@ napi_value create_addon(napi_env env) {
398
411
#include <node_api.h>
399
412
#include "addon.h"
400
413
401
- NAPI_MODULE_INIT() {
414
+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
402
415
// This function body is expected to return a `napi_value`.
403
416
// The variables `napi_env env` and `napi_value exports` may be used within
404
417
// the body, as they are provided by the definition of `NAPI_MODULE_INIT()`.
@@ -443,7 +456,7 @@ napiVersion: 6
443
456
-->
444
457
445
458
```c
446
- napi_status napi_set_instance_data(napi_env env,
459
+ napi_status napi_set_instance_data(node_api_nogc_env env,
447
460
void* data,
448
461
napi_finalize finalize_cb,
449
462
void* finalize_hint);
@@ -475,7 +488,7 @@ napiVersion: 6
475
488
-->
476
489
477
490
```c
478
- napi_status napi_get_instance_data(napi_env env,
491
+ napi_status napi_get_instance_data(node_api_nogc_env env,
479
492
void** data);
480
493
```
481
494
@@ -577,6 +590,22 @@ when an instance of a native addon is unloaded. Notification of this event is
577
590
delivered through the callbacks given to [`napi_add_env_cleanup_hook`][] and
578
591
[`napi_set_instance_data`][].
579
592
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
+
580
609
### `napi_value`
581
610
582
611
This 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);
741
770
Unless for reasons discussed in [Object Lifetime Management][], creating a
742
771
handle and/or callback scope inside a `napi_callback` is not necessary.
743
772
744
- #### `napi_finalize `
773
+ #### `node_api_nogc_finalize `
745
774
746
775
<!-- YAML
747
- added: v8.0.0
748
- napiVersion: 1
776
+ added: REPLACEME
749
777
-->
750
778
779
+ > Stability: 1 - Experimental
780
+
751
781
Function pointer type for add-on provided functions that allow the user to be
752
782
notified 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
756
786
finding out when objects that have external data are collected.
757
787
758
788
```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);
762
792
```
763
793
764
794
Unless for reasons discussed in [Object Lifetime Management][], creating a
765
795
handle and/or callback scope inside the function body is not necessary.
766
796
767
797
Since 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.
770
803
771
804
In the case of [`node_api_create_external_string_latin1`][] and
772
805
[`node_api_create_external_string_utf16`][] the `env` parameter may be null,
@@ -775,11 +808,39 @@ shutdown.
775
808
776
809
Change History:
777
810
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
+
778
838
* experimental (`NAPI_EXPERIMENTAL` is defined):
779
839
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`.
783
844
784
845
#### `napi_async_execute_callback`
785
846
@@ -979,7 +1040,7 @@ napiVersion: 1
979
1040
980
1041
```c
981
1042
napi_status
982
- napi_get_last_error_info(napi_env env,
1043
+ napi_get_last_error_info(node_api_nogc_env env,
983
1044
const napi_extended_error_info** result);
984
1045
```
985
1046
@@ -1798,7 +1859,7 @@ napiVersion: 3
1798
1859
-->
1799
1860
1800
1861
```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,
1802
1863
napi_cleanup_hook fun,
1803
1864
void* arg);
1804
1865
```
@@ -1828,7 +1889,7 @@ napiVersion: 3
1828
1889
-->
1829
1890
1830
1891
```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,
1832
1893
void (*fun)(void* arg),
1833
1894
void* arg);
1834
1895
```
@@ -1857,7 +1918,7 @@ changes:
1857
1918
1858
1919
```c
1859
1920
NAPI_EXTERN napi_status napi_add_async_cleanup_hook(
1860
- napi_env env,
1921
+ node_api_nogc_env env,
1861
1922
napi_async_cleanup_hook hook,
1862
1923
void* arg,
1863
1924
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
2015
2076
for `NAPI_MODULE` and defining an `Init` function:
2016
2077
2017
2078
```c
2018
- NAPI_MODULE_INIT() {
2079
+ NAPI_MODULE_INIT(/* napi_env env, napi_value exports */ ) {
2019
2080
napi_value answer;
2020
2081
napi_status result;
2021
2082
@@ -2029,6 +2090,9 @@ NAPI_MODULE_INIT() {
2029
2090
}
2030
2091
```
2031
2092
2093
+ The parameters `env` and `exports` are provided to the body of the
2094
+ `NAPI_MODULE_INIT` macro.
2095
+
2032
2096
All Node-API addons are context-aware, meaning they may be loaded multiple
2033
2097
times. There are a few design considerations when declaring such a module.
2034
2098
The documentation on [context-aware addons][] provides more details.
@@ -5391,7 +5455,7 @@ napiVersion: 5
5391
5455
napi_status napi_add_finalizer(napi_env env,
5392
5456
napi_value js_object,
5393
5457
void* finalize_data,
5394
- napi_finalize finalize_cb,
5458
+ node_api_nogc_finalize finalize_cb,
5395
5459
void* finalize_hint,
5396
5460
napi_ref* result);
5397
5461
```
@@ -5429,7 +5493,7 @@ added: v18.19.0
5429
5493
> Stability: 1 - Experimental
5430
5494
5431
5495
```c
5432
- napi_status node_api_post_finalizer(napi_env env,
5496
+ napi_status node_api_post_finalizer(node_api_nogc_env env,
5433
5497
napi_finalize finalize_cb,
5434
5498
void* finalize_data,
5435
5499
void* finalize_hint);
@@ -5499,7 +5563,7 @@ Once created the async worker can be queued
5499
5563
for execution using the [`napi_queue_async_work`][] function:
5500
5564
5501
5565
```c
5502
- napi_status napi_queue_async_work(napi_env env,
5566
+ napi_status napi_queue_async_work(node_api_nogc_env env,
5503
5567
napi_async_work work);
5504
5568
```
5505
5569
@@ -5591,7 +5655,7 @@ napiVersion: 1
5591
5655
-->
5592
5656
5593
5657
```c
5594
- napi_status napi_queue_async_work(napi_env env,
5658
+ napi_status napi_queue_async_work(node_api_nogc_env env,
5595
5659
napi_async_work work);
5596
5660
```
5597
5661
@@ -5612,7 +5676,7 @@ napiVersion: 1
5612
5676
-->
5613
5677
5614
5678
```c
5615
- napi_status napi_cancel_async_work(napi_env env,
5679
+ napi_status napi_cancel_async_work(node_api_nogc_env env,
5616
5680
napi_async_work work);
5617
5681
```
5618
5682
@@ -5816,7 +5880,7 @@ typedef struct {
5816
5880
const char* release;
5817
5881
} napi_node_version;
5818
5882
5819
- napi_status napi_get_node_version(napi_env env,
5883
+ napi_status napi_get_node_version(node_api_nogc_env env,
5820
5884
const napi_node_version** version);
5821
5885
```
5822
5886
@@ -5839,7 +5903,7 @@ napiVersion: 1
5839
5903
-->
5840
5904
5841
5905
```c
5842
- napi_status napi_get_version(napi_env env,
5906
+ napi_status napi_get_version(node_api_nogc_env env,
5843
5907
uint32_t* result);
5844
5908
```
5845
5909
@@ -5872,7 +5936,7 @@ napiVersion: 1
5872
5936
-->
5873
5937
5874
5938
```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,
5876
5940
int64_t change_in_bytes,
5877
5941
int64_t* result);
5878
5942
```
@@ -6089,7 +6153,7 @@ napiVersion: 2
6089
6153
-->
6090
6154
6091
6155
```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,
6093
6157
struct uv_loop_s** loop);
6094
6158
```
6095
6159
@@ -6403,7 +6467,7 @@ napiVersion: 4
6403
6467
6404
6468
```c
6405
6469
NAPI_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);
6407
6471
```
6408
6472
6409
6473
* `[in] env`: The environment that the API is invoked under.
@@ -6429,7 +6493,7 @@ napiVersion: 4
6429
6493
6430
6494
```c
6431
6495
NAPI_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);
6433
6497
```
6434
6498
6435
6499
* `[in] env`: The environment that the API is invoked under.
@@ -6455,7 +6519,7 @@ napiVersion: 9
6455
6519
6456
6520
```c
6457
6521
NAPI_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);
6459
6523
6460
6524
```
6461
6525
@@ -6519,6 +6583,7 @@ the add-on's file name during loading.
6519
6583
[`Number.MIN_SAFE_INTEGER`]: https://tc39.github.io/ecma262/#sec-number.min_safe_integer
6520
6584
[`Worker`]: worker_threads.md#class-worker
6521
6585
[`async_hooks.executionAsyncResource()`]: async_hooks.md#async_hooksexecutionasyncresource
6586
+ [`build_with_cmake`]: https://github.com/nodejs/node-addon-examples/tree/main/build_with_cmake
6522
6587
[`global`]: globals.md#global
6523
6588
[`init` hooks]: async_hooks.md#initasyncid-type-triggerasyncid-resource
6524
6589
[`napi_add_async_cleanup_hook`]: #napi_add_async_cleanup_hook
@@ -6582,6 +6647,8 @@ the add-on's file name during loading.
6582
6647
[`node_api_create_external_string_latin1`]: #node_api_create_external_string_latin1
6583
6648
[`node_api_create_external_string_utf16`]: #node_api_create_external_string_utf16
6584
6649
[`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
6585
6652
[`node_api_throw_syntax_error`]: #node_api_throw_syntax_error
6586
6653
[`process.release`]: process.md#processrelease
6587
6654
[`uv_ref`]: https://docs.libuv.org/en/v1.x/handle.html#c.uv_ref
0 commit comments