44#include <stdlib.h>
55#include "../../js-native-api/common.h"
66
7+ static int cleanup_hook_count = 0 ;
78static void MustNotCall (napi_async_cleanup_hook_handle hook , void * arg ) {
89 assert (0 );
910}
@@ -21,17 +22,20 @@ static struct AsyncData* CreateAsyncData() {
2122}
2223
2324static void AfterCleanupHookTwo (uv_handle_t * handle ) {
25+ cleanup_hook_count ++ ;
2426 struct AsyncData * data = (struct AsyncData * ) handle -> data ;
2527 napi_status status = napi_remove_async_cleanup_hook (data -> handle );
2628 assert (status == napi_ok );
2729 free (data );
2830}
2931
3032static void AfterCleanupHookOne (uv_async_t * async ) {
33+ cleanup_hook_count ++ ;
3134 uv_close ((uv_handle_t * ) async , AfterCleanupHookTwo );
3235}
3336
3437static void AsyncCleanupHook (napi_async_cleanup_hook_handle handle , void * arg ) {
38+ cleanup_hook_count ++ ;
3539 struct AsyncData * data = (struct AsyncData * ) arg ;
3640 uv_loop_t * loop ;
3741 napi_status status = napi_get_uv_event_loop (data -> env , & loop );
@@ -44,7 +48,31 @@ static void AsyncCleanupHook(napi_async_cleanup_hook_handle handle, void* arg) {
4448 uv_async_send (& data -> async );
4549}
4650
51+ static void ObjectFinalizer (napi_env env , void * data , void * hint ) {
52+ // AsyncCleanupHook and its subsequent callbacks are called twice.
53+ assert (cleanup_hook_count == 6 );
54+
55+ napi_ref * ref = data ;
56+ NODE_API_CALL_RETURN_VOID (env , napi_delete_reference (env , * ref ));
57+ free (ref );
58+ }
59+
60+ static void CreateObjectWrap (napi_env env ) {
61+ napi_value js_obj ;
62+ napi_ref * ref = malloc (sizeof (* ref ));
63+ NODE_API_CALL_RETURN_VOID (env , napi_create_object (env , & js_obj ));
64+ NODE_API_CALL_RETURN_VOID (
65+ env , napi_wrap (env , js_obj , ref , ObjectFinalizer , NULL , ref ));
66+ // create a strong reference so that the finalizer is called at shutdown.
67+ NODE_API_CALL_RETURN_VOID (env , napi_reference_ref (env , * ref , NULL ));
68+ }
69+
4770static napi_value Init (napi_env env , napi_value exports ) {
71+ // Reinitialize the static variable to be compatible with musl libc.
72+ cleanup_hook_count = 0 ;
73+ // Create object wrap before cleanup hooks.
74+ CreateObjectWrap (env );
75+
4876 {
4977 struct AsyncData * data = CreateAsyncData ();
5078 data -> env = env ;
@@ -64,6 +92,9 @@ static napi_value Init(napi_env env, napi_value exports) {
6492 napi_remove_async_cleanup_hook (must_not_call_handle );
6593 }
6694
95+ // Create object wrap after cleanup hooks.
96+ CreateObjectWrap (env );
97+
6798 return NULL ;
6899}
69100
0 commit comments