1#include "node.h" 2 3#include <assert.h> 4#include <vector> 5 6namespace { 7 8using node::AsyncResource; 9using v8::External; 10using v8::Function; 11using v8::FunctionCallbackInfo; 12using v8::Integer; 13using v8::Isolate; 14using v8::Local; 15using v8::MaybeLocal; 16using v8::Object; 17using v8::String; 18using v8::Value; 19 20int custom_async_resource_destructor_calls = 0; 21 22class CustomAsyncResource : public AsyncResource { 23 public: 24 CustomAsyncResource(Isolate* isolate, Local<Object> resource) 25 : AsyncResource(isolate, resource, "CustomAsyncResource") {} 26 ~CustomAsyncResource() { 27 custom_async_resource_destructor_calls++; 28 } 29}; 30 31void CreateAsyncResource(const FunctionCallbackInfo<Value>& args) { 32 Isolate* isolate = args.GetIsolate(); 33 assert(args[0]->IsObject()); 34 AsyncResource* r; 35 if (args[1]->IsInt32()) { 36 r = new AsyncResource(isolate, args[0].As<Object>(), "foobär", 37 args[1].As<Integer>()->Value()); 38 } else { 39 r = new AsyncResource(isolate, args[0].As<Object>(), "foobär"); 40 } 41 42 args.GetReturnValue().Set( 43 External::New(isolate, static_cast<void*>(r))); 44} 45 46void DestroyAsyncResource(const FunctionCallbackInfo<Value>& args) { 47 assert(args[0]->IsExternal()); 48 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 49 delete r; 50} 51 52void CallViaFunction(const FunctionCallbackInfo<Value>& args) { 53 Isolate* isolate = args.GetIsolate(); 54 assert(args[0]->IsExternal()); 55 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 56 57 Local<String> name = 58 String::NewFromUtf8(isolate, "methöd").ToLocalChecked(); 59 Local<Value> fn = 60 r->get_resource()->Get(isolate->GetCurrentContext(), name) 61 .ToLocalChecked(); 62 assert(fn->IsFunction()); 63 64 Local<Value> arg = Integer::New(isolate, 42); 65 MaybeLocal<Value> ret = r->MakeCallback(fn.As<Function>(), 1, &arg); 66 args.GetReturnValue().Set(ret.FromMaybe(Local<Value>())); 67} 68 69void CallViaString(const FunctionCallbackInfo<Value>& args) { 70 Isolate* isolate = args.GetIsolate(); 71 assert(args[0]->IsExternal()); 72 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 73 74 Local<String> name = 75 String::NewFromUtf8(isolate, "methöd").ToLocalChecked(); 76 77 Local<Value> arg = Integer::New(isolate, 42); 78 MaybeLocal<Value> ret = r->MakeCallback(name, 1, &arg); 79 args.GetReturnValue().Set(ret.FromMaybe(Local<Value>())); 80} 81 82void CallViaUtf8Name(const FunctionCallbackInfo<Value>& args) { 83 Isolate* isolate = args.GetIsolate(); 84 assert(args[0]->IsExternal()); 85 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 86 87 Local<Value> arg = Integer::New(isolate, 42); 88 MaybeLocal<Value> ret = r->MakeCallback("methöd", 1, &arg); 89 args.GetReturnValue().Set(ret.FromMaybe(Local<Value>())); 90} 91 92void GetAsyncId(const FunctionCallbackInfo<Value>& args) { 93 assert(args[0]->IsExternal()); 94 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 95 args.GetReturnValue().Set(r->get_async_id()); 96} 97 98void GetTriggerAsyncId(const FunctionCallbackInfo<Value>& args) { 99 assert(args[0]->IsExternal()); 100 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 101 args.GetReturnValue().Set(r->get_trigger_async_id()); 102} 103 104void GetResource(const FunctionCallbackInfo<Value>& args) { 105 assert(args[0]->IsExternal()); 106 auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value()); 107 args.GetReturnValue().Set(r->get_resource()); 108} 109 110void RunSubclassTest(const FunctionCallbackInfo<Value>& args) { 111 Isolate* isolate = args.GetIsolate(); 112 Local<Object> obj = Object::New(isolate); 113 114 assert(custom_async_resource_destructor_calls == 0); 115 CustomAsyncResource* resource = new CustomAsyncResource(isolate, obj); 116 delete static_cast<AsyncResource*>(resource); 117 assert(custom_async_resource_destructor_calls == 1); 118} 119 120void Initialize(Local<Object> exports) { 121 NODE_SET_METHOD(exports, "createAsyncResource", CreateAsyncResource); 122 NODE_SET_METHOD(exports, "destroyAsyncResource", DestroyAsyncResource); 123 NODE_SET_METHOD(exports, "callViaFunction", CallViaFunction); 124 NODE_SET_METHOD(exports, "callViaString", CallViaString); 125 NODE_SET_METHOD(exports, "callViaUtf8Name", CallViaUtf8Name); 126 NODE_SET_METHOD(exports, "getAsyncId", GetAsyncId); 127 NODE_SET_METHOD(exports, "getTriggerAsyncId", GetTriggerAsyncId); 128 NODE_SET_METHOD(exports, "getResource", GetResource); 129 NODE_SET_METHOD(exports, "runSubclassTest", RunSubclassTest); 130} 131 132} // anonymous namespace 133 134NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize) 135