11cb0ef41Sopenharmony_ci#include "node_api.h" 21cb0ef41Sopenharmony_ci#include "assert.h" 31cb0ef41Sopenharmony_ci#include "uv.h" 41cb0ef41Sopenharmony_ci#include <stdlib.h> 51cb0ef41Sopenharmony_ci#include "../../js-native-api/common.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_cistatic int cleanup_hook_count = 0; 81cb0ef41Sopenharmony_cistatic void MustNotCall(napi_async_cleanup_hook_handle hook, void* arg) { 91cb0ef41Sopenharmony_ci assert(0); 101cb0ef41Sopenharmony_ci} 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cistruct AsyncData { 131cb0ef41Sopenharmony_ci uv_async_t async; 141cb0ef41Sopenharmony_ci napi_env env; 151cb0ef41Sopenharmony_ci napi_async_cleanup_hook_handle handle; 161cb0ef41Sopenharmony_ci}; 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cistatic struct AsyncData* CreateAsyncData() { 191cb0ef41Sopenharmony_ci struct AsyncData* data = (struct AsyncData*) malloc(sizeof(struct AsyncData)); 201cb0ef41Sopenharmony_ci data->handle = NULL; 211cb0ef41Sopenharmony_ci return data; 221cb0ef41Sopenharmony_ci} 231cb0ef41Sopenharmony_ci 241cb0ef41Sopenharmony_cistatic void AfterCleanupHookTwo(uv_handle_t* handle) { 251cb0ef41Sopenharmony_ci cleanup_hook_count++; 261cb0ef41Sopenharmony_ci struct AsyncData* data = (struct AsyncData*) handle->data; 271cb0ef41Sopenharmony_ci napi_status status = napi_remove_async_cleanup_hook(data->handle); 281cb0ef41Sopenharmony_ci assert(status == napi_ok); 291cb0ef41Sopenharmony_ci free(data); 301cb0ef41Sopenharmony_ci} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cistatic void AfterCleanupHookOne(uv_async_t* async) { 331cb0ef41Sopenharmony_ci cleanup_hook_count++; 341cb0ef41Sopenharmony_ci uv_close((uv_handle_t*) async, AfterCleanupHookTwo); 351cb0ef41Sopenharmony_ci} 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_cistatic void AsyncCleanupHook(napi_async_cleanup_hook_handle handle, void* arg) { 381cb0ef41Sopenharmony_ci cleanup_hook_count++; 391cb0ef41Sopenharmony_ci struct AsyncData* data = (struct AsyncData*) arg; 401cb0ef41Sopenharmony_ci uv_loop_t* loop; 411cb0ef41Sopenharmony_ci napi_status status = napi_get_uv_event_loop(data->env, &loop); 421cb0ef41Sopenharmony_ci assert(status == napi_ok); 431cb0ef41Sopenharmony_ci int err = uv_async_init(loop, &data->async, AfterCleanupHookOne); 441cb0ef41Sopenharmony_ci assert(err == 0); 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ci data->async.data = data; 471cb0ef41Sopenharmony_ci data->handle = handle; 481cb0ef41Sopenharmony_ci uv_async_send(&data->async); 491cb0ef41Sopenharmony_ci} 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_cistatic void ObjectFinalizer(napi_env env, void* data, void* hint) { 521cb0ef41Sopenharmony_ci // AsyncCleanupHook and its subsequent callbacks are called twice. 531cb0ef41Sopenharmony_ci assert(cleanup_hook_count == 6); 541cb0ef41Sopenharmony_ci 551cb0ef41Sopenharmony_ci napi_ref* ref = data; 561cb0ef41Sopenharmony_ci NODE_API_CALL_RETURN_VOID(env, napi_delete_reference(env, *ref)); 571cb0ef41Sopenharmony_ci free(ref); 581cb0ef41Sopenharmony_ci} 591cb0ef41Sopenharmony_ci 601cb0ef41Sopenharmony_cistatic void CreateObjectWrap(napi_env env) { 611cb0ef41Sopenharmony_ci napi_value js_obj; 621cb0ef41Sopenharmony_ci napi_ref* ref = malloc(sizeof(*ref)); 631cb0ef41Sopenharmony_ci NODE_API_CALL_RETURN_VOID(env, napi_create_object(env, &js_obj)); 641cb0ef41Sopenharmony_ci NODE_API_CALL_RETURN_VOID( 651cb0ef41Sopenharmony_ci env, napi_wrap(env, js_obj, ref, ObjectFinalizer, NULL, ref)); 661cb0ef41Sopenharmony_ci // create a strong reference so that the finalizer is called at shutdown. 671cb0ef41Sopenharmony_ci NODE_API_CALL_RETURN_VOID(env, napi_reference_ref(env, *ref, NULL)); 681cb0ef41Sopenharmony_ci} 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_cistatic napi_value Init(napi_env env, napi_value exports) { 711cb0ef41Sopenharmony_ci // Reinitialize the static variable to be compatible with musl libc. 721cb0ef41Sopenharmony_ci cleanup_hook_count = 0; 731cb0ef41Sopenharmony_ci // Create object wrap before cleanup hooks. 741cb0ef41Sopenharmony_ci CreateObjectWrap(env); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci { 771cb0ef41Sopenharmony_ci struct AsyncData* data = CreateAsyncData(); 781cb0ef41Sopenharmony_ci data->env = env; 791cb0ef41Sopenharmony_ci napi_add_async_cleanup_hook(env, AsyncCleanupHook, data, &data->handle); 801cb0ef41Sopenharmony_ci } 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ci { 831cb0ef41Sopenharmony_ci struct AsyncData* data = CreateAsyncData(); 841cb0ef41Sopenharmony_ci data->env = env; 851cb0ef41Sopenharmony_ci napi_add_async_cleanup_hook(env, AsyncCleanupHook, data, NULL); 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci { 891cb0ef41Sopenharmony_ci napi_async_cleanup_hook_handle must_not_call_handle; 901cb0ef41Sopenharmony_ci napi_add_async_cleanup_hook( 911cb0ef41Sopenharmony_ci env, MustNotCall, NULL, &must_not_call_handle); 921cb0ef41Sopenharmony_ci napi_remove_async_cleanup_hook(must_not_call_handle); 931cb0ef41Sopenharmony_ci } 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci // Create object wrap after cleanup hooks. 961cb0ef41Sopenharmony_ci CreateObjectWrap(env); 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci return NULL; 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ciNAPI_MODULE(NODE_GYP_MODULE_NAME, Init) 102