• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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