11cb0ef41Sopenharmony_ci#include <node.h>
21cb0ef41Sopenharmony_ci#include <v8.h>
31cb0ef41Sopenharmony_ci#include <thread>  // NOLINT(build/c++11)
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ciusing node::Environment;
61cb0ef41Sopenharmony_ciusing v8::Context;
71cb0ef41Sopenharmony_ciusing v8::FunctionCallbackInfo;
81cb0ef41Sopenharmony_ciusing v8::HandleScope;
91cb0ef41Sopenharmony_ciusing v8::Isolate;
101cb0ef41Sopenharmony_ciusing v8::Local;
111cb0ef41Sopenharmony_ciusing v8::Maybe;
121cb0ef41Sopenharmony_ciusing v8::Object;
131cb0ef41Sopenharmony_ciusing v8::String;
141cb0ef41Sopenharmony_ciusing v8::Value;
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_cistatic std::thread interrupt_thread;
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_civoid ScheduleInterrupt(const FunctionCallbackInfo<Value>& args) {
191cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
201cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
211cb0ef41Sopenharmony_ci  Environment* env = node::GetCurrentEnvironment(isolate->GetCurrentContext());
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_ci  interrupt_thread = std::thread([=]() {
241cb0ef41Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::seconds(1));
251cb0ef41Sopenharmony_ci    node::RequestInterrupt(
261cb0ef41Sopenharmony_ci        env,
271cb0ef41Sopenharmony_ci        [](void* data) {
281cb0ef41Sopenharmony_ci          // Interrupt is called from JS thread.
291cb0ef41Sopenharmony_ci          interrupt_thread.join();
301cb0ef41Sopenharmony_ci          exit(0);
311cb0ef41Sopenharmony_ci        },
321cb0ef41Sopenharmony_ci        nullptr);
331cb0ef41Sopenharmony_ci  });
341cb0ef41Sopenharmony_ci}
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_civoid ScheduleInterruptWithJS(const FunctionCallbackInfo<Value>& args) {
371cb0ef41Sopenharmony_ci  Isolate* isolate = args.GetIsolate();
381cb0ef41Sopenharmony_ci  HandleScope handle_scope(isolate);
391cb0ef41Sopenharmony_ci  Environment* env = node::GetCurrentEnvironment(isolate->GetCurrentContext());
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  interrupt_thread = std::thread([=]() {
421cb0ef41Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::seconds(1));
431cb0ef41Sopenharmony_ci    node::RequestInterrupt(
441cb0ef41Sopenharmony_ci        env,
451cb0ef41Sopenharmony_ci        [](void* data) {
461cb0ef41Sopenharmony_ci          // Interrupt is called from JS thread.
471cb0ef41Sopenharmony_ci          interrupt_thread.join();
481cb0ef41Sopenharmony_ci          Isolate* isolate = static_cast<Isolate*>(data);
491cb0ef41Sopenharmony_ci          HandleScope handle_scope(isolate);
501cb0ef41Sopenharmony_ci          Local<Context> ctx = isolate->GetCurrentContext();
511cb0ef41Sopenharmony_ci          Local<String> str =
521cb0ef41Sopenharmony_ci              String::NewFromUtf8(isolate, "interrupt").ToLocalChecked();
531cb0ef41Sopenharmony_ci          // Calling into JS should abort immediately.
541cb0ef41Sopenharmony_ci          Maybe<bool> result = ctx->Global()->Set(ctx, str, str);
551cb0ef41Sopenharmony_ci          // Should not reach here.
561cb0ef41Sopenharmony_ci          if (!result.IsNothing()) {
571cb0ef41Sopenharmony_ci            // Called into JavaScript.
581cb0ef41Sopenharmony_ci            exit(2);
591cb0ef41Sopenharmony_ci          }
601cb0ef41Sopenharmony_ci          // Maybe exception thrown.
611cb0ef41Sopenharmony_ci          exit(1);
621cb0ef41Sopenharmony_ci        },
631cb0ef41Sopenharmony_ci        isolate);
641cb0ef41Sopenharmony_ci  });
651cb0ef41Sopenharmony_ci}
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_civoid init(Local<Object> exports) {
681cb0ef41Sopenharmony_ci  NODE_SET_METHOD(exports, "scheduleInterrupt", ScheduleInterrupt);
691cb0ef41Sopenharmony_ci  NODE_SET_METHOD(exports, "ScheduleInterruptWithJS", ScheduleInterruptWithJS);
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ciNODE_MODULE(NODE_GYP_MODULE_NAME, init)
73