Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit32906dd

Browse files
gabrielschulhofrichardlau
authored andcommitted
node-api: segregate nogc APIs from rest via type system
We define a new type called `node_api_nogc_env` as the `const` versionof `napi_env` and `node_api_nogc_finalize` as a variant of`napi_finalize` that accepts a `node_api_nogc_env` as its firstargument.We then modify those APIs which do not affect GC state as accepting a`node_api_nogc_env`. APIs accepting finalizer callbacks are modified toaccept `node_api_nogc_finalize` callbacks. Thus, the only way to attacha `napi_finalize` callback, wherein Node-APIs affecting GC state may becalled is to call `node_api_post_finalizer` from a`node_api_nogc_finalize` callback.In keeping with the process of introducing new Node-APIs, this featureis guarded by `NAPI_EXPERIMENTAL`. Since this feature modifies APIsalready marked as stable, it is additionally guared by`NODE_API_EXPERIMENTAL_NOGC_ENV`, so as to provide a further buffer toadoption. Nevertheless, both guards must be removed upon releasing anew version of Node-API.PR-URL:#50060Reviewed-By: Chengzhong Wu <legendecas@gmail.com>Reviewed-By: Vladimir Morozov <vmorozov@microsoft.com>Reviewed-By: Michael Dawson <midawson@redhat.com>Backport-PR-URL:#51804(cherry picked from commit7a216d5)
1 parent1aa71c2 commit32906dd

File tree

16 files changed

+368
-146
lines changed

16 files changed

+368
-146
lines changed

‎doc/api/n-api.md

Lines changed: 103 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ it still gets the benefits of the ABI stability provided by the C API.
7878
When using `node-addon-api` instead of the C APIs, start with the API [docs][]
7979
for `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
8282
an excellent orientation and tips for developers just getting started with
8383
Node-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

177177
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.
179180

180181
### Uploading precompiled binaries
181182

@@ -237,6 +238,18 @@ Some of the Node-API surface is experimental and requires explicit opt-in:
237238
In this case the entire API surface, including any experimental APIs, will be
238239
available 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

242255
Node-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
577590
delivered 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

582611
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);
741770
Unless for reasons discussed in [Object Lifetime Management][], creating a
742771
handle 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+
751781
Function pointer type for add-on provided functions that allow the user to be
752782
notified when externally-owned data is ready to be cleaned up because the
753-
objectwith whichit was associated with has been garbage-collected. The user
754-
must providea function satisfying the following signature which would get
755-
called upon theobject'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
756786
finding 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

764794
Unless for reasons discussed in [Object Lifetime Management][], creating a
765795
handle and/or callback scope inside the function body is not necessary.
766796

767797
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.
770803

771804
In 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

776809
Change 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
9811042
napi_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
18591920
NAPI_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
20152076
for `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+
20322096
All Node-API addons are context-aware, meaning they may be loaded multiple
20332097
times. There are a few design considerations when declaring such a module.
20342098
The documentation on [context-aware addons][] provides more details.
@@ -5391,7 +5455,7 @@ napiVersion: 5
53915455
napi_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
54995563
for 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
64056469
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);
64076471
```
64086472

64096473
* `[in] env`: The environment that the API is invoked under.
@@ -6429,7 +6493,7 @@ napiVersion: 4
64296493

64306494
```c
64316495
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);
64336497
```
64346498

64356499
* `[in] env`: The environment that the API is invoked under.
@@ -6455,7 +6519,7 @@ napiVersion: 9
64556519

64566520
```c
64576521
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);
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

‎doc/contributing/adding-new-napi-api.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,16 @@ Node-API.
5151
to the decision to take an API out of experimental status.
5252
* The API**must** be implemented in a Node.js implementation with an
5353
alternate VM.
54+
55+
Since the adoption of the policy whereby moving to a later version of Node-API
56+
from an earlier version may entail rework of existing code, it is possible to
57+
introduce modifications to already-released Node-APIs, as long as the
58+
modifications affect neither the ABI nor the API of earlier versions. Such
59+
modifications**must** be accompanied by an opt-out flag. This provides add-on
60+
maintainers who take advantage of the initial compile-time flag to track
61+
impending changes to Node-API with
62+
63+
* a quick fix to the breakage caused,
64+
* a notification that such breakage is impending, and thus
65+
* a buffer to adoption above and beyond the one provided by the initial
66+
compile-time flag.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp