1#include "node.h" 2#include "v8.h" 3#include "uv.h" 4 5#include <assert.h> 6#include <vector> 7#include <memory> 8 9namespace { 10 11void 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 35static 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 48static 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 70void 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 77NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) 78