diff options
author | Ben Noordhuis <info@bnoordhuis.nl> | 2013-10-10 14:09:38 +0200 |
---|---|---|
committer | Ben Noordhuis <info@bnoordhuis.nl> | 2013-10-10 14:09:39 +0200 |
commit | 51cdce8322b78814a8dbc9e1b8bd19eb305af312 (patch) | |
tree | fd8b3952bf3bfe832d6734cf3f44b55fc87588e0 /doc | |
parent | 9c65387673eb51bfa17143edb24fc925045e62de (diff) | |
download | node-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.markdown | 112 |
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) { |