`AsyncResource` is intended to be a base class, and since we don’t know what API consumers will do with it in their own code, it’s good practice to make its destructor virtual. This should not be ABI-breaking since all class methods are inline. PR-URL: https://github.com/nodejs/node/pull/20633 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com> Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
136 lines
4.5 KiB
C++
136 lines
4.5 KiB
C++
#include "node.h"
|
|
|
|
#include <assert.h>
|
|
#include <vector>
|
|
|
|
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<Object> resource)
|
|
: AsyncResource(isolate, resource, "CustomAsyncResource") {}
|
|
~CustomAsyncResource() {
|
|
custom_async_resource_destructor_calls++;
|
|
}
|
|
};
|
|
|
|
void CreateAsyncResource(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
assert(args[0]->IsObject());
|
|
AsyncResource* r;
|
|
if (args[1]->IsInt32()) {
|
|
r = new AsyncResource(isolate, args[0].As<Object>(), "foobär",
|
|
args[1].As<Integer>()->Value());
|
|
} else {
|
|
r = new AsyncResource(isolate, args[0].As<Object>(), "foobär");
|
|
}
|
|
|
|
args.GetReturnValue().Set(
|
|
External::New(isolate, static_cast<void*>(r)));
|
|
}
|
|
|
|
void DestroyAsyncResource(const FunctionCallbackInfo<Value>& args) {
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
delete r;
|
|
}
|
|
|
|
void CallViaFunction(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
|
|
Local<String> name =
|
|
String::NewFromUtf8(isolate, "methöd", v8::NewStringType::kNormal)
|
|
.ToLocalChecked();
|
|
Local<Value> fn =
|
|
r->get_resource()->Get(isolate->GetCurrentContext(), name)
|
|
.ToLocalChecked();
|
|
assert(fn->IsFunction());
|
|
|
|
Local<Value> arg = Integer::New(isolate, 42);
|
|
MaybeLocal<Value> ret = r->MakeCallback(fn.As<Function>(), 1, &arg);
|
|
args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
|
|
}
|
|
|
|
void CallViaString(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
|
|
Local<String> name =
|
|
String::NewFromUtf8(isolate, "methöd", v8::NewStringType::kNormal)
|
|
.ToLocalChecked();
|
|
|
|
Local<Value> arg = Integer::New(isolate, 42);
|
|
MaybeLocal<Value> ret = r->MakeCallback(name, 1, &arg);
|
|
args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
|
|
}
|
|
|
|
void CallViaUtf8Name(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
|
|
Local<Value> arg = Integer::New(isolate, 42);
|
|
MaybeLocal<Value> ret = r->MakeCallback("methöd", 1, &arg);
|
|
args.GetReturnValue().Set(ret.FromMaybe(Local<Value>()));
|
|
}
|
|
|
|
void GetAsyncId(const FunctionCallbackInfo<Value>& args) {
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
args.GetReturnValue().Set(r->get_async_id());
|
|
}
|
|
|
|
void GetTriggerAsyncId(const FunctionCallbackInfo<Value>& args) {
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
args.GetReturnValue().Set(r->get_trigger_async_id());
|
|
}
|
|
|
|
void GetResource(const FunctionCallbackInfo<Value>& args) {
|
|
assert(args[0]->IsExternal());
|
|
auto r = static_cast<AsyncResource*>(args[0].As<External>()->Value());
|
|
args.GetReturnValue().Set(r->get_resource());
|
|
}
|
|
|
|
void RunSubclassTest(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
Local<Object> obj = Object::New(isolate);
|
|
|
|
assert(custom_async_resource_destructor_calls == 0);
|
|
CustomAsyncResource* resource = new CustomAsyncResource(isolate, obj);
|
|
delete static_cast<AsyncResource*>(resource);
|
|
assert(custom_async_resource_destructor_calls == 1);
|
|
}
|
|
|
|
void Initialize(Local<Object> 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)
|