#include "node.h" #include #include namespace { using node::AsyncResource; using v8::External; using v8::Function; using v8::FunctionCallbackInfo; using v8::Integer; using v8::Isolate; using v8::Local; using v8::MaybeLocal; using v8::Object; using v8::String; using v8::Value; int custom_async_resource_destructor_calls = 0; class CustomAsyncResource : public AsyncResource { public: CustomAsyncResource(Isolate* isolate, Local resource) : AsyncResource(isolate, resource, "CustomAsyncResource") {} ~CustomAsyncResource() { custom_async_resource_destructor_calls++; } }; void CreateAsyncResource(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(args[0]->IsObject()); AsyncResource* r; if (args[1]->IsInt32()) { r = new AsyncResource(isolate, args[0].As(), "foobär", args[1].As()->Value()); } else { r = new AsyncResource(isolate, args[0].As(), "foobär"); } args.GetReturnValue().Set( External::New(isolate, static_cast(r))); } void DestroyAsyncResource(const FunctionCallbackInfo& args) { assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); delete r; } void CallViaFunction(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); Local name = String::NewFromUtf8(isolate, "methöd", v8::NewStringType::kNormal) .ToLocalChecked(); Local fn = r->get_resource()->Get(isolate->GetCurrentContext(), name) .ToLocalChecked(); assert(fn->IsFunction()); Local arg = Integer::New(isolate, 42); MaybeLocal ret = r->MakeCallback(fn.As(), 1, &arg); args.GetReturnValue().Set(ret.FromMaybe(Local())); } void CallViaString(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); Local name = String::NewFromUtf8(isolate, "methöd", v8::NewStringType::kNormal) .ToLocalChecked(); Local arg = Integer::New(isolate, 42); MaybeLocal ret = r->MakeCallback(name, 1, &arg); args.GetReturnValue().Set(ret.FromMaybe(Local())); } void CallViaUtf8Name(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); Local arg = Integer::New(isolate, 42); MaybeLocal ret = r->MakeCallback("methöd", 1, &arg); args.GetReturnValue().Set(ret.FromMaybe(Local())); } void GetAsyncId(const FunctionCallbackInfo& args) { assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); args.GetReturnValue().Set(r->get_async_id()); } void GetTriggerAsyncId(const FunctionCallbackInfo& args) { assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); args.GetReturnValue().Set(r->get_trigger_async_id()); } void GetResource(const FunctionCallbackInfo& args) { assert(args[0]->IsExternal()); auto r = static_cast(args[0].As()->Value()); args.GetReturnValue().Set(r->get_resource()); } void RunSubclassTest(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); Local obj = Object::New(isolate); assert(custom_async_resource_destructor_calls == 0); CustomAsyncResource* resource = new CustomAsyncResource(isolate, obj); delete static_cast(resource); assert(custom_async_resource_destructor_calls == 1); } void Initialize(Local exports) { NODE_SET_METHOD(exports, "createAsyncResource", CreateAsyncResource); NODE_SET_METHOD(exports, "destroyAsyncResource", DestroyAsyncResource); NODE_SET_METHOD(exports, "callViaFunction", CallViaFunction); NODE_SET_METHOD(exports, "callViaString", CallViaString); NODE_SET_METHOD(exports, "callViaUtf8Name", CallViaUtf8Name); NODE_SET_METHOD(exports, "getAsyncId", GetAsyncId); NODE_SET_METHOD(exports, "getTriggerAsyncId", GetTriggerAsyncId); NODE_SET_METHOD(exports, "getResource", GetResource); NODE_SET_METHOD(exports, "runSubclassTest", RunSubclassTest); } } // anonymous namespace NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)