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