summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorBen Noordhuis <info@bnoordhuis.nl>2013-10-10 14:09:38 +0200
committerBen Noordhuis <info@bnoordhuis.nl>2013-10-10 14:09:39 +0200
commit51cdce8322b78814a8dbc9e1b8bd19eb305af312 (patch)
treefd8b3952bf3bfe832d6734cf3f44b55fc87588e0 /doc
parent9c65387673eb51bfa17143edb24fc925045e62de (diff)
downloadnode-new-51cdce8322b78814a8dbc9e1b8bd19eb305af312.tar.gz
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.
Diffstat (limited to 'doc')
-rw-r--r--doc/api/addons.markdown112
1 files changed, 71 insertions, 41 deletions
diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown
index cb44538c82..65dce52e45 100644
--- a/doc/api/addons.markdown
+++ b/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();
- obj->Wrap(args.This());
-
- return args.This();
+ 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();
- obj->Wrap(args.This());
-
- return args.This();
+ 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();
- obj->Wrap(args.This());
-
- return args.This();
+ 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) {