#include #include 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 exports); ~MyObject(); private: explicit MyObject(double value = 0); static void New(const v8::FunctionCallbackInfo& args); static void PlusOne(const v8::FunctionCallbackInfo& args); double value_; }; MyObject::MyObject(double value) : value_(value) {} MyObject::~MyObject() {} void MyObject::Init(Local exports) { Isolate* isolate = Isolate::GetCurrent(); Local context = isolate->GetCurrentContext(); Local addon_data_tpl = ObjectTemplate::New(isolate); addon_data_tpl->SetInternalFieldCount(1); // 1 field for the MyObject::New() Local addon_data = addon_data_tpl->NewInstance(context).ToLocalChecked(); // Prepare constructor template Local 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 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& args) { Isolate* isolate = args.GetIsolate(); Local 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 argv[argc] = {args[0]}; Local cons = args.Data() .As() ->GetInternalField(0) .As() .As(); Local result = cons->NewInstance(context, argc, argv).ToLocalChecked(); args.GetReturnValue().Set(result); } } void MyObject::PlusOne(const FunctionCallbackInfo& args) { Isolate* isolate = args.GetIsolate(); MyObject* obj = ObjectWrap::Unwrap(args.This()); obj->value_ += 1; args.GetReturnValue().Set(Number::New(isolate, obj->value_)); } void InitAll(Local exports) { MyObject::Init(exports); } NODE_MODULE(NODE_GYP_MODULE_NAME, InitAll)