| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b091681 commit 3c32fe0
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -623,6 +623,15 @@ typedef struct { | |||
| 623 | 623 | } napi_type_tag; | |
| 624 | 624 | ``` | |
| 625 | 625 | ||
| 626 | + #### napi_async_cleanup_hook_handle | ||
| 627 | + <!-- YAML | ||
| 628 | + added: REPLACEME | ||
| 629 | + --> | ||
| 630 | + | ||
| 631 | + An opaque value returned by [`napi_add_async_cleanup_hook`][]. It must be passed | ||
| 632 | + to [`napi_remove_async_cleanup_hook`][] when the chain of asynchronous cleanup | ||
| 633 | + events completes. | ||
| 634 | + | ||
| 626 | 635 | ### N-API callback types | |
| 627 | 636 | ||
| 628 | 637 | #### napi_callback_info | |
@@ -751,6 +760,30 @@ typedef void (*napi_threadsafe_function_call_js)(napi_env env, | |||
| 751 | 760 | Unless for reasons discussed in [Object Lifetime Management][], creating a | |
| 752 | 761 | handle and/or callback scope inside the function body is not necessary. | |
| 753 | 762 | ||
| 763 | + #### napi_async_cleanup_hook | ||
| 764 | + <!-- YAML | ||
| 765 | + added: REPLACEME | ||
| 766 | + --> | ||
| 767 | + | ||
| 768 | + Function pointer used with [`napi_add_async_cleanup_hook`][]. It will be called | ||
| 769 | + when the environment is being torn down. | ||
| 770 | + | ||
| 771 | + Callback functions must satisfy the following signature: | ||
| 772 | + | ||
| 773 | + ```c | ||
| 774 | + typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle, | ||
| 775 | + void* data); | ||
| 776 | + ``` | ||
| 777 | + | ||
| 778 | + * `[in] handle`: The handle that must be passed to | ||
| 779 | + [`napi_remove_async_cleanup_hook`][] after completion of the asynchronous | ||
| 780 | + cleanup. | ||
| 781 | + * `[in] data`: The data that was passed to [`napi_add_async_cleanup_hook`][]. | ||
| 782 | + | ||
| 783 | + The body of the function should initiate the asynchronous cleanup actions at the | ||
| 784 | + end of which `handle` must be passed in a call to | ||
| 785 | + [`napi_remove_async_cleanup_hook`][]. | ||
| 786 | + | ||
| 754 | 787 | ## Error handling | |
| 755 | 788 | ||
| 756 | 789 | N-API uses both return values and JavaScript exceptions for error handling. | |
@@ -1580,22 +1613,33 @@ with `napi_add_env_cleanup_hook`, otherwise the process will abort. | |||
| 1580 | 1613 | #### napi_add_async_cleanup_hook | |
| 1581 | 1614 | <!-- YAML | |
| 1582 | 1615 | added: v14.8.0 | |
| 1616 | + changes: | ||
| 1617 | + - version: REPLACEME | ||
| 1618 | + pr-url: https://github.com/nodejs/node/pull/34819 | ||
| 1619 | + description: Changed signature of the `hook` callback. | ||
| 1583 | 1620 | --> | |
| 1584 | 1621 | ||
| 1585 | 1622 | > Stability: 1 - Experimental | |
| 1586 | 1623 | ||
| 1587 | 1624 | ```c | |
| 1588 | 1625 | NAPI_EXTERN napi_status napi_add_async_cleanup_hook( | |
| 1589 | 1626 | napi_env env, | |
| 1590 | - void (*fun)(void* arg, void(* cb)(void*), void* cbarg), | ||
| 1627 | + napi_async_cleanup_hook hook, | ||
| 1591 | 1628 | void* arg, | |
| 1592 | 1629 | napi_async_cleanup_hook_handle* remove_handle); | |
| 1593 | 1630 | ``` | |
| 1594 | 1631 | ||
| 1595 | - Registers `fun` as a function to be run with the `arg` parameter once the | ||
| 1596 | - current Node.js environment exits. Unlike [`napi_add_env_cleanup_hook`][], | ||
| 1597 | - the hook is allowed to be asynchronous in this case, and must invoke the passed | ||
| 1598 | - `cb()` function with `cbarg` once all asynchronous activity is finished. | ||
| 1632 | + * `[in] env`: The environment that the API is invoked under. | ||
| 1633 | + * `[in] hook`: The function pointer to call at environment teardown. | ||
| 1634 | + * `[in] arg`: The pointer to pass to `hook` when it gets called. | ||
| 1635 | + * `[out] remove_handle`: Optional handle that refers to the asynchronous cleanup | ||
| 1636 | + hook. | ||
| 1637 | + | ||
| 1638 | + Registers `hook`, which is a function of type [`napi_async_cleanup_hook`][], as | ||
| 1639 | + a function to be run with the `remove_handle` and `arg` parameters once the | ||
| 1640 | + current Node.js environment exits. | ||
| 1641 | + | ||
| 1642 | + Unlike [`napi_add_env_cleanup_hook`][], the hook is allowed to be asynchronous. | ||
| 1599 | 1643 | ||
| 1600 | 1644 | Otherwise, behavior generally matches that of [`napi_add_env_cleanup_hook`][]. | |
| 1601 | 1645 | ||
@@ -1608,19 +1652,25 @@ is being torn down anyway. | |||
| 1608 | 1652 | #### napi_remove_async_cleanup_hook | |
| 1609 | 1653 | <!-- YAML | |
| 1610 | 1654 | added: v14.8.0 | |
| 1655 | + changes: | ||
| 1656 | + - version: REPLACEME | ||
| 1657 | + pr-url: https://github.com/nodejs/node/pull/34819 | ||
| 1658 | + description: Removed `env` parameter. | ||
| 1611 | 1659 | --> | |
| 1612 | 1660 | ||
| 1613 | 1661 | > Stability: 1 - Experimental | |
| 1614 | 1662 | ||
| 1615 | 1663 | ```c | |
| 1616 | 1664 | NAPI_EXTERN napi_status napi_remove_async_cleanup_hook( | |
| 1617 | - napi_env env, | ||
| 1618 | 1665 | napi_async_cleanup_hook_handle remove_handle); | |
| 1619 | 1666 | ``` | |
| 1620 | 1667 | ||
| 1668 | + * `[in] remove_handle`: The handle to an asynchronous cleanup hook that was | ||
| 1669 | + created with [`napi_add_async_cleanup_hook`][]. | ||
| 1670 | + | ||
| 1621 | 1671 | Unregisters the cleanup hook corresponding to `remove_handle`. This will prevent | |
| 1622 | 1672 | the hook from being executed, unless it has already started executing. | |
| 1623 | - This must be called on any `napi_async_cleanup_hook_handle` value retrieved | ||
| 1673 | + This must be called on any `napi_async_cleanup_hook_handle` value obtained | ||
| 1624 | 1674 | from [`napi_add_async_cleanup_hook`][]. | |
| 1625 | 1675 | ||
| 1626 | 1676 | ## Module registration | |
@@ -5757,6 +5807,7 @@ This API may only be called from the main thread. | |||
| 5757 | 5807 | [`napi_add_async_cleanup_hook`]: #n_api_napi_add_async_cleanup_hook | |
| 5758 | 5808 | [`napi_add_env_cleanup_hook`]: #n_api_napi_add_env_cleanup_hook | |
| 5759 | 5809 | [`napi_add_finalizer`]: #n_api_napi_add_finalizer | |
| 5810 | + [`napi_async_cleanup_hook`]: #n_api_napi_async_cleanup_hook | ||
| 5760 | 5811 | [`napi_async_complete_callback`]: #n_api_napi_async_complete_callback | |
| 5761 | 5812 | [`napi_async_init`]: #n_api_napi_async_init | |
| 5762 | 5813 | [`napi_callback`]: #n_api_napi_callback | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -519,41 +519,68 @@ napi_status napi_remove_env_cleanup_hook(napi_env env, | |||
| 519 | 519 | } | |
| 520 | 520 | ||
| 521 | 521 | struct napi_async_cleanup_hook_handle__ { | |
| 522 | - node::AsyncCleanupHookHandle handle; | ||
| 522 | + napi_async_cleanup_hook_handle__(napi_env env, | ||
| 523 | + napi_async_cleanup_hook user_hook, | ||
| 524 | + void* user_data): | ||
| 525 | + env_(env), | ||
| 526 | + user_hook_(user_hook), | ||
| 527 | + user_data_(user_data) { | ||
| 528 | + handle_ = node::AddEnvironmentCleanupHook(env->isolate, Hook, this); | ||
| 529 | + env->Ref(); | ||
| 530 | + } | ||
| 531 | + | ||
| 532 | + ~napi_async_cleanup_hook_handle__() { | ||
| 533 | + node::RemoveEnvironmentCleanupHook(std::move(handle_)); | ||
| 534 | + if (done_cb_ != nullptr) | ||
| 535 | + done_cb_(done_data_); | ||
| 536 | + | ||
| 537 | + // Release the `env` handle asynchronously since it would be surprising if | ||
| 538 | + // a call to a N-API function would destroy `env` synchronously. | ||
| 539 | + static_cast<node_napi_env>(env_)->node_env() | ||
| 540 | + ->SetImmediate([env = env_](node::Environment*) { env->Unref(); }); | ||
| 541 | + } | ||
| 542 | + | ||
| 543 | + static void Hook(void* data, void (*done_cb)(void*), void* done_data) { | ||
| 544 | + auto handle = static_cast<napi_async_cleanup_hook_handle__*>(data); | ||
| 545 | + handle->done_cb_ = done_cb; | ||
| 546 | + handle->done_data_ = done_data; | ||
| 547 | + handle->user_hook_(handle, handle->user_data_); | ||
| 548 | + } | ||
| 549 | + | ||
| 550 | + node::AsyncCleanupHookHandle handle_; | ||
| 551 | + napi_env env_ = nullptr; | ||
| 552 | + napi_async_cleanup_hook user_hook_ = nullptr; | ||
| 553 | + void* user_data_ = nullptr; | ||
| 554 | + void (*done_cb_)(void*) = nullptr; | ||
| 555 | + void* done_data_ = nullptr; | ||
| 523 | 556 | }; | |
| 524 | 557 | ||
| 525 | 558 | napi_status napi_add_async_cleanup_hook( | |
| 526 | 559 | napi_env env, | |
| 527 | - void (*fun)(void* arg, void(* cb)(void*), void* cbarg), | ||
| 560 | + napi_async_cleanup_hook hook, | ||
| 528 | 561 | void* arg, | |
| 529 | 562 | napi_async_cleanup_hook_handle* remove_handle) { | |
| 530 | 563 | CHECK_ENV(env); | |
| 531 | - CHECK_ARG(env, fun); | ||
| 564 | + CHECK_ARG(env, hook); | ||
| 532 | 565 | ||
| 533 | - auto handle = node::AddEnvironmentCleanupHook(env->isolate, fun, arg); | ||
| 534 | - if (remove_handle != nullptr) { | ||
| 535 | - *remove_handle = new napi_async_cleanup_hook_handle__ { std::move(handle) }; | ||
| 536 | - env->Ref(); | ||
| 537 | - } | ||
| 566 | + napi_async_cleanup_hook_handle__* handle = | ||
| 567 | + new napi_async_cleanup_hook_handle__(env, hook, arg); | ||
| 568 | + | ||
| 569 | + if (remove_handle != nullptr) | ||
| 570 | + *remove_handle = handle; | ||
| 538 | 571 | ||
| 539 | 572 | return napi_clear_last_error(env); | |
| 540 | 573 | } | |
| 541 | 574 | ||
| 542 | 575 | napi_status napi_remove_async_cleanup_hook( | |
| 543 | - napi_env env, | ||
| 544 | 576 | napi_async_cleanup_hook_handle remove_handle) { | |
| 545 | - CHECK_ENV(env); | ||
| 546 | - CHECK_ARG(env, remove_handle); | ||
| 547 | 577 | ||
| 548 | - node::RemoveEnvironmentCleanupHook(std::move(remove_handle->handle)); | ||
| 549 | - delete remove_handle; | ||
| 578 | + if (remove_handle == nullptr) | ||
| 579 | + return napi_invalid_arg; | ||
| 550 | 580 | ||
| 551 | - // Release the `env` handle asynchronously since it would be surprising if | ||
| 552 | - // a call to a N-API function would destroy `env` synchronously. | ||
| 553 | - static_cast<node_napi_env>(env)->node_env() | ||
| 554 | - ->SetImmediate([env](node::Environment*) { env->Unref(); }); | ||
| 581 | + delete remove_handle; | ||
| 555 | 582 | ||
| 556 | - return napi_clear_last_error(env); | ||
| 583 | + return napi_ok; | ||
| 557 | 584 | } | |
| 558 | 585 | ||
| 559 | 586 | napi_status napi_fatal_exception(napi_env env, napi_value err) { | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -254,12 +254,11 @@ napi_ref_threadsafe_function(napi_env env, napi_threadsafe_function func); | |||
| 254 | 254 | ||
| 255 | 255 | NAPI_EXTERN napi_status napi_add_async_cleanup_hook( | |
| 256 | 256 | napi_env env, | |
| 257 | - void (*fun)(void* arg, void(* cb)(void*), void* cbarg), | ||
| 257 | + napi_async_cleanup_hook hook, | ||
| 258 | 258 | void* arg, | |
| 259 | 259 | napi_async_cleanup_hook_handle* remove_handle); | |
| 260 | 260 | ||
| 261 | 261 | NAPI_EXTERN napi_status napi_remove_async_cleanup_hook( | |
| 262 | - napi_env env, | ||
| 263 | 262 | napi_async_cleanup_hook_handle remove_handle); | |
| 264 | 263 | ||
| 265 | 264 | #endif // NAPI_EXPERIMENTAL | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -43,6 +43,8 @@ typedef struct { | |||
| 43 | 43 | ||
| 44 | 44 | #ifdef NAPI_EXPERIMENTAL | |
| 45 | 45 | typedef struct napi_async_cleanup_hook_handle__* napi_async_cleanup_hook_handle; | |
| 46 | + typedef void (*napi_async_cleanup_hook)(napi_async_cleanup_hook_handle handle, | ||
| 47 | + void* data); | ||
| 46 | 48 | #endif // NAPI_EXPERIMENTAL | |
| 47 | 49 | ||
| 48 | 50 | #endif // SRC_NODE_API_TYPES_H_ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,44 +5,34 @@ | |||
| 5 | 5 | #include <stdlib.h> | |
| 6 | 6 | #include "../../js-native-api/common.h" | |
| 7 | 7 | ||
| 8 | - void MustNotCall(void* arg, void(*cb)(void*), void* cbarg) { | ||
| 8 | + static void MustNotCall(napi_async_cleanup_hook_handle hook, void* arg) { | ||
| 9 | 9 | assert(0); | |
| 10 | 10 | } | |
| 11 | 11 | ||
| 12 | 12 | struct AsyncData { | |
| 13 | 13 | uv_async_t async; | |
| 14 | 14 | napi_env env; | |
| 15 | 15 | napi_async_cleanup_hook_handle handle; | |
| 16 | - void (*done_cb)(void*); | ||
| 17 | - void* done_arg; | ||
| 18 | 16 | }; | |
| 19 | 17 | ||
| 20 | - struct AsyncData* CreateAsyncData() { | ||
| 18 | + static struct AsyncData* CreateAsyncData() { | ||
| 21 | 19 | struct AsyncData* data = (struct AsyncData*) malloc(sizeof(struct AsyncData)); | |
| 22 | 20 | data->handle = NULL; | |
| 23 | 21 | return data; | |
| 24 | 22 | } | |
| 25 | 23 | ||
| 26 | - void AfterCleanupHookTwo(uv_handle_t* handle) { | ||
| 24 | + static void AfterCleanupHookTwo(uv_handle_t* handle) { | ||
| 27 | 25 | struct AsyncData* data = (struct AsyncData*) handle->data; | |
| 28 | - data->done_cb(data->done_arg); | ||
| 26 | + napi_status status = napi_remove_async_cleanup_hook(data->handle); | ||
| 27 | + assert(status == napi_ok); | ||
| 29 | 28 | free(data); | |
| 30 | 29 | } | |
| 31 | 30 | ||
| 32 | - void AfterCleanupHookOne(uv_async_t* async) { | ||
| 33 | - struct AsyncData* data = (struct AsyncData*) async->data; | ||
| 34 | - if (data->handle != NULL) { | ||
| 35 | - // Verify that removing the hook is okay between starting and finishing | ||
| 36 | - // of its execution. | ||
| 37 | - napi_status status = | ||
| 38 | - napi_remove_async_cleanup_hook(data->env, data->handle); | ||
| 39 | - assert(status == napi_ok); | ||
| 40 | - } | ||
| 41 | - | ||
| 31 | + static void AfterCleanupHookOne(uv_async_t* async) { | ||
| 42 | 32 | uv_close((uv_handle_t*) async, AfterCleanupHookTwo); | |
| 43 | 33 | } | |
| 44 | 34 | ||
| 45 | - void AsyncCleanupHook(void* arg, void(*cb)(void*), void* cbarg) { | ||
| 35 | + static void AsyncCleanupHook(napi_async_cleanup_hook_handle handle, void* arg) { | ||
| 46 | 36 | struct AsyncData* data = (struct AsyncData*) arg; | |
| 47 | 37 | uv_loop_t* loop; | |
| 48 | 38 | napi_status status = napi_get_uv_event_loop(data->env, &loop); | |
@@ -51,12 +41,11 @@ void AsyncCleanupHook(void* arg, void(*cb)(void*), void* cbarg) { | |||
| 51 | 41 | assert(err == 0); | |
| 52 | 42 | ||
| 53 | 43 | data->async.data = data; | |
| 54 | - data->done_cb = cb; | ||
| 55 | - data->done_arg = cbarg; | ||
| 44 | + data->handle = handle; | ||
| 56 | 45 | uv_async_send(&data->async); | |
| 57 | 46 | } | |
| 58 | 47 | ||
| 59 | - napi_value Init(napi_env env, napi_value exports) { | ||
| 48 | + static napi_value Init(napi_env env, napi_value exports) { | ||
| 60 | 49 | { | |
| 61 | 50 | struct AsyncData* data = CreateAsyncData(); | |
| 62 | 51 | data->env = env; | |
@@ -73,7 +62,7 @@ napi_value Init(napi_env env, napi_value exports) { | |||
| 73 | 62 | napi_async_cleanup_hook_handle must_not_call_handle; | |
| 74 | 63 | napi_add_async_cleanup_hook( | |
| 75 | 64 | env, MustNotCall, NULL, &must_not_call_handle); | |
| 76 | - napi_remove_async_cleanup_hook(env, must_not_call_handle); | ||
| 65 | + napi_remove_async_cleanup_hook(must_not_call_handle); | ||
| 77 | 66 | } | |
| 78 | 67 | ||
| 79 | 68 | return NULL; | |
| Back | FazBrowse Home | New Git URL |
0 commit comments