Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

n-api: Context for custom async operations #15189

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
213 changes: 133 additions & 80 deletions doc/api/n-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ The documentation for N-API is structured as follows:
* [Working with JavaScript Properties][]
* [Working with JavaScript Functions][]
* [Object Wrap][]
* [Asynchronous Operations][]
* [Simple Asynchronous Operations][]
* [Custom Asynchronous Operations][]
* [Promises][]

The N-API is a C API that ensures ABI stability across Node.js versions
Expand Down Expand Up @@ -263,7 +264,7 @@ It is intended only for logging purposes.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status
napi_status
napi_get_last_error_info(napi_env env,
const napi_extended_error_info** result);
```
Expand Down Expand Up @@ -514,8 +515,8 @@ This API returns a JavaScript RangeError with the text provided.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result);
napi_status napi_get_and_clear_last_exception(napi_env env,
napi_value* result);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -530,7 +531,7 @@ This API returns true if an exception is pending.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_is_exception_pending(napi_env env, bool* result);
napi_status napi_is_exception_pending(napi_env env, bool* result);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -550,7 +551,7 @@ thrown to immediately terminate the process.
added: v8.2.0
-->
```C
NAPI_EXTERN NAPI_NO_RETURN void napi_fatal_error(const char* location, const char* message);
NAPI_NO_RETURN void napi_fatal_error(const char* location, const char* message);
```

- `[in] location`: Optional location at which the error occurred.
Expand Down Expand Up @@ -717,10 +718,10 @@ reverse order from which they were created.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_escape_handle(napi_env env,
napi_escapable_handle_scope scope,
napi_value escapee,
napi_value* result);
napi_status napi_escape_handle(napi_env env,
napi_escapable_handle_scope scope,
napi_value escapee,
napi_value* result);
```

- `[in] env`: The environment that the API is invoked under.
Expand Down Expand Up @@ -1468,10 +1469,10 @@ of the ECMAScript Language Specification.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_create_string_latin1(napi_env env,
const char* str,
size_t length,
napi_value* result);
napi_status napi_create_string_latin1(napi_env env,
const char* str,
size_t length,
napi_value* result);
```

- `[in] env`: The environment that the API is invoked under.
Expand Down Expand Up @@ -1801,11 +1802,11 @@ JavaScript Number
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_get_value_string_latin1(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result)
napi_status napi_get_value_string_latin1(napi_env env,
napi_value value,
char* buf,
size_t bufsize,
size_t* result)
```

- `[in] env`: The environment that the API is invoked under.
Expand Down Expand Up @@ -2780,8 +2781,8 @@ in as arguments to the function.
Returns `napi_ok` if the API succeeded.

This method allows a JavaScript function object to be called from a native
add-on. This is an primary mechanism of calling back *from* the add-on's
native code *into* JavaScript. For special cases like calling into JavaScript
add-on. This is the primary mechanism of calling back *from* the add-on's
native code *into* JavaScript. For the special case of calling into JavaScript
after an async operation, see [`napi_make_callback`][].

A sample use case might look as follows. Consider the following JavaScript
Expand Down Expand Up @@ -2993,39 +2994,6 @@ status = napi_new_instance(env, constructor, argc, argv, &value);

Returns `napi_ok` if the API succeeded.

### *napi_make_callback*
<!-- YAML
added: v8.0.0
-->
```C
napi_status napi_make_callback(napi_env env,
napi_value recv,
napi_value func,
int argc,
const napi_value* argv,
napi_value* result)
```

- `[in] env`: The environment that the API is invoked under.
- `[in] recv`: The `this` object passed to the called function.
- `[in] func`: `napi_value` representing the JavaScript function
to be invoked.
- `[in] argc`: The count of elements in the `argv` array.
- `[in] argv`: Array of JavaScript values as `napi_value`
representing the arguments to the function.
- `[out] result`: `napi_value` representing the JavaScript object returned.

