1 #include "node.h"
2
3 #include <assert.h>
4 #include <vector>
5
6 namespace {
7
8 using node::AsyncResource;
9 using v8::External;
10 using v8::Function;
11 using v8::FunctionCallbackInfo;
12 using v8::Integer;
13 using v8::Isolate;
14 using v8::Local;
15 using v8::MaybeLocal;
16 using v8::Object;
17 using v8::String;
18 using v8::Value;
19
20 int custom_async_resource_destructor_calls = 0;
21
22 class CustomAsyncResource : public AsyncResource {
23 public:
CustomAsyncResource(Isolate * isolate,Local<Object> resource)24 CustomAsyncResource(Isolate* isolate, Local<Object> resource)
25 : AsyncResource(isolate, resource, "CustomAsyncResource") {}
~CustomAsyncResource()26 ~CustomAsyncResource() {
27 custom_async_resource_destructor_calls++;
28 }
29 };
30
CreateAsyncResource(const FunctionCallbackInfo<Value> & args)31 void 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
DestroyAsyncResource(const FunctionCallbackInfo<Value> & args)46 void 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
CallViaFunction(const FunctionCallbackInfo<Value> & args)52 void 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
CallViaString(const FunctionCallbackInfo<Value> & args)69 void 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
CallViaUtf8Name(const FunctionCallbackInfo<Value> & args)82 void 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
GetAsyncId(const FunctionCallbackInfo<Value> & args)92 void 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
GetTriggerAsyncId(const FunctionCallbackInfo<Value> & args)98 void 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
GetResource(const FunctionCallbackInfo<Value> & args)104 void 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
RunSubclassTest(const FunctionCallbackInfo<Value> & args)110 void 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
Initialize(Local<Object> exports)120 void 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
134 NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
135