Browse Source

doc: addon: fix object instantiation examples

* Extend examples to show how to handle non-constructor invocation in
  constructor callback functions.

* Fix up examples to initialize member variables at object construction.

* Fix up a few naming inconsistencies.

Fixes #5701.
v0.10.21-release
Ben Noordhuis 11 years ago
parent
commit
51cdce8322
  1. 100
      doc/api/addons.markdown

100
doc/api/addons.markdown

@ -323,12 +323,13 @@ Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`:
static void Init(v8::Handle<v8::Object> exports);
private:
MyObject();
explicit MyObject(double value = 0);
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
double counter_;
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
@ -343,8 +344,13 @@ prototype:
using namespace v8;
MyObject::MyObject() {};
MyObject::~MyObject() {};
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init(Handle<Object> exports) {
// Prepare constructor template
@ -354,28 +360,34 @@ prototype:
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
exports->Set(String::NewSymbol("MyObject"), constructor);
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
MyObject* obj = new MyObject();
obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->counter_ += 1;
obj->value_ += 1;
return scope.Close(Number::New(obj->counter_));
return scope.Close(Number::New(obj->value_));
}
Test it with:
@ -434,13 +446,13 @@ care of instantiating the object (i.e. it does the job of `new` in JavaScript):
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
private:
MyObject();
explicit MyObject(double value = 0);
~MyObject();
static v8::Persistent<v8::Function> constructor;
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args);
double counter_;
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
@ -453,11 +465,14 @@ The implementation is similar to the above in `myobject.cc`:
using namespace v8;
MyObject::MyObject() {};
MyObject::~MyObject() {};
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init() {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
@ -466,18 +481,24 @@ The implementation is similar to the above in `myobject.cc`:
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
MyObject* obj = new MyObject();
obj->counter_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
@ -494,9 +515,9 @@ The implementation is similar to the above in `myobject.cc`:
HandleScope scope;
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->counter_ += 1;
obj->value_ += 1;
return scope.Close(Number::New(obj->counter_));
return scope.Close(Number::New(obj->value_));
}
Test it with:
@ -540,7 +561,7 @@ In the following `addon.cc` we introduce a function `add()` that can take on two
MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>(
args[1]->ToObject());
double sum = obj1->Val() + obj2->Val();
double sum = obj1->Value() + obj2->Value();
return scope.Close(Number::New(sum));
}
@ -569,15 +590,15 @@ can probe private values after unwrapping the object:
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
double Val() const { return val_; }
double Value() const { return value_; }
private:
MyObject();
explicit MyObject(double value = 0);
~MyObject();
static v8::Persistent<v8::Function> constructor;
static v8::Handle<v8::Value> New(const v8::Arguments& args);
double val_;
static v8::Persistent<v8::Function> constructor;
double value_;
};
#endif
@ -590,28 +611,37 @@ The implementation of `myobject.cc` is similar as before:
using namespace v8;
MyObject::MyObject() {};
MyObject::~MyObject() {};
Persistent<Function> MyObject::constructor;
MyObject::MyObject(double value) : value_(value) {
}
MyObject::~MyObject() {
}
void MyObject::Init() {
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
constructor = Persistent<Function>::New(tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
HandleScope scope;
MyObject* obj = new MyObject();
obj->val_ = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
if (args.IsConstructCall()) {
// Invoked as constructor: `new MyObject(...)`
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
} else {
// Invoked as plain function `MyObject(...)`, turn into construct call.
const int argc = 1;
Local<Value> argv[argc] = { args[0] };
return scope.Close(constructor->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {

Loading…
Cancel
Save