This content is taken from https://github.com/nodejs/node/pull/63575. The original commit message is preserved below: --- worker: fix premature addon unload Weak callbacks could run after addons were unloaded, leading to a crash. Signed-off-by: Mohamed Akram <mohd.akram@outlook.com> PR-URL: https://github.com/nodejs/node/pull/63642 Fixes: https://github.com/nodejs/node/issues/63540 Refs: https://github.com/nodejs/node/pull/63575 Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
99 lines
2.9 KiB
C++
99 lines
2.9 KiB
C++
#include <node.h>
|
|
#include <node_object_wrap.h>
|
|
|
|
using v8::Context;
|
|
using v8::Function;
|
|
using v8::FunctionCallbackInfo;
|
|
using v8::FunctionTemplate;
|
|
using v8::Isolate;
|
|
using v8::Local;
|
|
using v8::Number;
|
|
using v8::Object;
|
|
using v8::ObjectTemplate;
|
|
using v8::String;
|
|
using v8::Value;
|
|
|
|
class MyObject : public node::ObjectWrap {
|
|
public:
|
|
static void Init(v8::Local<v8::Object> exports);
|
|
~MyObject();
|
|
|
|
private:
|
|
explicit MyObject(double value = 0);
|
|
|
|
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
|
|
|
|
double value_;
|
|
};
|
|
|
|
MyObject::MyObject(double value) : value_(value) {}
|
|
|
|
MyObject::~MyObject() {}
|
|
|
|
void MyObject::Init(Local<Object> exports) {
|
|
Isolate* isolate = Isolate::GetCurrent();
|
|
Local<Context> context = isolate->GetCurrentContext();
|
|
|
|
Local<ObjectTemplate> addon_data_tpl = ObjectTemplate::New(isolate);
|
|
addon_data_tpl->SetInternalFieldCount(1); // 1 field for the MyObject::New()
|
|
Local<Object> addon_data =
|
|
addon_data_tpl->NewInstance(context).ToLocalChecked();
|
|
|
|
// Prepare constructor template
|
|
Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, New, addon_data);
|
|
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject").ToLocalChecked());
|
|
tpl->InstanceTemplate()->SetInternalFieldCount(1);
|
|
|
|
// Prototype
|
|
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
|
|
|
|
Local<Function> constructor = tpl->GetFunction(context).ToLocalChecked();
|
|
addon_data->SetInternalField(0, constructor);
|
|
exports
|
|
->Set(context,
|
|
String::NewFromUtf8(isolate, "MyObject").ToLocalChecked(),
|
|
constructor)
|
|
.FromJust();
|
|
}
|
|
|
|
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
Local<Context> context = isolate->GetCurrentContext();
|
|
|
|
if (args.IsConstructCall()) {
|
|
// Invoked as constructor: `new MyObject(...)`
|
|
double value =
|
|
args[0]->IsUndefined() ? 0 : args[0]->NumberValue(context).FromMaybe(0);
|
|
MyObject* obj = new MyObject(value);
|
|
obj->Wrap(args.This());
|
|
args.GetReturnValue().Set(args.This());
|
|
} else {
|
|
// Invoked as plain function `MyObject(...)`, turn into construct call.
|
|
const int argc = 1;
|
|
Local<Value> argv[argc] = {args[0]};
|
|
Local<Function> cons = args.Data()
|
|
.As<Object>()
|
|
->GetInternalField(0)
|
|
.As<Value>()
|
|
.As<Function>();
|
|
Local<Object> result =
|
|
cons->NewInstance(context, argc, argv).ToLocalChecked();
|
|
args.GetReturnValue().Set(result);
|
|
}
|
|
}
|
|
|
|
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
|
|
Isolate* isolate = args.GetIsolate();
|
|
|
|
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
|
|
obj->value_ += 1;
|
|
|
|
args.GetReturnValue().Set(Number::New(isolate, obj->value_));
|
|
}
|
|
|
|
void InitAll(Local<Object> exports) {
|
|
MyObject::Init(exports);
|
|
}
|
|
|
|
NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)
|