1 #include "node.h"
2 #include "v8.h"
3 #include "uv.h"
4
5 #include <assert.h>
6 #include <vector>
7 #include <memory>
8
9 namespace {
10
RunInCallbackScope(const v8::FunctionCallbackInfo<v8::Value> & args)11 void RunInCallbackScope(const v8::FunctionCallbackInfo<v8::Value>& args) {
12 v8::Isolate* isolate = args.GetIsolate();
13
14 assert(args.Length() == 4);
15 assert(args[0]->IsObject());
16 assert(args[1]->IsNumber());
17 assert(args[2]->IsNumber());
18 assert(args[3]->IsFunction());
19
20 node::async_context asyncContext = {
21 args[1].As<v8::Number>()->Value(),
22 args[2].As<v8::Number>()->Value()
23 };
24
25 node::CallbackScope scope(isolate, args[0].As<v8::Object>(), asyncContext);
26 v8::Local<v8::Function> fn = args[3].As<v8::Function>();
27
28 v8::MaybeLocal<v8::Value> ret =
29 fn->Call(isolate->GetCurrentContext(), args[0], 0, nullptr);
30
31 if (!ret.IsEmpty())
32 args.GetReturnValue().Set(ret.ToLocalChecked());
33 }
34
Callback(uv_work_t * req,int ignored)35 static void Callback(uv_work_t* req, int ignored) {
36 v8::Isolate* isolate = v8::Isolate::GetCurrent();
37 v8::HandleScope scope(isolate);
38 node::CallbackScope callback_scope(isolate, v8::Object::New(isolate),
39 node::async_context{0, 0});
40 std::unique_ptr<v8::Global<v8::Promise::Resolver>> persistent {
41 static_cast<v8::Global<v8::Promise::Resolver>*>(req->data) };
42 v8::Local<v8::Promise::Resolver> local = persistent->Get(isolate);
43 local->Resolve(isolate->GetCurrentContext(),
44 v8::Undefined(isolate)).ToChecked();
45 delete req;
46 }
47
TestResolveAsync(const v8::FunctionCallbackInfo<v8::Value> & args)48 static void TestResolveAsync(const v8::FunctionCallbackInfo<v8::Value>& args) {
49 v8::Isolate* isolate = args.GetIsolate();
50
51 v8::Global<v8::Promise::Resolver>* persistent =
52 new v8::Global<v8::Promise::Resolver>(
53 isolate,
54 v8::Promise::Resolver::New(
55 isolate->GetCurrentContext()).ToLocalChecked());
56
57 uv_work_t* req = new uv_work_t;
58 req->data = static_cast<void*>(persistent);
59
60 uv_queue_work(node::GetCurrentEventLoop(isolate),
61 req,
62 [](uv_work_t*) {},
63 Callback);
64
65 v8::Local<v8::Promise::Resolver> local = persistent->Get(isolate);
66
67 args.GetReturnValue().Set(local->GetPromise());
68 }
69
Initialize(v8::Local<v8::Object> exports)70 void Initialize(v8::Local<v8::Object> exports) {
71 NODE_SET_METHOD(exports, "runInCallbackScope", RunInCallbackScope);
72 NODE_SET_METHOD(exports, "testResolveAsync", TestResolveAsync);
73 }
74
75 } // anonymous namespace
76
77 NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
78