Browse Source

addons: build and test examples

fix #6910
v0.11.11-release
Fedor Indutny 11 years ago
parent
commit
1442c1c6de
  1. 1
      .gitignore
  2. 29
      Makefile
  3. 197
      doc/api/addons.markdown
  4. 25
      test/addons/async-hello-world/binding.cc
  5. 3
      test/addons/at-exit/binding.cc
  6. 7
      test/addons/hello-world-function-export/binding.cc
  7. 7
      test/addons/hello-world/binding.cc
  8. 6
      test/addons/testcfg.py
  9. 25
      test/testpy/__init__.py
  10. 94
      tools/doc/addon-verify.js

1
.gitignore

@ -42,6 +42,7 @@ ipch/
/dist-osx
/npm.wxs
/tools/msvs/npm.wixobj
/test/addons/doc-*/
email.md
deps/v8-*
./node_modules

29
Makefile

@ -100,26 +100,38 @@ test/gc/node_modules/weak/build/Release/weakref.node:
--directory="$(shell pwd)/test/gc/node_modules/weak" \
--nodedir="$(shell pwd)"
build-addons:
@if [ ! -f node ]; then make all; fi
rm -rf test/addons/doc-*/
./node tools/doc/addon-verify.js
$(foreach dir, \
$(sort $(dir $(wildcard test/addons/*/*.gyp))), \
./node deps/npm/node_modules/node-gyp/bin/node-gyp rebuild \
--directory="$(shell pwd)/$(dir)" \
--nodedir="$(shell pwd)" && ) echo "build done"
test-gc: all test/gc/node_modules/weak/build/Release/weakref.node
$(PYTHON) tools/test.py --mode=release gc
test-all: all test/gc/node_modules/weak/build/Release/weakref.node
test-build: all build-addons
test-all: test-build test/gc/node_modules/weak/build/Release/weakref.node
$(PYTHON) tools/test.py --mode=debug,release
make test-npm
test-all-http1: all
test-all-http1: test-build
$(PYTHON) tools/test.py --mode=debug,release --use-http1
test-all-valgrind: all
test-all-valgrind: test-build
$(PYTHON) tools/test.py --mode=debug,release --valgrind
test-release: all
test-release: test-build
$(PYTHON) tools/test.py --mode=release
test-debug: all
test-debug: test-build
$(PYTHON) tools/test.py --mode=debug
test-message: all
test-message: test-build
$(PYTHON) tools/test.py message
test-simple: all
@ -140,6 +152,9 @@ test-npm: node
test-npm-publish: node
npm_package_config_publishtest=true ./node deps/npm/test/run.js
test-addons: test-build
$(PYTHON) tools/test.py --mode=release addons
apidoc_sources = $(wildcard doc/api/*.markdown)
apidocs = $(addprefix out/,$(apidoc_sources:.markdown=.html)) \
$(addprefix out/,$(apidoc_sources:.markdown=.json))
@ -418,4 +433,4 @@ cpplint:
lint: jslint cpplint
.PHONY: lint cpplint jslint bench clean docopen docclean doc dist distclean check uninstall install install-includes install-bin all staticlib dynamiclib test test-all website-upload pkg blog blogclean tar binary release-only bench-http-simple bench-idle bench-all bench bench-misc bench-array bench-buffer bench-net bench-http bench-fs bench-tls
.PHONY: lint cpplint jslint bench clean docopen docclean doc dist distclean check uninstall install install-includes install-bin all staticlib dynamiclib test test-all test-addons build-addons website-upload pkg blog blogclean tar binary release-only bench-http-simple bench-idle bench-all bench bench-misc bench-array bench-buffer bench-net bench-http bench-fs bench-tls

197
doc/api/addons.markdown

@ -38,22 +38,22 @@ the following JavaScript code:
First we create a file `hello.cc`:
// hello.cc
#include <node.h>
using namespace v8;
Handle<Value> Method(const Arguments& args) {
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
return scope.Close(String::New("world"));
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Handle<Object> exports) {
exports->Set(String::NewSymbol("hello"),
FunctionTemplate::New(Method)->GetFunction());
NODE_SET_METHOD(exports, "hello", Method);
}
NODE_MODULE(hello, init)
NODE_MODULE(addon, init)
Note that all Node addons must export an initialization function:
@ -66,7 +66,7 @@ There is no semi-colon after `NODE_MODULE` as it's not a function (see
The `module_name` needs to match the filename of the final binary (minus the
.node suffix).
The source code needs to be built into `hello.node`, the binary Addon. To
The source code needs to be built into `addon.node`, the binary Addon. To
do this we create a file called `binding.gyp` which describes the configuration
to build your module in a JSON-like format. This file gets compiled by
[node-gyp](https://github.com/TooTallNate/node-gyp).
@ -74,7 +74,7 @@ to build your module in a JSON-like format. This file gets compiled by
{
"targets": [
{
"target_name": "hello",
"target_name": "addon",
"sources": [ "hello.cc" ]
}
]
@ -93,7 +93,8 @@ in `build/Release/`.
You can now use the binary addon in a Node project `hello.js` by pointing
`require` to the recently built `hello.node` module:
var addon = require('./build/Release/hello');
// hello.js
var addon = require('./build/Release/addon');
console.log(addon.hello()); // 'world'
@ -138,39 +139,42 @@ 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`:
// addon.cc
#include <node.h>
using namespace v8;
Handle<Value> Add(const Arguments& args) {
void Add(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
if (args.Length() < 2) {
ThrowException(Exception::TypeError(
String::New("Wrong number of arguments")));
return scope.Close(Undefined(isolate));
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong number of arguments")));
return;
}
if (!args[0]->IsNumber() || !args[1]->IsNumber()) {
ThrowException(Exception::TypeError(String::New("Wrong arguments")));
return scope.Close(Undefined(isolate));
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Wrong arguments")));
return;
}
Local<Number> num = Number::New(args[0]->NumberValue() +
args[1]->NumberValue());
return scope.Close(num);
args.GetReturnValue().Set(num);
}
void Init(Handle<Object> exports) {
exports->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
NODE_SET_METHOD(exports, "add", Add);
}
NODE_MODULE(addon, Init)
You can test it with the following JavaScript snippet:
// test.js
var addon = require('./build/Release/addon');
console.log( 'This should be eight:', addon.add(3,5) );
@ -181,25 +185,23 @@ You can test it with the following JavaScript snippet:
You can pass JavaScript functions to a C++ function and execute them from
there. Here's `addon.cc`:
// addon.cc
#include <node.h>
using namespace v8;
Handle<Value> RunCallback(const Arguments& args) {
void RunCallback(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
Local<Function> cb = Local<Function>::Cast(args[0]);
const unsigned argc = 1;
Local<Value> argv[argc] = { String::New("hello world") };
Local<Value> argv[argc] = { String::NewFromUtf8(isolate, "hello world") };
cb->Call(Context::GetCurrent()->Global(), argc, argv);
return scope.Close(Undefined(isolate));
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(RunCallback)->GetFunction());
NODE_SET_METHOD(module, "exports", RunCallback);
}
NODE_MODULE(addon, Init)
@ -211,6 +213,7 @@ adding the function as a property of `exports`.
To test it run the following JavaScript snippet:
// test.js
var addon = require('./build/Release/addon');
addon(function(msg){
@ -224,29 +227,30 @@ 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()`:
// addon.cc
#include <node.h>
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
void CreateObject(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
Local<Object> obj = Object::New();
obj->Set(String::NewSymbol("msg"), args[0]->ToString());
obj->Set(String::NewFromUtf8(isolate, "msg"), args[0]->ToString());
return scope.Close(obj);
args.GetReturnValue().Set(obj);
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateObject)->GetFunction());
NODE_SET_METHOD(module, "exports", CreateObject);
}
NODE_MODULE(addon, Init)
To test it in JavaScript:
// test.js
var addon = require('./build/Release/addon');
var obj1 = addon('hello');
@ -259,17 +263,18 @@ To test it in JavaScript:
This pattern illustrates how to create and return a JavaScript function that
wraps a C++ function:
// addon.cc
#include <node.h>
using namespace v8;
Handle<Value> MyFunction(const Arguments& args) {
void MyFunction(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
return scope.Close(String::New("hello world"));
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "hello world"));
}
Handle<Value> CreateFunction(const Arguments& args) {
void CreateFunction(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
@ -277,20 +282,20 @@ wraps a C++ function:
Local<Function> fn = tpl->GetFunction();
// omit this to make it anonymous
fn->SetName(String::NewSymbol("theFunction"));
fn->SetName(String::NewFromUtf8(isolate, "theFunction"));
return scope.Close(fn);
args.GetReturnValue().Set(fn);
}
void Init(Handle<Object> exports, Handle<Object> module) {
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateFunction)->GetFunction());
NODE_SET_METHOD(module, "exports", CreateFunction);
}
NODE_MODULE(addon, Init)
To test:
// test.js
var addon = require('./build/Release/addon');
var fn = addon();
@ -303,6 +308,7 @@ 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`:
// addon.cc
#include <node.h>
#include "myobject.h"
@ -316,10 +322,12 @@ module `addon.cc`:
Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`:
// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
#include <node_object_wrap.h>
class MyObject : public node::ObjectWrap {
public:
@ -329,8 +337,8 @@ Then in `myobject.h` make your wrapper inherit from `node::ObjectWrap`:
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);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
@ -341,8 +349,7 @@ 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:
#include <node.h>
#include <node_object_wrap.h>
// myobject.cc
#include "myobject.h"
using namespace v8;
@ -360,20 +367,18 @@ prototype:
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
Persistent<Function> constructor
= Persistent<Function>::New(isolate, tpl->GetFunction());
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
exports->Set(String::NewSymbol("MyObject"), constructor);
constructor.Reset(isolate, tpl->GetFunction());
exports->Set(String::NewFromUtf8(isolate, "MyObject"),
tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
@ -382,27 +387,29 @@ prototype:
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
args.GetReturnValue().Set(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));
Local<Function> cons = Local<Function>::New(isolate, constructor);
args.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->value_ += 1;
return scope.Close(Number::New(obj->value_));
args.GetReturnValue().Set(Number::New(obj->value_));
}
Test it with:
// test.js
var addon = require('./build/Release/addon');
var obj = new addon.MyObject(10);
@ -421,22 +428,22 @@ explicitly instantiating them with the `new` operator in JavaScript, e.g.
Let's register our `createObject` method in `addon.cc`:
// addon.cc
#include <node.h>
#include "myobject.h"
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
void CreateObject(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
return scope.Close(MyObject::NewInstance(args));
MyObject::NewInstance(args);
}
void InitAll(Handle<Object> exports, Handle<Object> module) {
MyObject::Init();
module->Set(String::NewSymbol("exports"),
FunctionTemplate::New(CreateObject)->GetFunction());
NODE_SET_METHOD(module, "exports", CreateObject);
}
NODE_MODULE(addon, InitAll)
@ -444,22 +451,24 @@ Let's register our `createObject` method in `addon.cc`:
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):
// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <node.h>
#include <node_object_wrap.h>
class MyObject : public node::ObjectWrap {
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
private:
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);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void PlusOne(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
@ -468,6 +477,7 @@ care of instantiating the object (i.e. it does the job of `new` in JavaScript):
The implementation is similar to the above in `myobject.cc`:
// myobject.cc
#include <node.h>
#include "myobject.h"
@ -485,17 +495,16 @@ The implementation is similar to the above in `myobject.cc`:
Isolate* isolate = Isolate::GetCurrent();
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
// Prototype
tpl->PrototypeTemplate()->Set(String::NewSymbol("plusOne"),
FunctionTemplate::New(PlusOne)->GetFunction());
NODE_SET_PROTOTYPE_METHOD(tpl, "plusOne", PlusOne);
constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
constructor.Reset(isolate, tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
@ -504,38 +513,41 @@ The implementation is similar to the above in `myobject.cc`:
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
args.GetReturnValue().Set(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));
Local<Function> cons = Local<Function>::New(isolate, constructor);
args.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
const unsigned argc = 1;
Handle<Value> argv[argc] = { args[0] };
Local<Object> instance = constructor->NewInstance(argc, argv);
Local<Function> cons = Local<Function>::New(isolate, constructor);
Local<Object> instance = cons->NewInstance(argc, argv);
return scope.Close(instance);
args.GetReturnValue().Set(instance);
}
Handle<Value> MyObject::PlusOne(const Arguments& args) {
void MyObject::PlusOne(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
MyObject* obj = ObjectWrap::Unwrap<MyObject>(args.This());
obj->value_ += 1;
return scope.Close(Number::New(obj->value_));
args.GetReturnValue().Set(Number::New(obj->value_));
}
Test it with:
// test.js
var createObject = require('./build/Release/addon');
var obj = createObject(10);
@ -556,19 +568,20 @@ 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:
// addon.cc
#include <node.h>
#include <node_object_wrap.h>
#include "myobject.h"
using namespace v8;
Handle<Value> CreateObject(const Arguments& args) {
void CreateObject(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
return scope.Close(MyObject::NewInstance(args));
MyObject::NewInstance(args);
}
Handle<Value> Add(const Arguments& args) {
void Add(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
@ -577,18 +590,15 @@ 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->Value() + obj2->Value();
return scope.Close(Number::New(sum));
double sum = obj1->value() + obj2->value();
args.GetReturnValue().Set(Number::New(sum));
}
void InitAll(Handle<Object> exports) {
MyObject::Init();
exports->Set(String::NewSymbol("createObject"),
FunctionTemplate::New(CreateObject)->GetFunction());
exports->Set(String::NewSymbol("add"),
FunctionTemplate::New(Add)->GetFunction());
NODE_SET_METHOD(exports, "createObject", CreateObject);
NODE_SET_METHOD(exports, "add", Add);
}
NODE_MODULE(addon, InitAll)
@ -596,6 +606,7 @@ In the following `addon.cc` we introduce a function `add()` that can take on two
To make things interesting we introduce a public method in `myobject.h` so we
can probe private values after unwrapping the object:
// myobject.h
#ifndef MYOBJECT_H
#define MYOBJECT_H
@ -605,14 +616,14 @@ can probe private values after unwrapping the object:
class MyObject : public node::ObjectWrap {
public:
static void Init();
static v8::Handle<v8::Value> NewInstance(const v8::Arguments& args);
double Value() const { return value_; }
static void NewInstance(const v8::FunctionCallbackInfo<v8::Value>& args);
inline double value() const { return value_; }
private:
explicit MyObject(double value = 0);
~MyObject();
static v8::Handle<v8::Value> New(const v8::Arguments& args);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static v8::Persistent<v8::Function> constructor;
double value_;
};
@ -621,6 +632,7 @@ can probe private values after unwrapping the object:
The implementation of `myobject.cc` is similar as before:
// myobject.cc
#include <node.h>
#include "myobject.h"
@ -639,13 +651,13 @@ The implementation of `myobject.cc` is similar as before:
// Prepare constructor template
Local<FunctionTemplate> tpl = FunctionTemplate::New(New);
tpl->SetClassName(String::NewSymbol("MyObject"));
tpl->SetClassName(String::NewFromUtf8(isolate, "MyObject"));
tpl->InstanceTemplate()->SetInternalFieldCount(1);
constructor = Persistent<Function>::New(isolate, tpl->GetFunction());
constructor.Reset(isolate, tpl->GetFunction());
}
Handle<Value> MyObject::New(const Arguments& args) {
void MyObject::New(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
@ -654,28 +666,31 @@ The implementation of `myobject.cc` is similar as before:
double value = args[0]->IsUndefined() ? 0 : args[0]->NumberValue();
MyObject* obj = new MyObject(value);
obj->Wrap(args.This());
return args.This();
args.GetReturnValue().Set(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));
Local<Function> cons = Local<Function>::New(isolate, constructor);
args.GetReturnValue().Set(cons->NewInstance(argc, argv));
}
}
Handle<Value> MyObject::NewInstance(const Arguments& args) {
void MyObject::NewInstance(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
const unsigned argc = 1;
Handle<Value> argv[argc] = { args[0] };
Local<Object> instance = constructor->NewInstance(argc, argv);
Local<Function> cons = Local<Function>::New(isolate, constructor);
Local<Object> instance = cons->NewInstance(argc, argv);
return scope.Close(instance);
args.GetReturnValue().Set(instance);
}
Test it with:
// test.js
var addon = require('./build/Release/addon');
var obj1 = addon.createObject(10);

25
test/addons/async-hello-world/binding.cc

@ -13,21 +13,23 @@ struct async_req {
Persistent<Function> callback;
};
void DoAsync (uv_work_t *r) {
async_req *req = reinterpret_cast<async_req *>(r->data);
void DoAsync(uv_work_t* r) {
async_req* req = reinterpret_cast<async_req*>(r->data);
sleep(1); // simulate CPU intensive process...
req->output = req->input * 2;
}
void AfterAsync (uv_work_t *r) {
HandleScope scope;
async_req *req = reinterpret_cast<async_req *>(r->data);
void AfterAsync(uv_work_t* r) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
async_req* req = reinterpret_cast<async_req*>(r->data);
Handle<Value> argv[2] = { Null(), Integer::New(req->output) };
TryCatch try_catch;
req->callback->Call(Context::GetCurrent()->Global(), 2, argv);
Local<Function> callback = Local<Function>::New(isolate, req->callback);
callback->Call(Context::GetCurrent()->Global(), 2, argv);
// cleanup
req->callback.Dispose();
@ -38,24 +40,23 @@ void AfterAsync (uv_work_t *r) {
}
}
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
async_req *req = new async_req;
async_req* req = new async_req;
req->req.data = req;
req->input = args[0]->IntegerValue();
req->output = 0;
Local<Function> callback = Local<Function>::Cast(args[1]);
req->callback = Persistent<Function>::New(callback);
req->callback.Reset(isolate, callback);
uv_queue_work(uv_default_loop(),
&req->req,
DoAsync,
(uv_after_work_cb)AfterAsync);
return Undefined();
}
void init(Handle<Object> exports, Handle<Object> module) {

3
test/addons/at-exit/binding.cc

@ -7,6 +7,7 @@
using node::AtExit;
using v8::Handle;
using v8::HandleScope;
using v8::Isolate;
using v8::Local;
using v8::Object;
@ -15,7 +16,7 @@ static int at_exit_cb1_called = 0;
static int at_exit_cb2_called = 0;
static void at_exit_cb1(void* arg) {
HandleScope scope;
HandleScope scope(Isolate::GetCurrent());
assert(arg == 0);
Local<Object> obj = Object::New();
assert(!obj.IsEmpty()); // assert VM is still alive

7
test/addons/hello-world-function-export/binding.cc

@ -3,9 +3,10 @@
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Handle<Object> exports, Handle<Object> module) {

7
test/addons/hello-world/binding.cc

@ -3,9 +3,10 @@
using namespace v8;
Handle<Value> Method(const Arguments& args) {
HandleScope scope;
return scope.Close(String::New("world"));
void Method(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
args.GetReturnValue().Set(String::NewFromUtf8(isolate, "world"));
}
void init(Handle<Object> target) {

6
test/addons/testcfg.py

@ -0,0 +1,6 @@
import sys, os
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import testpy
def GetConfiguration(context, root):
return testpy.AddonTestConfiguration(context, root, 'addon')

25
test/testpy/__init__.py

@ -134,3 +134,28 @@ class SimpleTestConfiguration(test.TestConfiguration):
status_file = join(self.root, '%s.status' % (self.section))
if exists(status_file):
test.ReadConfigurationInto(status_file, sections, defs)
class AddonTestConfiguration(SimpleTestConfiguration):
def __init__(self, context, root, section, additional=[]):
super(AddonTestConfiguration, self).__init__(context, root, section)
def Ls(self, path):
def SelectTest(name):
return name.endswith('.js')
result = []
for subpath in os.listdir(path):
if os.path.isdir(join(path, subpath)):
for f in os.listdir(join(path, subpath)):
if SelectTest(f):
result.append([subpath, f[:-3]])
return result
def ListTests(self, current_path, path, mode):
all_tests = [current_path + t for t in self.Ls(join(self.root))]
result = []
for test in all_tests:
if self.Contains(path, test):
file_path = join(self.root, reduce(join, test[1:], "") + ".js")
result.append(SimpleTestCase(test, file_path, mode, self.context, self))
return result

94
tools/doc/addon-verify.js

@ -0,0 +1,94 @@
var fs = require('fs');
var path = require('path');
var marked = require('marked');
var doc = path.resolve(__dirname, '..', '..', 'doc', 'api', 'addons.markdown');
var verifyDir = path.resolve(__dirname, '..', '..', 'test', 'addons');
var contents = fs.readFileSync(doc).toString();
var tokens = marked.lexer(contents, {});
var files = null;
var id = 0;
// Just to make sure that all examples will be processed
tokens.push({ type: 'heading' });
var oldDirs = fs.readdirSync(verifyDir);
oldDirs = oldDirs.filter(function(dir) {
return /^doc-/.test(dir);
}).map(function(dir) {
return path.resolve(verifyDir, dir);
});
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.type === 'heading') {
if (files && Object.keys(files).length !== 0) {
verifyFiles(files, function(err) {
if (err)
console.log(err);
else
console.log('done');
});
}
files = {};
} else if (token.type === 'code') {
var match = token.text.match(/^\/\/\s+(.*\.(?:cc|h|js))[\r\n]/);
if (match === null)
continue;
files[match[1]] = token.text;
}
}
function once(fn) {
var once = false;
return function() {
if (once)
return;
once = true;
fn.apply(this, arguments);
};
}
function verifyFiles(files, callback) {
var dir = path.resolve(verifyDir, 'doc-' + id++);
files = Object.keys(files).map(function(name) {
return {
path: path.resolve(dir, name),
name: name,
content: files[name]
};
});
files.push({
path: path.resolve(dir, 'binding.gyp'),
content: JSON.stringify({
targets: [
{
target_name: 'addon',
sources: files.map(function(file) {
return file.name;
})
}
]
})
});
fs.mkdir(dir, function() {
// Ignore errors
var waiting = files.length;
for (var i = 0; i < files.length; i++)
fs.writeFile(files[i].path, files[i].content, next);
var done = once(callback);
function next(err) {
if (err)
return done(err);
if (--waiting === 0)
done();
}
});
}
Loading…
Cancel
Save