11cb0ef41Sopenharmony_ci#include <node.h>
21cb0ef41Sopenharmony_ci#include <v8.h>
31cb0ef41Sopenharmony_ci#include <uv.h>
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cistruct async_req {
61cb0ef41Sopenharmony_ci  uv_work_t req;
71cb0ef41Sopenharmony_ci  int input;
81cb0ef41Sopenharmony_ci  int output;
91cb0ef41Sopenharmony_ci  v8::Isolate* isolate;
101cb0ef41Sopenharmony_ci  v8::Global<v8::Function> callback;
111cb0ef41Sopenharmony_ci  node::async_context context;
121cb0ef41Sopenharmony_ci};
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_civoid DoAsync(uv_work_t* r) {
151cb0ef41Sopenharmony_ci  async_req* req = reinterpret_cast<async_req*>(r->data);
161cb0ef41Sopenharmony_ci  // Simulate CPU intensive process...
171cb0ef41Sopenharmony_ci  uv_sleep(1000);
181cb0ef41Sopenharmony_ci  req->output = req->input * 2;
191cb0ef41Sopenharmony_ci}
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_citemplate <bool use_makecallback>
221cb0ef41Sopenharmony_civoid AfterAsync(uv_work_t* r) {
231cb0ef41Sopenharmony_ci  async_req* req = reinterpret_cast<async_req*>(r->data);
241cb0ef41Sopenharmony_ci  v8::Isolate* isolate = req->isolate;
251cb0ef41Sopenharmony_ci  v8::HandleScope scope(isolate);
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  v8::Local<v8::Value> argv[2] = {
281cb0ef41Sopenharmony_ci    v8::Null(isolate),
291cb0ef41Sopenharmony_ci    v8::Integer::New(isolate, req->output)
301cb0ef41Sopenharmony_ci  };
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_ci  v8::TryCatch try_catch(isolate);
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global();
351cb0ef41Sopenharmony_ci  v8::Local<v8::Function> callback =
361cb0ef41Sopenharmony_ci      v8::Local<v8::Function>::New(isolate, req->callback);
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  if (use_makecallback) {
391cb0ef41Sopenharmony_ci    v8::Local<v8::Value> ret =
401cb0ef41Sopenharmony_ci        node::MakeCallback(isolate, global, callback, 2, argv, req->context)
411cb0ef41Sopenharmony_ci            .ToLocalChecked();
421cb0ef41Sopenharmony_ci    // This should be changed to an empty handle.
431cb0ef41Sopenharmony_ci    assert(!ret.IsEmpty());
441cb0ef41Sopenharmony_ci  } else {
451cb0ef41Sopenharmony_ci    callback->Call(isolate->GetCurrentContext(),
461cb0ef41Sopenharmony_ci                   global, 2, argv).ToLocalChecked();
471cb0ef41Sopenharmony_ci  }
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci  // None of the following operations should allocate handles into this scope.
501cb0ef41Sopenharmony_ci  v8::SealHandleScope seal_handle_scope(isolate);
511cb0ef41Sopenharmony_ci  // cleanup
521cb0ef41Sopenharmony_ci  node::EmitAsyncDestroy(isolate, req->context);
531cb0ef41Sopenharmony_ci  delete req;
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_ci  if (try_catch.HasCaught()) {
561cb0ef41Sopenharmony_ci    node::FatalException(isolate, try_catch);
571cb0ef41Sopenharmony_ci  }
581cb0ef41Sopenharmony_ci}
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_citemplate <bool use_makecallback>
611cb0ef41Sopenharmony_civoid Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
621cb0ef41Sopenharmony_ci  v8::Isolate* isolate = args.GetIsolate();
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  async_req* req = new async_req;
651cb0ef41Sopenharmony_ci  req->req.data = req;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci  req->input = args[0].As<v8::Integer>()->Value();
681cb0ef41Sopenharmony_ci  req->output = 0;
691cb0ef41Sopenharmony_ci  req->isolate = isolate;
701cb0ef41Sopenharmony_ci  req->context = node::EmitAsyncInit(isolate, v8::Object::New(isolate), "test");
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
731cb0ef41Sopenharmony_ci  req->callback.Reset(isolate, callback);
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  uv_queue_work(node::GetCurrentEventLoop(isolate),
761cb0ef41Sopenharmony_ci                &req->req,
771cb0ef41Sopenharmony_ci                DoAsync,
781cb0ef41Sopenharmony_ci                (uv_after_work_cb)AfterAsync<use_makecallback>);
791cb0ef41Sopenharmony_ci}
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_civoid init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {
821cb0ef41Sopenharmony_ci  NODE_SET_METHOD(exports, "runCall", Method<false>);
831cb0ef41Sopenharmony_ci  NODE_SET_METHOD(exports, "runMakeCallback", Method<true>);
841cb0ef41Sopenharmony_ci}
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ciNODE_MODULE(NODE_GYP_MODULE_NAME, init)
87