Returns `napi_ok` if the API succeeded.

This method allows a JavaScript function object to be called from a native
add-on. This API is similar to `napi_call_function`. However, it is used to call
*from* native code back *into* JavaScript *after* returning from an async
operation (when there is no other script on the stack). It is a fairly simple
wrapper around `node::MakeCallback`.

For an example on how to use `napi_make_callback`, see the section on
[Asynchronous Operations][].

## Object Wrap

N-API offers a way to "wrap" C++ classes and instances so that the class
Expand Down Expand Up @@ -3204,7 +3172,7 @@ restoring the JavaScript object's prototype chain. If a finalize callback was
associated with the wrapping, it will no longer be called when the JavaScript
object becomes garbage-collected.

## Asynchronous Operations
## Simple Asynchronous Operations

Addon modules often need to leverage async helpers from libuv as part of their
implementation. This allows them to schedule work to be executed asynchronously
Expand Down Expand Up @@ -3240,8 +3208,8 @@ Once created the async worker can be queued
for execution using the [`napi_queue_async_work`][] function:

```C
NAPI_EXTERN napi_status napi_queue_async_work(napi_env env,
napi_async_work work);
napi_status napi_queue_async_work(napi_env env,
napi_async_work work);
```

[`napi_cancel_async_work`][] can be used if the work needs
Expand All @@ -3257,7 +3225,6 @@ callback invocation, even when it was cancelled.
added: v8.0.0
-->
```C
NAPI_EXTERN
napi_status napi_create_async_work(napi_env env,
napi_async_execute_callback execute,
napi_async_complete_callback complete,
Expand Down Expand Up @@ -3286,8 +3253,8 @@ required.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_delete_async_work(napi_env env,
napi_async_work work);
napi_status napi_delete_async_work(napi_env env,
napi_async_work work);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3302,8 +3269,8 @@ This API frees a previously allocated work object.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_queue_async_work(napi_env env,
napi_async_work work);
napi_status napi_queue_async_work(napi_env env,
napi_async_work work);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3319,8 +3286,8 @@ for execution.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_cancel_async_work(napi_env env,
napi_async_work work);
napi_status napi_cancel_async_work(napi_env env,
napi_async_work work);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3335,6 +3302,92 @@ the `complete` callback will be invoked with a status value of
`napi_cancelled`. The work should not be deleted before the `complete`
callback invocation, even if it has been successfully cancelled.

## Custom Asynchronous Operations
The simple asynchronous work APIs above may not be appropriate for every
scenario, because with those the async execution still happens on the main
event loop. When using any other async mechanism, the following APIs are
necessary to ensure an async operation is properly tracked by the runtime.

### *napi_async_init**
<!-- YAML
added: REPLACEME
-->
```C
napi_status napi_async_init(napi_env env,
napi_value async_resource,
const char* async_resource_name,
napi_async_context* result)
```

- `[in] env`: The environment that the API is invoked under.
- `[in] async_resource`: An optional object associated with the async work
that will be passed to possible async_hooks [`init` hooks][].
- `[in] async_resource_name`: An identifier for the kind of resource that is
being provided for diagnostic information exposed by the `async_hooks` API.
- `[out] result`: The initialized async context.

Returns `napi_ok` if the API succeeded.

### *napi_async_destroy**
<!-- YAML
added: REPLACEME
-->
```C
napi_status napi_async_destroy(napi_env env,
napi_async_context async_context);
```

- `[in] env`: The environment that the API is invoked under.
- `[in] async_context`: The async context to be destroyed.

Returns `napi_ok` if the API succeeded.

### *napi_make_callback*
<!-- YAML
added: v8.0.0
changes:
- version: REPLACEME
description: Added `async_context` parameter.
-->
```C
napi_status napi_make_callback(napi_env env,
napi_async_context async_context,
napi_value recv,
napi_value func,
int argc,
const napi_value* argv,
napi_value* result)
```

- `[in] env`: The environment that the API is invoked under.
- `[in] async_context`: Context for the async operation that is
invoking the callback. This should normally be a value previously
obtained from [`napi_async_init`][]. However `NULL` is also allowed,
which indicates the current async context (if any) is to be used
for the callback.
- `[in] recv`: The `this` object passed to the called function.
- `[in] func`: `napi_value` representing the JavaScript function
to be invoked.
- `[in] argc`: The count of elements in the `argv` array.
- `[in] argv`: Array of JavaScript values as `napi_value`
representing the arguments to the function.
- `[out] result`: `napi_value` representing the JavaScript object returned.

Returns `napi_ok` if the API succeeded.

This method allows a JavaScript function object to be called from a native
add-on. This API is similar to `napi_call_function`. However, it is used to call
*from* native code back *into* JavaScript *after* returning from an async
operation (when there is no other script on the stack). It is a fairly simple
wrapper around `node::MakeCallback`.

Note it is NOT necessary to use `napi_make_callback` from within a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/NOT/*not*

`napi_async_complete_callback`; in that situation the callback's async
context has already been set up, so a direct call to `napi_call_function`
is sufficient and appropriate. Use of the `napi_make_callback` function
may be required when implementing custom async behavior that does not use
`napi_create_async_work`.

## Version Management

### napi_get_node_version
Expand All @@ -3350,7 +3403,6 @@ typedef struct {
const char* release;
} napi_node_version;

NAPI_EXTERN
napi_status napi_get_node_version(napi_env env,
const napi_node_version** version);
```
Expand All @@ -3371,8 +3423,8 @@ The returned buffer is statically allocated and does not need to be freed.
added: v8.0.0
-->
```C
NAPI_EXTERN napi_status napi_get_version(napi_env env,
uint32_t* result);
napi_status napi_get_version(napi_env env,
uint32_t* result);
```

