• 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", v8::NewStringType::kNormal)
59       .ToLocalChecked();
60   Local<Value> fn =
61       r->get_resource()->Get(isolate->GetCurrentContext(), name)
62       .ToLocalChecked();
63   assert(fn->IsFunction());
64 
65   Local<Value> arg = Integer::New(isolate, 42);
66   MaybeLocal<Value> ret = r->MakeCallback(fn.As<Function>(), 1, &arg);
67   args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
68 }
69 
CallViaString(const FunctionCallbackInfo<Value> & args)70 void CallViaString(const FunctionCallbackInfo<Value>& args) {
71   Isolate* isolate = args.GetIsolate();
72   assert(args[0]->IsExternal());
73   auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
74 
75   Local<String> name =
76       String::NewFromUtf8(isolate, "methöd", v8::NewStringType::kNormal)
77       .ToLocalChecked();
78 
79   Local<Value> arg = Integer::New(isolate, 42);
80   MaybeLocal<Value> ret = r->MakeCallback(name, 1, &arg);
81   args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
82 }
83 
CallViaUtf8Name(const FunctionCallbackInfo<Value> & args)84 void CallViaUtf8Name(const FunctionCallbackInfo<Value>& args) {
85   Isolate* isolate = args.GetIsolate();
86   assert(args[0]->IsExternal());
87   auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
88 
89   Local<Value> arg = Integer::New(isolate, 42);
90   MaybeLocal<Value> ret = r->MakeCallback("methöd", 1, &arg);
91   args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
92 }
93 
GetAsyncId(const FunctionCallbackInfo<Value> & args)94 void GetAsyncId(const FunctionCallbackInfo<Value>& args) {
95   assert(args[0]->IsExternal());
96   auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
97   args.GetReturnValue().Set(r->get_async_id());
98 }
99 
GetTriggerAsyncId(const FunctionCallbackInfo<Value> & args)100 void GetTriggerAsyncId(const FunctionCallbackInfo<Value>& args) {
101   assert(args[0]->IsExternal());
102   auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
103   args.GetReturnValue().Set(r->get_trigger_async_id());
104 }
105 
GetResource(const FunctionCallbackInfo<Value> & args)106 void GetResource(const FunctionCallbackInfo<Value>& args) {
107   assert(args[0]->IsExternal());
108   auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
109   args.GetReturnValue().Set(r->get_resource());
110 }
111 
RunSubclassTest(const FunctionCallbackInfo<Value> & args)112 void RunSubclassTest(const FunctionCallbackInfo<Value>& args) {
113   Isolate* isolate = args.GetIsolate();
114   Local<Object> obj = Object::New(isolate);
115 
116   assert(custom_async_resource_destructor_calls == 0);
117   CustomAsyncResource* resource = new CustomAsyncResource(isolate, obj);
118   delete static_cast<AsyncResource*>(resource);
119   assert(custom_async_resource_destructor_calls == 1);
120 }
121 
Initialize(Local<Object> exports)122 void Initialize(Local<Object> exports) {
123   NODE_SET_METHOD(exports, "createAsyncResource", CreateAsyncResource);
124   NODE_SET_METHOD(exports, "destroyAsyncResource", DestroyAsyncResource);
125   NODE_SET_METHOD(exports, "callViaFunction", CallViaFunction);
126   NODE_SET_METHOD(exports, "callViaString", CallViaString);
127   NODE_SET_METHOD(exports, "callViaUtf8Name", CallViaUtf8Name);
128   NODE_SET_METHOD(exports, "getAsyncId", GetAsyncId);
129   NODE_SET_METHOD(exports, "getTriggerAsyncId", GetTriggerAsyncId);
130   NODE_SET_METHOD(exports, "getResource", GetResource);
131   NODE_SET_METHOD(exports, "runSubclassTest", RunSubclassTest);
132 }
133 
134 }  // anonymous namespace
135 
136 NODE_MODULE(NODE_GYP_MODULE_NAME, Initialize)
137