◐ Shell
clean mode source ↗

node-api: segregate nogc APIs from rest via type system · nodejs/node@32906dd

@@ -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`.

808081-

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][].

176176177177

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.

179180180181

### 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.

239240241+

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

241254242255

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"

400413401-

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

-->

444457445458

```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

-->

476489477490

```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`][].

579592593+

### `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`

581610582611

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.

743772744-

#### `napi_finalize`

773+

#### `node_api_nogc_finalize`

745774746775

<!-- YAML

747-

added: v8.0.0

748-

napiVersion: 1

776+

added: REPLACEME

749777

-->

750778779+

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

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

756786

finding out when objects that have external data are collected.

757787758788

```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

```

763793764794

Unless for reasons discussed in [Object Lifetime Management][], creating a

765795

handle and/or callback scope inside the function body is not necessary.

766796767797

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.

770803771804

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.

775808776809

Change History:

777810811+

* 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):

779839780-

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`.

783844784845

#### `napi_async_execute_callback`

785846

@@ -979,7 +1040,7 @@ napiVersion: 1

97910409801041

```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

-->

1799186018001861

```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

-->

1829189018301891

```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:

1857191818581919

```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:

2016207720172078

```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

```

203120922093+

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

5430549454315495

```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:

5500556455015565

```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

-->

5592565655935657

```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

-->

5613567756145678

```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;

581858825819-

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

-->

5840590458415905

```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

-->

5873593758745938

```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

-->

6090615460916155

```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

6403646764046468

```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

```

6408647264096473

* `[in] env`: The environment that the API is invoked under.

@@ -6429,7 +6493,7 @@ napiVersion: 4

6429649364306494

```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

```

6434649864356499

* `[in] env`: The environment that the API is invoked under.

@@ -6455,7 +6519,7 @@ napiVersion: 9

6455651964566520

```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);

6459652364606524

```

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