• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <node.h>
2 #include <v8.h>
3 #include <uv.h>
4 
5 #if defined _WIN32
6 #include <windows.h>
7 #else
8 #include <unistd.h>
9 #endif
10 
11 
12 struct async_req {
13   uv_work_t req;
14   int input;
15   int output;
16   v8::Isolate* isolate;
17   v8::Global<v8::Function> callback;
18   node::async_context context;
19 };
20 
DoAsync(uv_work_t * r)21 void DoAsync(uv_work_t* r) {
22   async_req* req = reinterpret_cast<async_req*>(r->data);
23   // Simulate CPU intensive process...
24 #if defined _WIN32
25   Sleep(1000);
26 #else
27   sleep(1);
28 #endif
29   req->output = req->input * 2;
30 }
31 
32 template <bool use_makecallback>
AfterAsync(uv_work_t * r)33 void AfterAsync(uv_work_t* r) {
34   async_req* req = reinterpret_cast<async_req*>(r->data);
35   v8::Isolate* isolate = req->isolate;
36   v8::HandleScope scope(isolate);
37 
38   v8::Local<v8::Value> argv[2] = {
39     v8::Null(isolate),
40     v8::Integer::New(isolate, req->output)
41   };
42 
43   v8::TryCatch try_catch(isolate);
44 
45   v8::Local<v8::Object> global = isolate->GetCurrentContext()->Global();
46   v8::Local<v8::Function> callback =
47       v8::Local<v8::Function>::New(isolate, req->callback);
48 
49   if (use_makecallback) {
50     v8::Local<v8::Value> ret =
51         node::MakeCallback(isolate, global, callback, 2, argv, req->context)
52             .ToLocalChecked();
53     // This should be changed to an empty handle.
54     assert(!ret.IsEmpty());
55   } else {
56     callback->Call(isolate->GetCurrentContext(),
57                    global, 2, argv).ToLocalChecked();
58   }
59 
60   // None of the following operations should allocate handles into this scope.
61   v8::SealHandleScope seal_handle_scope(isolate);
62   // cleanup
63   node::EmitAsyncDestroy(isolate, req->context);
64   delete req;
65 
66   if (try_catch.HasCaught()) {
67     node::FatalException(isolate, try_catch);
68   }
69 }
70 
71 template <bool use_makecallback>
Method(const v8::FunctionCallbackInfo<v8::Value> & args)72 void Method(const v8::FunctionCallbackInfo<v8::Value>& args) {
73   v8::Isolate* isolate = args.GetIsolate();
74 
75   async_req* req = new async_req;
76   req->req.data = req;
77 
78   req->input = args[0].As<v8::Integer>()->Value();
79   req->output = 0;
80   req->isolate = isolate;
81   req->context = node::EmitAsyncInit(isolate, v8::Object::New(isolate), "test");
82 
83   v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(args[1]);
84   req->callback.Reset(isolate, callback);
85 
86   uv_queue_work(node::GetCurrentEventLoop(isolate),
87                 &req->req,
88                 DoAsync,
89                 (uv_after_work_cb)AfterAsync<use_makecallback>);
90 }
91 
init(v8::Local<v8::Object> exports,v8::Local<v8::Object> module)92 void init(v8::Local<v8::Object> exports, v8::Local<v8::Object> module) {
93   NODE_SET_METHOD(exports, "runCall", Method<false>);
94   NODE_SET_METHOD(exports, "runMakeCallback", Method<true>);
95 }
96 
97 NODE_MODULE(NODE_GYP_MODULE_NAME, init)
98