11cb0ef41Sopenharmony_ci#include <node.h>
21cb0ef41Sopenharmony_ci#include <v8.h>
31cb0ef41Sopenharmony_ci#include <uv.h>
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciusing v8::Context;
61cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
71cb0ef41Sopenharmony_ciusing v8::Isolate;
81cb0ef41Sopenharmony_ciusing v8::Local;
91cb0ef41Sopenharmony_ciusing v8::Value;
101cb0ef41Sopenharmony_ci
111cb0ef41Sopenharmony_ci// Give these things names in the public namespace so that we can see
121cb0ef41Sopenharmony_ci// them show up in symbol dumps.
131cb0ef41Sopenharmony_civoid CloseCallback(uv_handle_t* handle) {}
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciclass ExampleOwnerClass {
161cb0ef41Sopenharmony_ci public:
171cb0ef41Sopenharmony_ci  virtual ~ExampleOwnerClass();
181cb0ef41Sopenharmony_ci};
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ci// Do not inline this into the class, because that may remove the virtual
211cb0ef41Sopenharmony_ci// table when LTO is used, and with it the symbol for which we grep the process
221cb0ef41Sopenharmony_ci// output in test/abort/test-addon-uv-handle-leak.
231cb0ef41Sopenharmony_ci// When the destructor is not inlined, the compiler will have to assume that it,
241cb0ef41Sopenharmony_ci// and the vtable, is part of what this compilation unit exports, and keep them.
251cb0ef41Sopenharmony_ciExampleOwnerClass::~ExampleOwnerClass() {}
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciExampleOwnerClass example_instance;
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_civoid LeakHandle(const FunctionCallbackInfo<Value>& args) {
301cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
311cb0ef41Sopenharmony_ci  Local<Context> context = isolate->GetCurrentContext();
321cb0ef41Sopenharmony_ci  uv_loop_t* loop = node::GetCurrentEventLoop(isolate);
331cb0ef41Sopenharmony_ci  assert(loop != nullptr);
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_ci  uv_timer_t* leaked_timer = new uv_timer_t;
361cb0ef41Sopenharmony_ci  leaked_timer->close_cb = CloseCallback;
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  if (args[0]->IsNumber()) {
391cb0ef41Sopenharmony_ci    leaked_timer->data =
401cb0ef41Sopenharmony_ci        reinterpret_cast<void*>(args[0]->IntegerValue(context).FromJust());
411cb0ef41Sopenharmony_ci  } else {
421cb0ef41Sopenharmony_ci    leaked_timer->data = &example_instance;
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  uv_timer_init(loop, leaked_timer);
461cb0ef41Sopenharmony_ci  uv_timer_start(leaked_timer, [](uv_timer_t*){}, 1000, 1000);
471cb0ef41Sopenharmony_ci  uv_unref(reinterpret_cast<uv_handle_t*>(leaked_timer));
481cb0ef41Sopenharmony_ci}
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci// This module gets loaded multiple times in some tests so it must support that.
511cb0ef41Sopenharmony_ciNODE_MODULE_INIT(/*exports, module, context*/) {
521cb0ef41Sopenharmony_ci  NODE_SET_METHOD(exports, "leakHandle", LeakHandle);
531cb0ef41Sopenharmony_ci}
54