11cb0ef41Sopenharmony_ci#include <node.h>
21cb0ef41Sopenharmony_ci#include <uv.h>
31cb0ef41Sopenharmony_ci#include <assert.h>
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_civoid MustNotCall(void* arg, void(*cb)(void*), void* cbarg) {
61cb0ef41Sopenharmony_ci  assert(0);
71cb0ef41Sopenharmony_ci}
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_cistruct AsyncData {
101cb0ef41Sopenharmony_ci  uv_async_t async;
111cb0ef41Sopenharmony_ci  v8::Isolate* isolate;
121cb0ef41Sopenharmony_ci  node::AsyncCleanupHookHandle handle;
131cb0ef41Sopenharmony_ci  void (*done_cb)(void*);
141cb0ef41Sopenharmony_ci  void* done_arg;
151cb0ef41Sopenharmony_ci};
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_civoid AsyncCleanupHook(void* arg, void(*cb)(void*), void* cbarg) {
181cb0ef41Sopenharmony_ci  AsyncData* data = static_cast<AsyncData*>(arg);
191cb0ef41Sopenharmony_ci  uv_loop_t* loop = node::GetCurrentEventLoop(data->isolate);
201cb0ef41Sopenharmony_ci  assert(loop != nullptr);
211cb0ef41Sopenharmony_ci  int err = uv_async_init(loop, &data->async, [](uv_async_t* async) {
221cb0ef41Sopenharmony_ci    AsyncData* data = static_cast<AsyncData*>(async->data);
231cb0ef41Sopenharmony_ci    // Attempting to remove the cleanup hook here should be a no-op since it
241cb0ef41Sopenharmony_ci    // has already been started.
251cb0ef41Sopenharmony_ci    node::RemoveEnvironmentCleanupHook(std::move(data->handle));
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci    uv_close(reinterpret_cast<uv_handle_t*>(async), [](uv_handle_t* handle) {
281cb0ef41Sopenharmony_ci      AsyncData* data = static_cast<AsyncData*>(handle->data);
291cb0ef41Sopenharmony_ci      data->done_cb(data->done_arg);
301cb0ef41Sopenharmony_ci      delete data;
311cb0ef41Sopenharmony_ci    });
321cb0ef41Sopenharmony_ci  });
331cb0ef41Sopenharmony_ci  assert(err == 0);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  data->async.data = data;
361cb0ef41Sopenharmony_ci  data->done_cb = cb;
371cb0ef41Sopenharmony_ci  data->done_arg = cbarg;
381cb0ef41Sopenharmony_ci  uv_async_send(&data->async);
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_civoid Initialize(v8::Local<v8::Object> exports,
421cb0ef41Sopenharmony_ci                v8::Local<v8::Value> module,
431cb0ef41Sopenharmony_ci                v8::Local<v8::Context> context) {
441cb0ef41Sopenharmony_ci  AsyncData* data = new AsyncData();
451cb0ef41Sopenharmony_ci  data->isolate = context->GetIsolate();
461cb0ef41Sopenharmony_ci  auto handle = node::AddEnvironmentCleanupHook(
471cb0ef41Sopenharmony_ci      context->GetIsolate(),
481cb0ef41Sopenharmony_ci      AsyncCleanupHook,
491cb0ef41Sopenharmony_ci      data);
501cb0ef41Sopenharmony_ci  data->handle = std::move(handle);
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  auto must_not_call_handle = node::AddEnvironmentCleanupHook(
531cb0ef41Sopenharmony_ci      context->GetIsolate(),
541cb0ef41Sopenharmony_ci      MustNotCall,
551cb0ef41Sopenharmony_ci      nullptr);
561cb0ef41Sopenharmony_ci  node::RemoveEnvironmentCleanupHook(std::move(must_not_call_handle));
571cb0ef41Sopenharmony_ci}
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ciNODE_MODULE_CONTEXT_AWARE(NODE_GYP_MODULE_NAME, Initialize)
60