diff options
author | Fedor Indutny <fedor.indutny@gmail.com> | 2012-01-23 22:30:28 +0400 |
---|---|---|
committer | Fedor Indutny <fedor.indutny@gmail.com> | 2012-01-23 22:30:28 +0400 |
commit | 667aae596cded9336f50574386683ec39ada43f2 (patch) | |
tree | 41918ad8d4801cc34215b054cb63dc83bd1ce8a5 /doc | |
parent | 2433eeb3850a91feb99bab530cb7183800166390 (diff) | |
parent | 6c0c00a2052ec613503a0322dcbabb6fcf41dab0 (diff) |
Merge branch 'v0.6'
Conflicts:
ChangeLog
doc/template.html
lib/cluster.js
lib/http.js
lib/tls.js
src/node.h
src/node_version.h
test/simple/test-cluster-kill-workers.js
Diffstat (limited to 'doc')
-rw-r--r-- | doc/api/addons.markdown | 547 | ||||
-rw-r--r-- | doc/api/appendix_1.markdown | 2 | ||||
-rw-r--r-- | doc/community/index.html | 6 | ||||
-rw-r--r-- | doc/index.html | 14 | ||||
-rw-r--r-- | doc/logos/index.html | 2 |
5 files changed, 556 insertions, 15 deletions
diff --git a/doc/api/addons.markdown b/doc/api/addons.markdown index 6f99f8be48e..4527b24063b 100644 --- a/doc/api/addons.markdown +++ b/doc/api/addons.markdown @@ -6,7 +6,8 @@ knowledge of several libraries: - V8 JavaScript, a C++ library. Used for interfacing with JavaScript: creating objects, calling functions, etc. Documented mostly in the - `v8.h` header file (`deps/v8/include/v8.h` in the Node source tree). + `v8.h` header file (`deps/v8/include/v8.h` in the Node source tree), + which is also available [online](http://izs.me/v8-docs/main.html). - [libuv](https://github.com/joyent/libuv), C event loop library. Anytime one needs to wait for a file descriptor to become readable, wait for a timer, or @@ -22,12 +23,15 @@ Node statically compiles all its dependencies into the executable. When compiling your module, you don't need to worry about linking to any of these libraries. + +### Hello world + To get started let's make a small Addon which is the C++ equivalent of the following Javascript code: exports.hello = function() { return 'world'; }; -To get started we create a file `hello.cc`: +First we create a file `hello.cc`: #include <node.h> #include <v8.h> @@ -40,7 +44,8 @@ To get started we create a file `hello.cc`: } void init(Handle<Object> target) { - NODE_SET_METHOD(target, "hello", Method); + target->Set(String::NewSymbol("hello"), + FunctionTemplate::New(Method)->GetFunction()); } NODE_MODULE(hello, init) @@ -87,5 +92,537 @@ the recently built module: console.log(addon.hello()); // 'world' -For the moment, that is all the documentation on addons. Please see -<https://github.com/pietern/hiredis-node> for a real example. +Please see patterns below for further information or +<https://github.com/pietern/hiredis-node> for an example in production. + + +## Addon patterns + +Below are some addon patterns to help you get started. Consult the online +[v8 reference](http://izs.me/v8-docs/main.html) for help with the various v8 +calls, and v8's [Embedder's Guide](http://code.google.com/apis/v8/embed.html) +for an explanation of several concepts used such as handles, scopes, +function templates, etc. + +To compile these examples, create the `wscript` file below and run +`node-waf configure build`: + + srcdir = '.' + blddir = 'build' + VERSION = '0.0.1' + + def set_options(opt): + opt.tool_options('compiler_cxx') + + def configure(conf): + conf.check_tool('compiler_cxx') + conf.check_tool('node_addon') + + def build(bld): + obj = bld.new_task_gen('cxx', 'shlib', 'node_addon') + obj.target = 'addon' + obj.source = ['addon.cc'] + +In cases where there is more than one `.cc` file, simply add the file name to the +`obj.source` array, e.g.: + + obj.source = ['addon.cc', 'myexample.cc'] + + +#### Function arguments + +The following pattern illustrates how to read arguments from JavaScript +function calls and return a result. This is the main and only needed source +`addon.cc`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + + using namespace v8; + + Handle<Value> Add(const Arguments& args) { + HandleScope scope; + + if (args.Length() < 2) { + ThrowException(Exception::TypeError(String::New("Wrong number of arguments"))); + return scope.Close(Undefined()); + } + + if (!args[0]->IsNumber() || !args[1]->IsNumber()) { + ThrowException(Exception::TypeError(String::New("Wrong arguments"))); + return scope.Close(Undefined()); + } + + Local<Number> num = Number::New(args[0]->NumberValue() + + args[1]->NumberValue()); + return scope.Close(num); + } + + void Init(Handle<Object> target) { + target->Set(String::NewSymbol("add"), + FunctionTemplate::New(Add)->GetFunction()); + } + + NODE_MODULE(addon, Init) + +You can test it with the following JavaScript snippet: + + var addon = require('./build/Release/addon'); + + console.log( 'This should be eight:', addon.add(3,5) ); + + +#### Callbacks + +You can pass JavaScript functions to a C++ function and execute them from +there. Here's `addon.cc`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + + using namespace v8; + + Handle<Value> RunCallback(const Arguments& args) { + HandleScope scope; + + Local<Function> cb = Local<Function>::Cast(args[0]); + const unsigned argc = 1; + Local<Value> argv[argc] = { Local<Value>::New(String::New("hello world")) }; + cb->Call(Context::GetCurrent()->Global(), argc, argv); + + return scope.Close(Undefined()); + } + + void Init(Handle<Object> target) { + target->Set(String::NewSymbol("runCallback"), + FunctionTemplate::New(RunCallback)->GetFunction()); + } + + NODE_MODULE(addon, Init) + +To test it run the following JavaScript snippet: + + var addon = require('./build/Release/addon'); + + addon.runCallback(function(msg){ + console.log(msg); // 'hello world' + }); + + +#### Object factory + +You can create and return new objects from within a C++ function with this +`addon.cc` pattern, which returns an object with property `msg` that echoes +the string passed to `createObject()`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + + using namespace v8; + + Handle<Value> CreateObject(const Arguments& args) { + HandleScope scope; + + Local<Object> obj = Object::New(); + obj->Set(String::NewSymbol("msg"), args[0]->ToString()); + + return scope.Close(obj); + } + + void Init(Handle<Object> target) { + target->Set(String::NewSymbol("createObject"), + FunctionTemplate::New(CreateObject)->GetFunction()); + } + + NODE_MODULE(addon, Init) + +To test it in JavaScript: + + var addon = require('./build/Release/addon'); + + var obj1 = addon.createObject('hello'); + var obj2 = addon.createObject('world'); + console.log(obj1.msg+' '+obj2.msg); // 'hello world' + + +#### Function factory + +This pattern illustrates how to create and return a JavaScript function that +wraps a C++ function: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + + using namespace v8; + + Handle<Value> MyFunction(const Arguments& args) { + HandleScope scope; + return scope.Close(String::New("hello world")); + } + + Handle<Value> CreateFunction(const Arguments& args) { + HandleScope scope; + + Local<FunctionTemplate> tpl = FunctionTemplate::New(MyFunction); + Local<Function> fn = tpl->GetFunction(); + fn->SetName(String::NewSymbol("theFunction")); // omit this to make it anonymous + + return scope.Close(fn); + } + + void Init(Handle<Object> target) { + target->Set(String::NewSymbol("createFunction"), + FunctionTemplate::New(CreateFunction)->GetFunction()); + } + + NODE_MODULE(addon, Init) + + +To test: + + var addon = require('./build/Release/addon'); + + var fn = addon.createFunction(); + console.log(fn()); // 'hello world' + + +#### Wrapping C++ objects + +Here we will create a wrapper for a C++ object/class `MyObject` that can be +instantiated in JavaScript through the `new` operator. First prepare the main +module `addon.cc`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + void InitAll(Handle<Object> target) { + MyObject::Init(target); + } + + NODE_MODULE(addon, InitAll) + +Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`: + + #ifndef MYOBJECT_H + #define MYOBJECT_H + + #include <node.h> + + class MyObject : public node::ObjectWrap { + public: + static void Init(v8::Handle<v8::Object> target); + + private: + MyObject(); + ~MyObject(); + + static v8::Handle<v8::Value> New(const v8::Arguments& args); + static v8::Handle<v8::Value> PlusOne(const v8::Arguments& args); + double counter_; + }; + + #endif + +And in `myobject.cc` implement the various methods that you want to expose. +Here we expose the method `plusOne` by adding it to the constructor's +prototype: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + MyObject::MyObject() {}; + MyObject::~MyObject() {}; + + void MyObject::Init(Handle<Object> target) { + // Prepare constructor template + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(String::NewSymbol("MyObject")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + // Prototype + tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"), + FunctionTemplate::New(PlusOne)->GetFunction()); + + Persistent<Function> constructor = Persistent<Function>::New(tpl->GetFunction()); + target->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(); + } + + Handle<Value> MyObject::PlusOne(const Arguments& args) { + HandleScope scope; + + MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This()); + obj->counter_ += 1; + + return scope.Close(Number::New(obj->counter_)); + } + +Test it with: + + var addon = require('./build/Release/addon'); + + var obj = new addon.MyObject(10); + console.log( obj.plusOne() ); // 11 + console.log( obj.plusOne() ); // 12 + console.log( obj.plusOne() ); // 13 + + +#### Factory of wrapped objects + +This is useful when you want to be able to create native objects without +explicitly instantiating them with the `new` operator in JavaScript, e.g. + + var obj = addon.createObject(); + // instead of: + // var obj = new addon.Object(); + +Let's register our `createObject` method in `addon.cc`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + Handle<Value> CreateObject(const Arguments& args) { + HandleScope scope; + return scope.Close(MyObject::NewInstance(args)); + } + + void InitAll(Handle<Object> target) { + MyObject::Init(); + + target->Set(String::NewSymbol("createObject"), + FunctionTemplate::New(CreateObject)->GetFunction()); + } + + NODE_MODULE(addon, InitAll) + +In `myobject.h` we now introduce the static method `NewInstance` that takes +care of instantiating the object (i.e. it does the job of `new` in JavaScript): + + #define BUILDING_NODE_EXTENSION + #ifndef MYOBJECT_H + #define MYOBJECT_H + + #include <node.h> + + class MyObject : public node::ObjectWrap { + public: + static void Init(); + static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args); + + private: + MyObject(); + ~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_; + }; + + #endif + +The implementation is similar to the above in `myobject.cc`: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + MyObject::MyObject() {}; + MyObject::~MyObject() {}; + + Persistent<Function> MyObject::constructor; + + void MyObject::Init() { + // Prepare constructor template + Local<FunctionTemplate> tpl = FunctionTemplate::New(New); + tpl->SetClassName(String::NewSymbol("MyObject")); + tpl->InstanceTemplate()->SetInternalFieldCount(1); + // 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(); + } + + Handle<Value> MyObject::NewInstance(const Arguments& args) { + HandleScope scope; + + const unsigned argc = 1; + Handle<Value> argv[argc] = { args[0] }; + Local<Object> instance = constructor->NewInstance(argc, argv); + + return scope.Close(instance); + } + + Handle<Value> MyObject::PlusOne(const Arguments& args) { + HandleScope scope; + + MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This()); + obj->counter_ += 1; + + return scope.Close(Number::New(obj->counter_)); + } + +Test it with: + + var addon = require('./build/Release/addon'); + + var obj = addon.createObject(10); + console.log( obj.plusOne() ); // 11 + console.log( obj.plusOne() ); // 12 + console.log( obj.plusOne() ); // 13 + + var obj2 = addon.createObject(20); + console.log( obj2.plusOne() ); // 21 + console.log( obj2.plusOne() ); // 22 + console.log( obj2.plusOne() ); // 23 + + +#### Passing wrapped objects around + +In addition to wrapping and returning C++ objects, you can pass them around +by unwrapping them with Node's `node::ObjectWrap::Unwrap` helper function. +In the following `addon.cc` we introduce a function `add()` that can take on two +`MyObject` objects: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + Handle<Value> CreateObject(const Arguments& args) { + HandleScope scope; + return scope.Close(MyObject::NewInstance(args)); + } + + Handle<Value> Add(const Arguments& args) { + HandleScope scope; + + MyObject* obj1 = node::ObjectWrap::Unwrap<MyObject>( + args[0]->ToObject()); + MyObject* obj2 = node::ObjectWrap::Unwrap<MyObject>( + args[1]->ToObject()); + + double sum = obj1->Val() + obj2->Val(); + return scope.Close(Number::New(sum)); + } + + void InitAll(Handle<Object> target) { + MyObject::Init(); + + target->Set(String::NewSymbol("createObject"), + FunctionTemplate::New(CreateObject)->GetFunction()); + + target->Set(String::NewSymbol("add"), + FunctionTemplate::New(Add)->GetFunction()); + } + + NODE_MODULE(addon, InitAll) + +To make things interesting we introduce a public method in `myobject.h` so we +can probe private values after unwrapping the object: + + #define BUILDING_NODE_EXTENSION + #ifndef MYOBJECT_H + #define MYOBJECT_H + + #include <node.h> + + class MyObject : public node::ObjectWrap { + public: + static void Init(); + static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args); + double Val() const { return val_; } + + private: + MyObject(); + ~MyObject(); + + static v8::Persistent<v8::Function> constructor; + static v8::Handle<v8::Value> New(const v8::Arguments& args); + double val_; + }; + + #endif + +The implementation of `myobject.cc` is similar as before: + + #define BUILDING_NODE_EXTENSION + #include <node.h> + #include "myobject.h" + + using namespace v8; + + MyObject::MyObject() {}; + MyObject::~MyObject() {}; + + Persistent<Function> MyObject::constructor; + + 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(); + } + + Handle<Value> MyObject::NewInstance(const Arguments& args) { + HandleScope scope; + + const unsigned argc = 1; + Handle<Value> argv[argc] = { args[0] }; + Local<Object> instance = constructor->NewInstance(argc, argv); + + return scope.Close(instance); + } + +Test it with: + + var addon = require('./build/Release/addon'); + + var obj1 = addon.createObject(10); + var obj2 = addon.createObject(20); + var result = addon.add(obj1, obj2); + + console.log(result); // 30 diff --git a/doc/api/appendix_1.markdown b/doc/api/appendix_1.markdown index d25d7f9f3c3..59430c20e25 100644 --- a/doc/api/appendix_1.markdown +++ b/doc/api/appendix_1.markdown @@ -38,7 +38,7 @@ elsewhere. - [ncurses](https://github.com/mscdex/node-ncurses) - Testing/TDD/BDD: [vows](http://vowsjs.org/), - [expresso](https://github.com/visionmedia/expresso), + [mocha](https://github.com/visionmedia/mocha), [mjsunit.runner](https://github.com/tmpvar/mjsunit.runner) Patches to this list are welcome. diff --git a/doc/community/index.html b/doc/community/index.html index dec8b58b900..3219f7bf847 100644 --- a/doc/community/index.html +++ b/doc/community/index.html @@ -28,7 +28,11 @@ </div> <div id="content" class="clearfix"> <div id="column1" class="interior"> - <p>Node's most valuable feature is the friendly and colorful community of developers. There are many places where this group congregates on the internet. This page attempts to highlight the best forums.</p> + <p>Node's most valuable feature is the friendly and <a + href="http://blip.tv/jsconf/nodeconf-2011-marak-squires-5729610">colorful + community</a> of developers. There are many places where + this group congregates on the internet. This page attempts + to highlight the best forums.</p> <h2>Periodicals</h2> diff --git a/doc/index.html b/doc/index.html index 61f10893d7b..3769002f911 100644 --- a/doc/index.html +++ b/doc/index.html @@ -77,15 +77,15 @@ <a href="#" id="download-close">X</a> <img id="download-logo" src="download-logo.png" alt="node.js"> <ul id="installers" class="clearfix"> - <li><a href="http://nodejs.org/dist/v0.6.7/node-v0.6.7.msi">Windows Installer</a><br>node-v0.6.7.msi</li> - <li><a href="http://nodejs.org/dist/v0.6.7/node-v0.6.7.pkg">Macintosh Installer</a><br>node-v0.6.7.pkg</li> - <li id="source"><a href="http://nodejs.org/dist/v0.6.7/node-v0.6.7.tar.gz">Source Code</a><br>node-v0.6.7.tar.gz</li> + <li><a href="http://nodejs.org/dist/v0.6.8/node-v0.6.8.msi">Windows Installer</a><br>node-v0.6.8.msi</li> + <li><a href="http://nodejs.org/dist/v0.6.8/node-v0.6.8.pkg">Macintosh Installer</a><br>node-v0.6.8.pkg</li> + <li id="source"><a href="http://nodejs.org/dist/v0.6.8/node-v0.6.8.tar.gz">Source Code</a><br>node-v0.6.8.tar.gz</li> </ul> <ul id="documentation"> - <li><a href="https://raw.github.com/joyent/node/v0.6.7/ChangeLog">Change Log</a></li> - <li><a href="http://nodejs.org/docs/v0.6.7/api/index.html">Documentation</a></li> - <li><a href="http://nodejs.org/dist/v0.6.7">Other release files</a></li> - <li><a href="https://raw.github.com/joyent/node/v0.6.7/LICENSE">License</a></li> + <li><a href="https://raw.github.com/joyent/node/v0.6.8/ChangeLog">Change Log</a></li> + <li><a href="http://nodejs.org/docs/v0.6.8/api/index.html">Documentation</a></li> + <li><a href="http://nodejs.org/dist/v0.6.8">Other release files</a></li> + <li><a href="https://raw.github.com/joyent/node/v0.6.8/LICENSE">License</a></li> <li><a href="https://github.com/joyent/node">Git Repository</a></li> <li><a href="https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager">Installing with a Package Manager</a> diff --git a/doc/logos/index.html b/doc/logos/index.html index 403abe2da0e..35c575cb551 100644 --- a/doc/logos/index.html +++ b/doc/logos/index.html @@ -60,7 +60,7 @@ </div> </div> <div id="footer"> - <p>Copyright <a href="http://joyent.com">Joyent, Inc</a>., Node.js is a <a href="trademark-policy.pdf">trademark of Joyent, Inc</a>., <a href="https://raw.github.com/joyent/node/v0.6.7/LICENSE">View License</a></p> + <p>Copyright <a href="http://joyent.com">Joyent, Inc</a>., Node.js is a <a href="trademark-policy.pdf">trademark of Joyent, Inc</a>., <a href="https://raw.github.com/joyent/node/v0.6.8/LICENSE">View License</a></p> </div> |