- `[in] env`: The environment that the API is invoked under.
Expand Down Expand Up @@ -3455,9 +3507,9 @@ deferred = NULL;
added: REPLACEME
-->
```C
NAPI_EXTERN napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise);
napi_status napi_create_promise(napi_env env,
napi_deferred* deferred,
napi_value* promise);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3475,9 +3527,9 @@ This API creates a deferred object and a JavaScript promise.
added: REPLACEME
-->
```C
NAPI_EXTERN napi_status napi_resolve_deferred(napi_env env,
napi_deferred deferred,
napi_value resolution);
napi_status napi_resolve_deferred(napi_env env,
napi_deferred deferred,
napi_value resolution);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3498,9 +3550,9 @@ The deferred object is freed upon successful completion.
added: REPLACEME
-->
```C
NAPI_EXTERN napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection);
napi_status napi_reject_deferred(napi_env env,
napi_deferred deferred,
napi_value rejection);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3521,9 +3573,9 @@ The deferred object is freed upon successful completion.
added: REPLACEME
-->
```C
NAPI_EXTERN napi_status napi_is_promise(napi_env env,
napi_value promise,
bool* is_promise);
napi_status napi_is_promise(napi_env env,
napi_value promise,
bool* is_promise);
```

- `[in] env`: The environment that the API is invoked under.
Expand All @@ -3532,7 +3584,8 @@ NAPI_EXTERN napi_status napi_is_promise(napi_env env,
object - that is, a promise object created by the underlying engine.

[Promises]: #n_api_promises
[Asynchronous Operations]: #n_api_asynchronous_operations
[Simple Asynchronous Operations]: #n_api_asynchronous_operations
[Custom Asynchronous Operations]: #n_api_custom_asynchronous_operations
[Basic N-API Data Types]: #n_api_basic_n_api_data_types
[ECMAScript Language Specification]: https://tc39.github.io/ecma262/
[Error Handling]: #n_api_error_handling
Expand Down
Loading