lib, src: upgrade after v8 api change
This is a big commit that touches just about every file in the src/ directory. The V8 API has changed in significant ways. The most important changes are: * Binding functions take a const v8::FunctionCallbackInfo<T>& argument rather than a const v8::Arguments& argument. * Binding functions return void rather than v8::Handle<v8::Value>. The return value is returned with the args.GetReturnValue().Set() family of functions. * v8::Persistent<T> no longer derives from v8::Handle<T> and no longer allows you to directly dereference the object that the persistent handle points to. This means that the common pattern of caching oft-used JS values in a persistent handle no longer quite works, you first need to reconstruct a v8::Local<T> from the persistent handle with the Local<T>::New(isolate, persistent) factory method. A handful of (internal) convenience classes and functions have been added to make dealing with the new API a little easier. The most visible one is node::Cached<T>, which wraps a v8::Persistent<T> with some template sugar. It can hold arbitrary types but so far it's exclusively used for v8::Strings (which was by far the most commonly cached handle type.)
This commit is contained in:
parent
9b3de60d35
commit
110a9cd8db
@ -556,8 +556,7 @@ Socket.prototype._getpeername = function() {
|
||||
}
|
||||
if (!this._peername) {
|
||||
this._peername = this._handle.getpeername();
|
||||
// getpeername() returns null on error
|
||||
if (this._peername === null) {
|
||||
if (!this._peername) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@ -581,7 +580,7 @@ Socket.prototype._getsockname = function() {
|
||||
}
|
||||
if (!this._sockname) {
|
||||
this._sockname = this._handle.getsockname();
|
||||
if (this._sockname === null) {
|
||||
if (!this._sockname) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
@ -648,7 +647,7 @@ Socket.prototype._writeGeneric = function(writev, data, encoding, cb) {
|
||||
var writeReq = createWriteReq(this._handle, data, enc);
|
||||
}
|
||||
|
||||
if (!writeReq || typeof writeReq !== 'object')
|
||||
if (!writeReq)
|
||||
return this._destroy(errnoException(process._errno, 'write'), cb);
|
||||
|
||||
writeReq.oncomplete = afterWrite;
|
||||
|
2
node.gyp
2
node.gyp
@ -112,7 +112,6 @@
|
||||
'src/timer_wrap.cc',
|
||||
'src/tty_wrap.cc',
|
||||
'src/process_wrap.cc',
|
||||
'src/v8_typed_array.cc',
|
||||
'src/udp_wrap.cc',
|
||||
# headers to make for a more pleasant IDE experience
|
||||
'src/handle_wrap.h',
|
||||
@ -142,7 +141,6 @@
|
||||
'src/string_bytes.h',
|
||||
'src/stream_wrap.h',
|
||||
'src/tree.h',
|
||||
'src/v8_typed_array.h',
|
||||
'deps/http_parser/http_parser.h',
|
||||
'<(SHARED_INTERMEDIATE_DIR)/node_natives.h',
|
||||
# javascript files to make for an even more pleasant IDE experience
|
||||
|
@ -45,9 +45,9 @@ namespace node {
|
||||
|
||||
namespace cares_wrap {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Array;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
@ -69,7 +69,7 @@ struct ares_task_t {
|
||||
};
|
||||
|
||||
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
static ares_channel ares_channel;
|
||||
static uv_timer_t ares_timer;
|
||||
static RB_HEAD(ares_task_list, ares_task_t) ares_tasks;
|
||||
@ -268,7 +268,8 @@ static void SetAresErrno(int errorno) {
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Value> key = String::NewSymbol("_errno");
|
||||
Local<Value> value = String::NewSymbol(AresErrnoString(errorno));
|
||||
node::process->Set(key, value);
|
||||
Local<Object> process = Local<Object>::New(node_isolate, process_p);
|
||||
process->Set(key, value);
|
||||
}
|
||||
|
||||
|
||||
@ -276,26 +277,18 @@ class QueryWrap {
|
||||
public:
|
||||
QueryWrap() {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
object_ = Persistent<Object>::New(node_isolate, Object::New());
|
||||
persistent().Reset(node_isolate, Object::New());
|
||||
}
|
||||
|
||||
virtual ~QueryWrap() {
|
||||
assert(!object_.IsEmpty());
|
||||
|
||||
object_->Delete(oncomplete_sym);
|
||||
|
||||
object_.Dispose(node_isolate);
|
||||
object_.Clear();
|
||||
}
|
||||
|
||||
Handle<Object> GetObject() {
|
||||
return object_;
|
||||
assert(!persistent().IsEmpty());
|
||||
object()->Delete(oncomplete_sym);
|
||||
persistent().Dispose();
|
||||
}
|
||||
|
||||
void SetOnComplete(Handle<Value> oncomplete) {
|
||||
assert(oncomplete->IsFunction());
|
||||
object_->Set(oncomplete_sym, oncomplete);
|
||||
object()->Set(oncomplete_sym, oncomplete);
|
||||
}
|
||||
|
||||
// Subclasses should implement the appropriate Send method.
|
||||
@ -309,6 +302,14 @@ class QueryWrap {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline Persistent<Object>& persistent() {
|
||||
return object_;
|
||||
}
|
||||
|
||||
inline Local<Object> object() {
|
||||
return Local<Object>::New(node_isolate, persistent());
|
||||
}
|
||||
|
||||
protected:
|
||||
void* GetQueryArg() {
|
||||
return static_cast<void*>(this);
|
||||
@ -343,13 +344,13 @@ class QueryWrap {
|
||||
void CallOnComplete(Local<Value> answer) {
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Value> argv[2] = { Integer::New(0, node_isolate), answer };
|
||||
MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
void CallOnComplete(Local<Value> answer, Local<Value> family) {
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Value> argv[3] = { Integer::New(0, node_isolate), answer, family };
|
||||
MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
void ParseError(int status) {
|
||||
@ -358,7 +359,7 @@ class QueryWrap {
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Value> argv[1] = { Integer::New(-1, node_isolate) };
|
||||
MakeCallback(object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(object(), oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
// Subclasses should implement the appropriate Parse method.
|
||||
@ -730,7 +731,7 @@ class GetHostByNameWrap: public QueryWrap {
|
||||
|
||||
|
||||
template <class Wrap>
|
||||
static Handle<Value> Query(const Arguments& args) {
|
||||
static void Query(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(!args.IsConstructCall());
|
||||
@ -742,8 +743,8 @@ static Handle<Value> Query(const Arguments& args) {
|
||||
|
||||
// We must cache the wrap's js object here, because cares might make the
|
||||
// callback from the wrap->Send stack. This will destroy the wrap's internal
|
||||
// object reference, causing wrap->GetObject() to return undefined.
|
||||
Local<Object> object = Local<Object>::New(node_isolate, wrap->GetObject());
|
||||
// object reference, causing wrap->object() to return an empty handle.
|
||||
Local<Object> object = wrap->object();
|
||||
|
||||
String::Utf8Value name(args[0]);
|
||||
|
||||
@ -751,15 +752,14 @@ static Handle<Value> Query(const Arguments& args) {
|
||||
if (r) {
|
||||
SetAresErrno(r);
|
||||
delete wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(object);
|
||||
args.GetReturnValue().Set(object);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <class Wrap>
|
||||
static Handle<Value> QueryWithFamily(const Arguments& args) {
|
||||
static void QueryWithFamily(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(!args.IsConstructCall());
|
||||
@ -771,8 +771,8 @@ static Handle<Value> QueryWithFamily(const Arguments& args) {
|
||||
|
||||
// We must cache the wrap's js object here, because cares might make the
|
||||
// callback from the wrap->Send stack. This will destroy the wrap's internal
|
||||
// object reference, causing wrap->GetObject() to return undefined.
|
||||
Local<Object> object = Local<Object>::New(node_isolate, wrap->GetObject());
|
||||
// object reference, causing wrap->object() to return an empty handle.
|
||||
Local<Object> object = wrap->object();
|
||||
|
||||
String::Utf8Value name(args[0]);
|
||||
int family = args[1]->Int32Value();
|
||||
@ -781,9 +781,8 @@ static Handle<Value> QueryWithFamily(const Arguments& args) {
|
||||
if (r) {
|
||||
SetAresErrno(r);
|
||||
delete wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(object);
|
||||
args.GetReturnValue().Set(object);
|
||||
}
|
||||
}
|
||||
|
||||
@ -877,31 +876,29 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {
|
||||
uv_freeaddrinfo(res);
|
||||
|
||||
// Make the callback into JavaScript
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap->object(), oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> IsIP(const Arguments& args) {
|
||||
static void IsIP(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
String::AsciiValue ip(args[0]);
|
||||
char address_buffer[sizeof(struct in6_addr)];
|
||||
|
||||
if (uv_inet_pton(AF_INET, *ip, &address_buffer).code == UV_OK) {
|
||||
return scope.Close(v8::Integer::New(4, node_isolate));
|
||||
}
|
||||
int rc = 0;
|
||||
if (uv_inet_pton(AF_INET, *ip, &address_buffer).code == UV_OK)
|
||||
rc = 4;
|
||||
else if (uv_inet_pton(AF_INET6, *ip, &address_buffer).code == UV_OK)
|
||||
rc = 6;
|
||||
|
||||
if (uv_inet_pton(AF_INET6, *ip, &address_buffer).code == UV_OK) {
|
||||
return scope.Close(v8::Integer::New(6, node_isolate));
|
||||
}
|
||||
|
||||
return scope.Close(v8::Integer::New(0, node_isolate));
|
||||
args.GetReturnValue().Set(rc);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> GetAddrInfo(const Arguments& args) {
|
||||
static void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
String::Utf8Value hostname(args[0]);
|
||||
@ -937,14 +934,13 @@ static Handle<Value> GetAddrInfo(const Arguments& args) {
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> GetServers(const Arguments& args) {
|
||||
static void GetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Array> server_array = Array::New();
|
||||
@ -969,11 +965,11 @@ static Handle<Value> GetServers(const Arguments& args) {
|
||||
|
||||
ares_free_data(servers);
|
||||
|
||||
return scope.Close(server_array);
|
||||
args.GetReturnValue().Set(server_array);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> SetServers(const Arguments& args) {
|
||||
static void SetServers(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(args[0]->IsArray());
|
||||
@ -984,7 +980,7 @@ static Handle<Value> SetServers(const Arguments& args) {
|
||||
|
||||
if (len == 0) {
|
||||
int rv = ares_set_servers(ares_channel, NULL);
|
||||
return scope.Close(Integer::New(rv));
|
||||
return args.GetReturnValue().Set(rv);
|
||||
}
|
||||
|
||||
ares_addr_node* servers = new ares_addr_node[len];
|
||||
@ -1039,16 +1035,14 @@ static Handle<Value> SetServers(const Arguments& args) {
|
||||
|
||||
delete[] servers;
|
||||
|
||||
return scope.Close(Integer::New(r));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> StrError(const Arguments& args) {
|
||||
HandleScope scope;
|
||||
|
||||
int r = args[0]->Int32Value();
|
||||
|
||||
return scope.Close(String::New(ares_strerror(r)));
|
||||
static void StrError(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
const char* errmsg = ares_strerror(args[0]->Int32Value());
|
||||
args.GetReturnValue().Set(String::New(errmsg));
|
||||
}
|
||||
|
||||
|
||||
@ -1100,7 +1094,7 @@ static void Initialize(Handle<Object> target) {
|
||||
target->Set(String::NewSymbol("AF_UNSPEC"),
|
||||
Integer::New(AF_UNSPEC, node_isolate));
|
||||
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
}
|
||||
|
||||
|
||||
|
@ -24,20 +24,28 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
using namespace v8;
|
||||
|
||||
namespace node {
|
||||
|
||||
static Persistent<String> change_sym;
|
||||
static Persistent<String> onchange_sym;
|
||||
static Persistent<String> rename_sym;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Cached<String> change_sym;
|
||||
static Cached<String> onchange_sym;
|
||||
static Cached<String> rename_sym;
|
||||
|
||||
class FSEventWrap: public HandleWrap {
|
||||
public:
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
static Handle<Value> Start(const Arguments& args);
|
||||
static Handle<Value> Close(const Arguments& args);
|
||||
static void New(const FunctionCallbackInfo<Value>& args);
|
||||
static void Start(const FunctionCallbackInfo<Value>& args);
|
||||
static void Close(const FunctionCallbackInfo<Value>& args);
|
||||
|
||||
private:
|
||||
FSEventWrap(Handle<Object> object);
|
||||
@ -74,33 +82,28 @@ void FSEventWrap::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "start", Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "close", Close);
|
||||
|
||||
target->Set(String::NewSymbol("FSEvent"),
|
||||
Persistent<FunctionTemplate>::New(node_isolate,
|
||||
t)->GetFunction());
|
||||
target->Set(String::New("FSEvent"), t->GetFunction());
|
||||
|
||||
change_sym = NODE_PSYMBOL("change");
|
||||
onchange_sym = NODE_PSYMBOL("onchange");
|
||||
rename_sym = NODE_PSYMBOL("rename");
|
||||
change_sym = String::New("change");
|
||||
onchange_sym = String::New("onchange");
|
||||
rename_sym = String::New("rename");
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> FSEventWrap::New(const Arguments& args) {
|
||||
void FSEventWrap::New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(args.IsConstructCall());
|
||||
new FSEventWrap(args.This());
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> FSEventWrap::Start(const Arguments& args) {
|
||||
void FSEventWrap::Start(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(FSEventWrap)
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsString()) {
|
||||
return ThrowException(Exception::TypeError(String::New("Bad arguments")));
|
||||
return ThrowTypeError("Bad arguments");
|
||||
}
|
||||
|
||||
String::Utf8Value path(args[0]);
|
||||
@ -116,7 +119,7 @@ Handle<Value> FSEventWrap::Start(const Arguments& args) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
@ -127,7 +130,7 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
|
||||
|
||||
FSEventWrap* wrap = static_cast<FSEventWrap*>(handle->data);
|
||||
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
// We're in a bind here. libuv can set both UV_RENAME and UV_CHANGE but
|
||||
// the Node API only lets us pass a single event to JS land.
|
||||
@ -158,14 +161,18 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
|
||||
Handle<Value> argv[3] = {
|
||||
Integer::New(status, node_isolate),
|
||||
eventStr,
|
||||
filename ? String::New(filename) : v8::Null(node_isolate)
|
||||
Null(node_isolate)
|
||||
};
|
||||
|
||||
MakeCallback(wrap->object_, onchange_sym, ARRAY_SIZE(argv), argv);
|
||||
if (filename != NULL) {
|
||||
argv[2] = String::New(filename);
|
||||
}
|
||||
|
||||
MakeCallback(wrap->object(), onchange_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> FSEventWrap::Close(const Arguments& args) {
|
||||
void FSEventWrap::Close(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// Unwrap manually here. The UNWRAP() macro asserts that wrap != NULL.
|
||||
@ -176,12 +183,10 @@ Handle<Value> FSEventWrap::Close(const Arguments& args) {
|
||||
void* ptr = args.This()->GetAlignedPointerFromInternalField(0);
|
||||
FSEventWrap* wrap = static_cast<FSEventWrap*>(ptr);
|
||||
|
||||
if (wrap == NULL || wrap->initialized_ == false) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
if (wrap == NULL || wrap->initialized_ == false) return;
|
||||
wrap->initialized_ = false;
|
||||
|
||||
return HandleWrap::Close(args);
|
||||
HandleWrap::Close(args);
|
||||
}
|
||||
|
||||
|
||||
|
@ -25,20 +25,17 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
|
||||
|
||||
// defined in node.cc
|
||||
extern QUEUE handle_wrap_queue;
|
||||
static Persistent<String> close_sym;
|
||||
static Cached<String> close_sym;
|
||||
|
||||
|
||||
void HandleWrap::Initialize(Handle<Object> target) {
|
||||
@ -46,7 +43,7 @@ void HandleWrap::Initialize(Handle<Object> target) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> HandleWrap::Ref(const Arguments& args) {
|
||||
void HandleWrap::Ref(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP_NO_ABORT(HandleWrap)
|
||||
@ -55,12 +52,10 @@ Handle<Value> HandleWrap::Ref(const Arguments& args) {
|
||||
uv_ref(wrap->handle__);
|
||||
wrap->flags_ &= ~kUnref;
|
||||
}
|
||||
|
||||
return v8::Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> HandleWrap::Unref(const Arguments& args) {
|
||||
void HandleWrap::Unref(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP_NO_ABORT(HandleWrap)
|
||||
@ -69,33 +64,27 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
|
||||
uv_unref(wrap->handle__);
|
||||
wrap->flags_ |= kUnref;
|
||||
}
|
||||
|
||||
return v8::Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> HandleWrap::Close(const Arguments& args) {
|
||||
void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
HandleWrap *wrap = static_cast<HandleWrap*>(
|
||||
args.This()->GetAlignedPointerFromInternalField(0));
|
||||
|
||||
// guard against uninitialized handle or double close
|
||||
if (wrap == NULL || wrap->handle__ == NULL) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
if (wrap == NULL || wrap->handle__ == NULL) return;
|
||||
|
||||
assert(!wrap->object_.IsEmpty());
|
||||
assert(!wrap->persistent().IsEmpty());
|
||||
uv_close(wrap->handle__, OnClose);
|
||||
wrap->handle__ = NULL;
|
||||
|
||||
if (args[0]->IsFunction()) {
|
||||
if (close_sym.IsEmpty() == true) close_sym = NODE_PSYMBOL("close");
|
||||
wrap->object_->Set(close_sym, args[0]);
|
||||
if (close_sym.IsEmpty() == true) close_sym = String::New("close");
|
||||
wrap->object()->Set(close_sym, args[0]);
|
||||
wrap->flags_ |= kCloseCallback;
|
||||
}
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -105,16 +94,16 @@ HandleWrap::HandleWrap(Handle<Object> object, uv_handle_t* h) {
|
||||
handle__->data = this;
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
assert(object_.IsEmpty());
|
||||
assert(persistent().IsEmpty());
|
||||
assert(object->InternalFieldCount() > 0);
|
||||
object_ = v8::Persistent<v8::Object>::New(node_isolate, object);
|
||||
object_->SetAlignedPointerInInternalField(0, this);
|
||||
persistent().Reset(node_isolate, object);
|
||||
object->SetAlignedPointerInInternalField(0, this);
|
||||
QUEUE_INSERT_TAIL(&handle_wrap_queue, &handle_wrap_queue_);
|
||||
}
|
||||
|
||||
|
||||
HandleWrap::~HandleWrap() {
|
||||
assert(object_.IsEmpty());
|
||||
assert(persistent().IsEmpty());
|
||||
QUEUE_REMOVE(&handle_wrap_queue_);
|
||||
}
|
||||
|
||||
@ -123,20 +112,21 @@ void HandleWrap::OnClose(uv_handle_t* handle) {
|
||||
HandleWrap* wrap = static_cast<HandleWrap*>(handle->data);
|
||||
|
||||
// The wrap object should still be there.
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
// But the handle pointer should be gone.
|
||||
assert(wrap->handle__ == NULL);
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Object> object = wrap->object();
|
||||
|
||||
if (wrap->flags_ & kCloseCallback) {
|
||||
assert(close_sym.IsEmpty() == false);
|
||||
MakeCallback(wrap->object_, close_sym, 0, NULL);
|
||||
MakeCallback(object, close_sym, 0, NULL);
|
||||
}
|
||||
|
||||
wrap->object_->SetAlignedPointerInInternalField(0, NULL);
|
||||
wrap->object_.Dispose(node_isolate);
|
||||
wrap->object_.Clear();
|
||||
|
||||
object->SetAlignedPointerInInternalField(0, NULL);
|
||||
wrap->persistent().Dispose();
|
||||
delete wrap;
|
||||
}
|
||||
|
||||
|
@ -53,31 +53,38 @@ namespace node {
|
||||
args.This()->GetAlignedPointerFromInternalField(0));
|
||||
|
||||
class HandleWrap {
|
||||
public:
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Ref(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Unref(const v8::Arguments& args);
|
||||
public:
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Ref(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Unref(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
inline uv_handle_t* GetHandle() { return handle__; };
|
||||
inline uv_handle_t* GetHandle() { return handle__; };
|
||||
|
||||
protected:
|
||||
HandleWrap(v8::Handle<v8::Object> object, uv_handle_t* handle);
|
||||
virtual ~HandleWrap();
|
||||
protected:
|
||||
HandleWrap(v8::Handle<v8::Object> object, uv_handle_t* handle);
|
||||
virtual ~HandleWrap();
|
||||
|
||||
v8::Persistent<v8::Object> object_;
|
||||
inline v8::Local<v8::Object> object() {
|
||||
return v8::Local<v8::Object>::New(node_isolate, persistent());
|
||||
}
|
||||
|
||||
private:
|
||||
friend v8::Handle<v8::Value> GetActiveHandles(const v8::Arguments&);
|
||||
static void OnClose(uv_handle_t* handle);
|
||||
QUEUE handle_wrap_queue_;
|
||||
// Using double underscore due to handle_ member in tcp_wrap. Probably
|
||||
// tcp_wrap should rename it's member to 'handle'.
|
||||
uv_handle_t* handle__;
|
||||
unsigned int flags_;
|
||||
inline v8::Persistent<v8::Object>& persistent() {
|
||||
return object_;
|
||||
}
|
||||
|
||||
static const unsigned int kUnref = 1;
|
||||
static const unsigned int kCloseCallback = 2;
|
||||
private:
|
||||
friend void GetActiveHandles(const v8::FunctionCallbackInfo<v8::Value>&);
|
||||
static void OnClose(uv_handle_t* handle);
|
||||
v8::Persistent<v8::Object> object_;
|
||||
QUEUE handle_wrap_queue_;
|
||||
// Using double underscore due to handle_ member in tcp_wrap. Probably
|
||||
// tcp_wrap should rename it's member to 'handle'.
|
||||
uv_handle_t* handle__;
|
||||
unsigned int flags_;
|
||||
|
||||
static const unsigned int kUnref = 1;
|
||||
static const unsigned int kCloseCallback = 2;
|
||||
};
|
||||
|
||||
|
||||
|
502
src/node.cc
502
src/node.cc
File diff suppressed because it is too large
Load Diff
55
src/node.h
55
src/node.h
@ -95,10 +95,6 @@ v8::Handle<v8::Object> SetupProcessObject(int argc, char *argv[]);
|
||||
void Load(v8::Handle<v8::Object> process);
|
||||
void EmitExit(v8::Handle<v8::Object> process);
|
||||
|
||||
#define NODE_PSYMBOL(s) \
|
||||
v8::Persistent<v8::String>::New(v8::Isolate::GetCurrent(), \
|
||||
v8::String::NewSymbol(s))
|
||||
|
||||
/* Converts a unixtime to V8 Date */
|
||||
#define NODE_UNIXTIME_V8(t) v8::Date::New(1000*static_cast<double>(t))
|
||||
#define NODE_V8_UNIXTIME(v) (static_cast<double>((v)->NumberValue())/1000.0);
|
||||
@ -109,25 +105,25 @@ void EmitExit(v8::Handle<v8::Object> process);
|
||||
static_cast<v8::PropertyAttribute>( \
|
||||
v8::ReadOnly|v8::DontDelete))
|
||||
|
||||
template <typename target_t>
|
||||
void SetMethod(target_t obj, const char* name,
|
||||
v8::InvocationCallback callback)
|
||||
{
|
||||
obj->Set(v8::String::NewSymbol(name),
|
||||
v8::FunctionTemplate::New(callback)->GetFunction());
|
||||
// Used to be a macro, hence the uppercase name.
|
||||
template <typename TypeName>
|
||||
inline void NODE_SET_METHOD(TypeName& recv,
|
||||
const char* name,
|
||||
v8::FunctionCallback callback) {
|
||||
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(callback);
|
||||
recv->Set(v8::String::New(name), t->GetFunction());
|
||||
}
|
||||
#define NODE_SET_METHOD node::NODE_SET_METHOD
|
||||
|
||||
template <typename target_t>
|
||||
void SetPrototypeMethod(target_t target,
|
||||
const char* name, v8::InvocationCallback callback)
|
||||
{
|
||||
v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(callback);
|
||||
target->PrototypeTemplate()->Set(v8::String::NewSymbol(name), templ);
|
||||
// Used to be a macro, hence the uppercase name.
|
||||
// Not a template because it only makes sense for FunctionTemplates.
|
||||
inline void NODE_SET_PROTOTYPE_METHOD(v8::Handle<v8::FunctionTemplate> recv,
|
||||
const char* name,
|
||||
v8::FunctionCallback callback) {
|
||||
v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New(callback);
|
||||
recv->PrototypeTemplate()->Set(v8::String::New(name), t->GetFunction());
|
||||
}
|
||||
|
||||
// for backwards compatibility
|
||||
#define NODE_SET_METHOD node::SetMethod
|
||||
#define NODE_SET_PROTOTYPE_METHOD node::SetPrototypeMethod
|
||||
#define NODE_SET_PROTOTYPE_METHOD node::NODE_SET_PROTOTYPE_METHOD
|
||||
|
||||
enum encoding {ASCII, UTF8, BASE64, UCS2, BINARY, HEX, BUFFER};
|
||||
enum encoding ParseEncoding(v8::Handle<v8::Value> encoding_v,
|
||||
@ -151,25 +147,6 @@ NODE_EXTERN ssize_t DecodeWrite(char *buf,
|
||||
v8::Local<v8::Object> BuildStatsObject(const uv_stat_t* s);
|
||||
|
||||
|
||||
static inline v8::Persistent<v8::Function>* cb_persist(v8::Local<v8::Value> v) {
|
||||
v8::Persistent<v8::Function>* fn = new v8::Persistent<v8::Function>();
|
||||
*fn = v8::Persistent<v8::Function>::New(v8::Isolate::GetCurrent(),
|
||||
v.As<v8::Function>());
|
||||
return fn;
|
||||
}
|
||||
|
||||
static inline v8::Persistent<v8::Function>* cb_unwrap(void *data) {
|
||||
v8::Persistent<v8::Function> *cb =
|
||||
reinterpret_cast<v8::Persistent<v8::Function>*>(data);
|
||||
assert((*cb)->IsFunction());
|
||||
return cb;
|
||||
}
|
||||
|
||||
static inline void cb_destroy(v8::Persistent<v8::Function> * cb) {
|
||||
cb->Dispose(v8::Isolate::GetCurrent());
|
||||
delete cb;
|
||||
}
|
||||
|
||||
NODE_EXTERN v8::Local<v8::Value> ErrnoException(int errorno,
|
||||
const char *syscall = NULL,
|
||||
const char *msg = "",
|
||||
|
@ -57,9 +57,8 @@ namespace node {
|
||||
|
||||
namespace Buffer {
|
||||
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -72,8 +71,7 @@ using v8::Uint32;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
|
||||
|
||||
Persistent<Function> p_buffer_fn;
|
||||
static Persistent<Function> p_buffer_fn;
|
||||
|
||||
|
||||
bool HasInstance(Handle<Value> val) {
|
||||
@ -140,7 +138,7 @@ Local<Object> New(size_t length) {
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = p_buffer_fn->NewInstance(2, argv);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
|
||||
// TODO(trevnorris): done like this to handle HasInstance since only checks
|
||||
// if external array data has been set, but would like to use a better
|
||||
@ -172,7 +170,7 @@ Local<Object> New(const char* data, size_t length) {
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = p_buffer_fn->NewInstance(2, argv);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
|
||||
// TODO(trevnorris): done like this to handle HasInstance since only checks
|
||||
// if external array data has been set, but would like to use a better
|
||||
@ -206,7 +204,7 @@ Local<Object> New(char* data,
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = p_buffer_fn->NewInstance(2, argv);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
|
||||
smalloc::Alloc(obj, data, length, callback, hint);
|
||||
|
||||
@ -224,7 +222,7 @@ Local<Object> Use(char* data, uint32_t length) {
|
||||
// of GC reclaiming the values prematurely.
|
||||
argv[0] = Undefined(node_isolate);
|
||||
argv[1] = Uint32::New(length, node_isolate);
|
||||
Local<Object> obj = p_buffer_fn->NewInstance(2, argv);
|
||||
Local<Object> obj = NewInstance(p_buffer_fn, ARRAY_SIZE(argv), argv);
|
||||
|
||||
smalloc::Alloc(obj, data, length);
|
||||
|
||||
@ -233,49 +231,49 @@ Local<Object> Use(char* data, uint32_t length) {
|
||||
|
||||
|
||||
template <encoding encoding>
|
||||
Handle<Value> StringSlice(const Arguments& args) {
|
||||
void StringSlice(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
ARGS_THIS(args.This())
|
||||
SLICE_START_END(args[0], args[1], obj_length)
|
||||
|
||||
return scope.Close(StringBytes::Encode(obj_data + start, length, encoding));
|
||||
args.GetReturnValue().Set(
|
||||
StringBytes::Encode(obj_data + start, length, encoding));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> BinarySlice(const Arguments& args) {
|
||||
return StringSlice<BINARY>(args);
|
||||
void BinarySlice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<BINARY>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> AsciiSlice(const Arguments& args) {
|
||||
return StringSlice<ASCII>(args);
|
||||
void AsciiSlice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<ASCII>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Utf8Slice(const Arguments& args) {
|
||||
return StringSlice<UTF8>(args);
|
||||
void Utf8Slice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<UTF8>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Ucs2Slice(const Arguments& args) {
|
||||
return StringSlice<UCS2>(args);
|
||||
void Ucs2Slice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<UCS2>(args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Handle<Value> HexSlice(const Arguments& args) {
|
||||
return StringSlice<HEX>(args);
|
||||
void HexSlice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<HEX>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Base64Slice(const Arguments& args) {
|
||||
return StringSlice<BASE64>(args);
|
||||
void Base64Slice(const FunctionCallbackInfo<Value>& args) {
|
||||
StringSlice<BASE64>(args);
|
||||
}
|
||||
|
||||
|
||||
// bytesCopied = buffer.copy(target[, targetStart][, sourceStart][, sourceEnd]);
|
||||
Handle<Value> Copy(const Arguments &args) {
|
||||
void Copy(const FunctionCallbackInfo<Value> &args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> target = args[0]->ToObject();
|
||||
@ -297,7 +295,7 @@ Handle<Value> Copy(const Arguments &args) {
|
||||
|
||||
// Copy 0 bytes; we're done
|
||||
if (target_start >= target_length || source_start >= source_end)
|
||||
return scope.Close(Uint32::New(0, node_isolate));
|
||||
return args.GetReturnValue().Set(0);
|
||||
|
||||
if (source_start > obj_length)
|
||||
return ThrowRangeError("out of range index");
|
||||
@ -305,27 +303,27 @@ Handle<Value> Copy(const Arguments &args) {
|
||||
if (source_end - source_start > target_length - target_start)
|
||||
source_end = source_start + target_length - target_start;
|
||||
|
||||
size_t to_copy = MIN(MIN(source_end - source_start,
|
||||
target_length - target_start),
|
||||
obj_length - source_start);
|
||||
uint32_t to_copy = MIN(MIN(source_end - source_start,
|
||||
target_length - target_start),
|
||||
obj_length - source_start);
|
||||
|
||||
memmove(target_data + target_start, obj_data + source_start, to_copy);
|
||||
|
||||
return scope.Close(Uint32::New(to_copy, node_isolate));
|
||||
args.GetReturnValue().Set(to_copy);
|
||||
}
|
||||
|
||||
|
||||
// buffer.fill(value[, start][, end]);
|
||||
Handle<Value> Fill(const Arguments &args) {
|
||||
void Fill(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
ARGS_THIS(args.This())
|
||||
SLICE_START_END(args[1], args[2], obj_length)
|
||||
args.GetReturnValue().Set(args.This());
|
||||
|
||||
if (args[0]->IsNumber()) {
|
||||
int value = args[0]->Uint32Value() & 255;
|
||||
memset(obj_data + start, value, length);
|
||||
return args.This();
|
||||
return;
|
||||
}
|
||||
|
||||
String::Utf8Value at(args[0]);
|
||||
@ -335,7 +333,7 @@ Handle<Value> Fill(const Arguments &args) {
|
||||
if (at_length == 1) {
|
||||
int value = static_cast<int>((*at)[0]);
|
||||
memset(obj_data + start, value, length);
|
||||
return args.This();
|
||||
return;
|
||||
}
|
||||
|
||||
size_t in_there = at_length;
|
||||
@ -344,7 +342,7 @@ Handle<Value> Fill(const Arguments &args) {
|
||||
memcpy(obj_data + start, *at, MIN(at_length, length));
|
||||
|
||||
if (at_length >= length)
|
||||
return args.This();
|
||||
return;
|
||||
|
||||
while (in_there < length - in_there) {
|
||||
memcpy(ptr, obj_data + start, in_there);
|
||||
@ -356,13 +354,11 @@ Handle<Value> Fill(const Arguments &args) {
|
||||
memcpy(ptr, obj_data + start, length - in_there);
|
||||
in_there = length;
|
||||
}
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
|
||||
template <encoding encoding>
|
||||
Handle<Value> StringWrite(const Arguments& args) {
|
||||
void StringWrite(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
ARGS_THIS(args.This())
|
||||
@ -384,7 +380,7 @@ Handle<Value> StringWrite(const Arguments& args) {
|
||||
max_length = MIN(obj_length - offset, max_length);
|
||||
|
||||
if (max_length == 0)
|
||||
return scope.Close(Uint32::New(0, node_isolate));
|
||||
return args.GetReturnValue().Set(0);
|
||||
|
||||
if (encoding == UCS2)
|
||||
max_length = max_length / 2;
|
||||
@ -392,43 +388,42 @@ Handle<Value> StringWrite(const Arguments& args) {
|
||||
if (offset >= obj_length)
|
||||
return ThrowRangeError("Offset is out of bounds");
|
||||
|
||||
size_t written = StringBytes::Write(obj_data + offset,
|
||||
max_length,
|
||||
str,
|
||||
encoding,
|
||||
NULL);
|
||||
|
||||
return scope.Close(Uint32::New(written, node_isolate));
|
||||
uint32_t written = StringBytes::Write(obj_data + offset,
|
||||
max_length,
|
||||
str,
|
||||
encoding,
|
||||
NULL);
|
||||
args.GetReturnValue().Set(written);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Base64Write(const Arguments& args) {
|
||||
return StringWrite<BASE64>(args);
|
||||
void Base64Write(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<BASE64>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> BinaryWrite(const Arguments& args) {
|
||||
return StringWrite<BINARY>(args);
|
||||
void BinaryWrite(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<BINARY>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Utf8Write(const Arguments& args) {
|
||||
return StringWrite<UTF8>(args);
|
||||
void Utf8Write(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<UTF8>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> Ucs2Write(const Arguments& args) {
|
||||
return StringWrite<UCS2>(args);
|
||||
void Ucs2Write(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<UCS2>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> HexWrite(const Arguments& args) {
|
||||
return StringWrite<HEX>(args);
|
||||
void HexWrite(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<HEX>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> AsciiWrite(const Arguments& args) {
|
||||
return StringWrite<ASCII>(args);
|
||||
void AsciiWrite(const FunctionCallbackInfo<Value>& args) {
|
||||
StringWrite<ASCII>(args);
|
||||
}
|
||||
|
||||
|
||||
@ -443,7 +438,7 @@ static inline void Swizzle(char* start, unsigned int len) {
|
||||
|
||||
|
||||
template <typename T, enum Endianness endianness>
|
||||
Handle<Value> ReadFloatGeneric(const Arguments& args) {
|
||||
void ReadFloatGeneric(const FunctionCallbackInfo<Value>& args) {
|
||||
bool doAssert = !args[1]->BooleanValue();
|
||||
size_t offset;
|
||||
|
||||
@ -466,32 +461,32 @@ Handle<Value> ReadFloatGeneric(const Arguments& args) {
|
||||
memcpy(na.bytes, ptr, sizeof(na.bytes));
|
||||
if (endianness != GetEndianness()) Swizzle(na.bytes, sizeof(na.bytes));
|
||||
|
||||
return Number::New(na.val);
|
||||
args.GetReturnValue().Set(na.val);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> ReadFloatLE(const Arguments& args) {
|
||||
return ReadFloatGeneric<float, kLittleEndian>(args);
|
||||
void ReadFloatLE(const FunctionCallbackInfo<Value>& args) {
|
||||
ReadFloatGeneric<float, kLittleEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> ReadFloatBE(const Arguments& args) {
|
||||
return ReadFloatGeneric<float, kBigEndian>(args);
|
||||
void ReadFloatBE(const FunctionCallbackInfo<Value>& args) {
|
||||
ReadFloatGeneric<float, kBigEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> ReadDoubleLE(const Arguments& args) {
|
||||
return ReadFloatGeneric<double, kLittleEndian>(args);
|
||||
void ReadDoubleLE(const FunctionCallbackInfo<Value>& args) {
|
||||
ReadFloatGeneric<double, kLittleEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> ReadDoubleBE(const Arguments& args) {
|
||||
return ReadFloatGeneric<double, kBigEndian>(args);
|
||||
void ReadDoubleBE(const FunctionCallbackInfo<Value>& args) {
|
||||
ReadFloatGeneric<double, kBigEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, enum Endianness endianness>
|
||||
Handle<Value> WriteFloatGeneric(const Arguments& args) {
|
||||
void WriteFloatGeneric(const FunctionCallbackInfo<Value>& args) {
|
||||
bool doAssert = !args[2]->BooleanValue();
|
||||
|
||||
T val = static_cast<T>(args[0]->NumberValue());
|
||||
@ -515,32 +510,30 @@ Handle<Value> WriteFloatGeneric(const Arguments& args) {
|
||||
char* ptr = static_cast<char*>(data) + offset;
|
||||
if (endianness != GetEndianness()) Swizzle(na.bytes, sizeof(na.bytes));
|
||||
memcpy(ptr, na.bytes, sizeof(na.bytes));
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WriteFloatLE(const Arguments& args) {
|
||||
return WriteFloatGeneric<float, kLittleEndian>(args);
|
||||
void WriteFloatLE(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteFloatGeneric<float, kLittleEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WriteFloatBE(const Arguments& args) {
|
||||
return WriteFloatGeneric<float, kBigEndian>(args);
|
||||
void WriteFloatBE(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteFloatGeneric<float, kBigEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WriteDoubleLE(const Arguments& args) {
|
||||
return WriteFloatGeneric<double, kLittleEndian>(args);
|
||||
void WriteDoubleLE(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteFloatGeneric<double, kLittleEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WriteDoubleBE(const Arguments& args) {
|
||||
return WriteFloatGeneric<double, kBigEndian>(args);
|
||||
void WriteDoubleBE(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteFloatGeneric<double, kBigEndian>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> ByteLength(const Arguments &args) {
|
||||
void ByteLength(const FunctionCallbackInfo<Value> &args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (!args[0]->IsString())
|
||||
@ -549,18 +542,19 @@ Handle<Value> ByteLength(const Arguments &args) {
|
||||
Local<String> s = args[0]->ToString();
|
||||
enum encoding e = ParseEncoding(args[1], UTF8);
|
||||
|
||||
return scope.Close(Uint32::New(StringBytes::Size(s, e), node_isolate));
|
||||
uint32_t size = StringBytes::Size(s, e);
|
||||
args.GetReturnValue().Set(size);
|
||||
}
|
||||
|
||||
|
||||
// pass Buffer object to load prototype methods
|
||||
Handle<Value> SetupBufferJS(const Arguments& args) {
|
||||
void SetupBufferJS(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(args[0]->IsFunction());
|
||||
|
||||
Local<Function> bv = args[0].As<Function>();
|
||||
p_buffer_fn = Persistent<Function>::New(node_isolate, bv);
|
||||
p_buffer_fn.Reset(node_isolate, bv);
|
||||
Local<Value> proto_v = bv->Get(String::New("prototype"));
|
||||
|
||||
assert(proto_v->IsObject());
|
||||
@ -599,8 +593,6 @@ Handle<Value> SetupBufferJS(const Arguments& args) {
|
||||
|
||||
// for backwards compatibility
|
||||
proto->Set(String::New("offset"), Uint32::New(0, node_isolate), v8::ReadOnly);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#include "node_counters.h"
|
||||
|
||||
#include "uv.h"
|
||||
|
||||
#include <string.h>
|
||||
@ -28,60 +27,55 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::GCCallbackFlags;
|
||||
using v8::GCEpilogueCallback;
|
||||
using v8::GCPrologueCallback;
|
||||
using v8::GCType;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static uint64_t counter_gc_start_time;
|
||||
static uint64_t counter_gc_end_time;
|
||||
|
||||
#define SLURP_OBJECT(obj, member, valp) \
|
||||
if (!(obj)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"object for " #obj " to contain object member " #member)))); \
|
||||
} \
|
||||
*valp = Local<Object>::Cast(obj->Get(String::New(#member)));
|
||||
|
||||
|
||||
Handle<Value> COUNTER_NET_SERVER_CONNECTION(const Arguments& args) {
|
||||
void COUNTER_NET_SERVER_CONNECTION(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_SERVER_CONN_OPEN();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> COUNTER_NET_SERVER_CONNECTION_CLOSE(const Arguments& args) {
|
||||
void COUNTER_NET_SERVER_CONNECTION_CLOSE(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_SERVER_CONN_CLOSE();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> COUNTER_HTTP_SERVER_REQUEST(const Arguments& args) {
|
||||
void COUNTER_HTTP_SERVER_REQUEST(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_HTTP_SERVER_REQUEST();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> COUNTER_HTTP_SERVER_RESPONSE(const Arguments& args) {
|
||||
void COUNTER_HTTP_SERVER_RESPONSE(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_HTTP_SERVER_RESPONSE();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> COUNTER_HTTP_CLIENT_REQUEST(const Arguments& args) {
|
||||
void COUNTER_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_HTTP_CLIENT_REQUEST();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> COUNTER_HTTP_CLIENT_RESPONSE(const Arguments& args) {
|
||||
void COUNTER_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo<Value>&) {
|
||||
NODE_COUNT_HTTP_CLIENT_RESPONSE();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
static void counter_gc_start(GCType type, GCCallbackFlags flags) {
|
||||
counter_gc_start_time = NODE_COUNT_GET_GC_RAWTIME();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -98,33 +92,30 @@ static void counter_gc_done(GCType type, GCCallbackFlags flags) {
|
||||
counter_gc_end_time = endgc;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define NODE_PROBE(name) #name, name
|
||||
|
||||
void InitPerfCounters(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
static struct {
|
||||
const char* name;
|
||||
Handle<Value> (*func)(const Arguments&);
|
||||
Persistent<FunctionTemplate> templ;
|
||||
void (*func)(const FunctionCallbackInfo<Value>&);
|
||||
} tab[] = {
|
||||
#define NODE_PROBE(name) #name, name
|
||||
{ NODE_PROBE(COUNTER_NET_SERVER_CONNECTION) },
|
||||
{ NODE_PROBE(COUNTER_NET_SERVER_CONNECTION_CLOSE) },
|
||||
{ NODE_PROBE(COUNTER_HTTP_SERVER_REQUEST) },
|
||||
{ NODE_PROBE(COUNTER_HTTP_SERVER_RESPONSE) },
|
||||
{ NODE_PROBE(COUNTER_HTTP_CLIENT_REQUEST) },
|
||||
{ NODE_PROBE(COUNTER_HTTP_CLIENT_RESPONSE) }
|
||||
#undef NODE_PROBE
|
||||
};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
tab[i].templ = Persistent<FunctionTemplate>::New(node_isolate,
|
||||
FunctionTemplate::New(tab[i].func));
|
||||
target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
|
||||
Local<String> key = String::New(tab[i].name);
|
||||
Local<Value> val = FunctionTemplate::New(tab[i].func)->GetFunction();
|
||||
target->Set(key, val);
|
||||
}
|
||||
|
||||
// Only Windows performance counters supported
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -64,19 +64,21 @@ class SecureContext : ObjectWrap {
|
||||
|
||||
protected:
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Init(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetKey(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetCert(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> AddCACert(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> AddCRL(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> AddRootCerts(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetCiphers(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetOptions(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetSessionIdContext(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetSessionTimeout(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> LoadPKCS12(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetCert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void AddCACert(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void AddCRL(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void AddRootCerts(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetCiphers(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetSessionIdContext(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetSessionTimeout(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void LoadPKCS12(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
static SSL_SESSION* GetSessionCallback(SSL* s,
|
||||
unsigned char* key,
|
||||
@ -172,48 +174,52 @@ class Connection : ObjectWrap {
|
||||
#endif
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> EncIn(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ClearOut(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ClearPending(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> EncPending(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> EncOut(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ClearIn(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPeerCertificate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> LoadSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> IsSessionReused(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> IsInitFinished(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> VerifyError(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetCurrentCipher(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Shutdown(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ReceivedShutdown(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EncIn(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ClearOut(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ClearPending(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EncPending(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EncOut(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ClearIn(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPeerCertificate(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsInitFinished(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ReceivedShutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Close(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
// NPN
|
||||
static v8::Handle<v8::Value> GetNegotiatedProto(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetNPNProtocols(const v8::Arguments& args);
|
||||
static int AdvertiseNextProtoCallback_(SSL *s,
|
||||
const unsigned char **data,
|
||||
unsigned int *len,
|
||||
void *arg);
|
||||
static int SelectNextProtoCallback_(SSL *s,
|
||||
unsigned char **out, unsigned char *outlen,
|
||||
static void GetNegotiatedProto(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static int AdvertiseNextProtoCallback_(SSL* s,
|
||||
const unsigned char** data,
|
||||
unsigned int* len,
|
||||
void* arg);
|
||||
static int SelectNextProtoCallback_(SSL* s,
|
||||
unsigned char** out,
|
||||
unsigned char* outlen,
|
||||
const unsigned char* in,
|
||||
unsigned int inlen, void *arg);
|
||||
unsigned int inlen,
|
||||
void* arg);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
// SNI
|
||||
static v8::Handle<v8::Value> GetServername(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetSNICallback(const v8::Arguments& args);
|
||||
static int SelectSNIContextCallback_(SSL *s, int *ad, void* arg);
|
||||
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetSNICallback(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static int SelectSNIContextCallback_(SSL* s, int* ad, void* arg);
|
||||
#endif
|
||||
|
||||
int HandleBIOError(BIO *bio, const char* func, int rv);
|
||||
int HandleBIOError(BIO* bio, const char* func, int rv);
|
||||
|
||||
enum ZeroStatus {
|
||||
kZeroIsNotAnError,
|
||||
@ -230,7 +236,7 @@ class Connection : ObjectWrap {
|
||||
void ClearError();
|
||||
void SetShutdownFlags();
|
||||
|
||||
static Connection* Unwrap(const v8::Arguments& args) {
|
||||
static Connection* Unwrap(const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
Connection* ss = ObjectWrap::Unwrap<Connection>(args.This());
|
||||
ss->ClearError();
|
||||
return ss;
|
||||
@ -254,14 +260,14 @@ class Connection : ObjectWrap {
|
||||
}
|
||||
|
||||
#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
if (!npnProtos_.IsEmpty()) npnProtos_.Dispose(node_isolate);
|
||||
if (!selectedNPNProto_.IsEmpty()) selectedNPNProto_.Dispose(node_isolate);
|
||||
npnProtos_.Dispose();
|
||||
selectedNPNProto_.Dispose();
|
||||
#endif
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
if (!sniObject_.IsEmpty()) sniObject_.Dispose(node_isolate);
|
||||
if (!sniContext_.IsEmpty()) sniContext_.Dispose(node_isolate);
|
||||
if (!servername_.IsEmpty()) servername_.Dispose(node_isolate);
|
||||
sniObject_.Dispose();
|
||||
sniContext_.Dispose();
|
||||
servername_.Dispose();
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -291,22 +297,18 @@ class CipherBase : public ObjectWrap {
|
||||
kDecipher
|
||||
};
|
||||
|
||||
v8::Handle<v8::Value> Init(char* cipher_type, char* key_buf, int key_buf_len);
|
||||
v8::Handle<v8::Value> InitIv(char* cipher_type,
|
||||
char* key,
|
||||
int key_len,
|
||||
char* iv,
|
||||
int iv_len);
|
||||
void Init(char* cipher_type, char* key_buf, int key_buf_len);
|
||||
void InitIv(char* cipher_type, char* key, int key_len, char* iv, int iv_len);
|
||||
bool Update(char* data, int len, unsigned char** out, int* out_len);
|
||||
bool Final(unsigned char** out, int *out_len);
|
||||
bool SetAutoPadding(bool auto_padding);
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Init(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> InitIv(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Update(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Final(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetAutoPadding(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Init(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void InitIv(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Update(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Final(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetAutoPadding(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
CipherBase(CipherKind kind) : cipher_(NULL),
|
||||
initialised_(false),
|
||||
@ -330,14 +332,14 @@ class Hmac : public ObjectWrap {
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
protected:
|
||||
v8::Handle<v8::Value> HmacInit(char* hashType, char* key, int key_len);
|
||||
void HmacInit(char* hashType, char* key, int key_len);
|
||||
bool HmacUpdate(char* data, int len);
|
||||
bool HmacDigest(unsigned char** md_value, unsigned int* md_len);
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> HmacInit(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> HmacUpdate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> HmacDigest(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void HmacInit(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void HmacUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void HmacDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
Hmac() : md_(NULL), initialised_(false) {
|
||||
}
|
||||
@ -361,9 +363,9 @@ class Hash : public ObjectWrap {
|
||||
bool HashUpdate(char* data, int len);
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> HashUpdate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> HashDigest(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void HashUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void HashDigest(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
Hash() : md_(NULL), initialised_(false) {
|
||||
}
|
||||
@ -383,7 +385,7 @@ class Sign : public ObjectWrap {
|
||||
public:
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
|
||||
v8::Handle<v8::Value> SignInit(const char* sign_type);
|
||||
void SignInit(const char* sign_type);
|
||||
bool SignUpdate(char* data, int len);
|
||||
bool SignFinal(unsigned char** md_value,
|
||||
unsigned int *md_len,
|
||||
@ -391,10 +393,10 @@ class Sign : public ObjectWrap {
|
||||
int key_pem_len);
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SignInit(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SignUpdate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SignFinal(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SignInit(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SignUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SignFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
Sign() : md_(NULL), initialised_(false) {
|
||||
}
|
||||
@ -414,18 +416,18 @@ class Verify : public ObjectWrap {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
v8::Handle<v8::Value> VerifyInit(const char* verify_type);
|
||||
void VerifyInit(const char* verify_type);
|
||||
bool VerifyUpdate(char* data, int len);
|
||||
v8::Handle<v8::Value> VerifyFinal(char* key_pem,
|
||||
int key_pem_len,
|
||||
unsigned char* sig,
|
||||
int siglen);
|
||||
bool VerifyFinal(char* key_pem,
|
||||
int key_pem_len,
|
||||
unsigned char* sig,
|
||||
int siglen);
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> New (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> VerifyInit(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> VerifyUpdate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> VerifyFinal(const v8::Arguments& args);
|
||||
static void New (const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyInit(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyUpdate(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyFinal(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
Verify() : md_(NULL), initialised_(false) {
|
||||
}
|
||||
@ -451,16 +453,17 @@ class DiffieHellman : public ObjectWrap {
|
||||
bool Init(unsigned char* p, int p_len, unsigned char* g, int g_len);
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> DiffieHellmanGroup(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GenerateKeys(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPrime(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetGenerator(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPublicKey(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPrivateKey(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ComputeSecret(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetPublicKey(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetPrivateKey(const v8::Arguments& args);
|
||||
static void DiffieHellmanGroup(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GenerateKeys(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPrime(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetGenerator(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ComputeSecret(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetPublicKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetPrivateKey(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
DiffieHellman() : ObjectWrap(), initialised_(false), dh(NULL) {
|
||||
}
|
||||
|
@ -59,12 +59,23 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::GCCallbackFlags;
|
||||
using v8::GCEpilogueCallback;
|
||||
using v8::GCPrologueCallback;
|
||||
using v8::GCType;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
#define SLURP_STRING(obj, member, valp) \
|
||||
if (!(obj)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"object for " #obj " to contain string member " #member)))); \
|
||||
return ThrowError( \
|
||||
"expected object for " #obj " to contain string member " #member); \
|
||||
} \
|
||||
String::Utf8Value _##member(obj->Get(String::New(#member))); \
|
||||
if ((*(const char **)valp = *_##member) == NULL) \
|
||||
@ -72,22 +83,22 @@ using namespace v8;
|
||||
|
||||
#define SLURP_INT(obj, member, valp) \
|
||||
if (!(obj)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"object for " #obj " to contain integer member " #member)))); \
|
||||
return ThrowError( \
|
||||
"expected object for " #obj " to contain integer member " #member); \
|
||||
} \
|
||||
*valp = obj->Get(String::New(#member))->ToInteger()->Value();
|
||||
|
||||
#define SLURP_OBJECT(obj, member, valp) \
|
||||
if (!(obj)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"object for " #obj " to contain object member " #member)))); \
|
||||
return ThrowError( \
|
||||
"expected object for " #obj " to contain object member " #member); \
|
||||
} \
|
||||
*valp = Local<Object>::Cast(obj->Get(String::New(#member)));
|
||||
|
||||
#define SLURP_CONNECTION(arg, conn) \
|
||||
if (!(arg)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"argument " #arg " to be a connection object")))); \
|
||||
return ThrowError( \
|
||||
"expected argument " #arg " to be a connection object"); \
|
||||
} \
|
||||
node_dtrace_connection_t conn; \
|
||||
Local<Object> _##conn = Local<Object>::Cast(arg); \
|
||||
@ -103,8 +114,8 @@ using namespace v8;
|
||||
|
||||
#define SLURP_CONNECTION_HTTP_CLIENT(arg, conn) \
|
||||
if (!(arg)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"argument " #arg " to be a connection object")))); \
|
||||
return ThrowError( \
|
||||
"expected argument " #arg " to be a connection object"); \
|
||||
} \
|
||||
node_dtrace_connection_t conn; \
|
||||
Local<Object> _##conn = Local<Object>::Cast(arg); \
|
||||
@ -115,12 +126,12 @@ using namespace v8;
|
||||
|
||||
#define SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(arg0, arg1, conn) \
|
||||
if (!(arg0)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"argument " #arg0 " to be a connection object")))); \
|
||||
return ThrowError( \
|
||||
"expected argument " #arg0 " to be a connection object"); \
|
||||
} \
|
||||
if (!(arg1)->IsObject()) { \
|
||||
return (ThrowException(Exception::Error(String::New("expected " \
|
||||
"argument " #arg1 " to be a connection object")))); \
|
||||
return ThrowError( \
|
||||
"expected argument " #arg1 " to be a connection object"); \
|
||||
} \
|
||||
node_dtrace_connection_t conn; \
|
||||
Local<Object> _##conn = Local<Object>::Cast(arg0); \
|
||||
@ -131,86 +142,71 @@ using namespace v8;
|
||||
SLURP_INT(_##conn, port, &conn.port);
|
||||
|
||||
|
||||
Handle<Value> DTRACE_NET_SERVER_CONNECTION(const Arguments& args) {
|
||||
void DTRACE_NET_SERVER_CONNECTION(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_NET_SERVER_CONNECTION_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION(args[0], conn);
|
||||
|
||||
NODE_NET_SERVER_CONNECTION(&conn, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) {
|
||||
|
||||
void DTRACE_NET_STREAM_END(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_NET_STREAM_END_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION(args[0], conn);
|
||||
|
||||
NODE_NET_STREAM_END(&conn, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_NET_SOCKET_READ(const Arguments& args) {
|
||||
|
||||
void DTRACE_NET_SOCKET_READ(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_NET_SOCKET_READ_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION(args[0], conn);
|
||||
|
||||
if (!args[1]->IsNumber()) {
|
||||
return (ThrowException(Exception::Error(String::New("expected "
|
||||
"argument 1 to be number of bytes"))));
|
||||
return ThrowError("expected argument 1 to be number of bytes");
|
||||
}
|
||||
|
||||
int nbytes = args[1]->Int32Value();
|
||||
NODE_NET_SOCKET_READ(&conn, nbytes, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_NET_SOCKET_WRITE(const Arguments& args) {
|
||||
|
||||
void DTRACE_NET_SOCKET_WRITE(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_NET_SOCKET_WRITE_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION(args[0], conn);
|
||||
|
||||
if (!args[1]->IsNumber()) {
|
||||
return (ThrowException(Exception::Error(String::New("expected "
|
||||
"argument 1 to be number of bytes"))));
|
||||
return ThrowError("expected argument 1 to be number of bytes");
|
||||
}
|
||||
|
||||
int nbytes = args[1]->Int32Value();
|
||||
NODE_NET_SOCKET_WRITE(&conn, nbytes, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
|
||||
|
||||
void DTRACE_HTTP_SERVER_REQUEST(const FunctionCallbackInfo<Value>& args) {
|
||||
node_dtrace_http_server_request_t req;
|
||||
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> arg0 = Local<Object>::Cast(args[0]);
|
||||
Local<Object> headers;
|
||||
|
||||
@ -218,12 +214,12 @@ Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
|
||||
req._un.version = 1;
|
||||
SLURP_STRING(arg0, url, &req.url);
|
||||
SLURP_STRING(arg0, method, &req.method);
|
||||
|
||||
SLURP_OBJECT(arg0, headers, &headers);
|
||||
|
||||
if (!(headers)->IsObject())
|
||||
return (ThrowException(Exception::Error(String::New("expected "
|
||||
"object for request to contain string member headers"))));
|
||||
if (!(headers)->IsObject()) {
|
||||
return ThrowError(
|
||||
"expected object for request to contain string member headers");
|
||||
}
|
||||
|
||||
Local<Value> strfwdfor = headers->Get(String::New("x-forwarded-for"));
|
||||
String::Utf8Value fwdfor(strfwdfor);
|
||||
@ -232,35 +228,29 @@ Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
|
||||
req.forwardedFor = const_cast<char*>("");
|
||||
|
||||
SLURP_CONNECTION(args[1], conn);
|
||||
|
||||
NODE_HTTP_SERVER_REQUEST(&req, &conn, conn.remote, conn.port, req.method, \
|
||||
req.url, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) {
|
||||
|
||||
void DTRACE_HTTP_SERVER_RESPONSE(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION(args[0], conn);
|
||||
|
||||
NODE_HTTP_SERVER_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_HTTP_CLIENT_REQUEST(const Arguments& args) {
|
||||
|
||||
void DTRACE_HTTP_CLIENT_REQUEST(const FunctionCallbackInfo<Value>& args) {
|
||||
node_dtrace_http_client_request_t req;
|
||||
char *header;
|
||||
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_HTTP_CLIENT_REQUEST_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
@ -290,28 +280,21 @@ Handle<Value> DTRACE_HTTP_CLIENT_REQUEST(const Arguments& args) {
|
||||
*header = '\0';
|
||||
|
||||
SLURP_CONNECTION_HTTP_CLIENT(args[1], conn);
|
||||
|
||||
NODE_HTTP_CLIENT_REQUEST(&req, &conn, conn.remote, conn.port, req.method, \
|
||||
req.url, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
Handle<Value> DTRACE_HTTP_CLIENT_RESPONSE(const Arguments& args) {
|
||||
|
||||
void DTRACE_HTTP_CLIENT_RESPONSE(const FunctionCallbackInfo<Value>& args) {
|
||||
#ifndef HAVE_SYSTEMTAP
|
||||
if (!NODE_HTTP_CLIENT_RESPONSE_ENABLED())
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
#endif
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
SLURP_CONNECTION_HTTP_CLIENT_RESPONSE(args[0], args[1], conn);
|
||||
|
||||
NODE_HTTP_CLIENT_RESPONSE(&conn, conn.remote, conn.port, conn.fd);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
#define NODE_PROBE(name) #name, name, Persistent<FunctionTemplate>()
|
||||
|
||||
static int dtrace_gc_start(GCType type, GCCallbackFlags flags) {
|
||||
NODE_GC_START(type, flags);
|
||||
@ -322,17 +305,21 @@ static int dtrace_gc_start(GCType type, GCCallbackFlags flags) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int dtrace_gc_done(GCType type, GCCallbackFlags flags) {
|
||||
NODE_GC_DONE(type, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void InitDTrace(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
Handle<Value> (*func)(const Arguments&);
|
||||
Persistent<FunctionTemplate> templ;
|
||||
void (*func)(const FunctionCallbackInfo<Value>&);
|
||||
} tab[] = {
|
||||
#define NODE_PROBE(name) #name, name
|
||||
{ NODE_PROBE(DTRACE_NET_SERVER_CONNECTION) },
|
||||
{ NODE_PROBE(DTRACE_NET_STREAM_END) },
|
||||
{ NODE_PROBE(DTRACE_NET_SOCKET_READ) },
|
||||
@ -341,12 +328,13 @@ void InitDTrace(Handle<Object> target) {
|
||||
{ NODE_PROBE(DTRACE_HTTP_SERVER_RESPONSE) },
|
||||
{ NODE_PROBE(DTRACE_HTTP_CLIENT_REQUEST) },
|
||||
{ NODE_PROBE(DTRACE_HTTP_CLIENT_RESPONSE) }
|
||||
#undef NODE_PROBE
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < ARRAY_SIZE(tab); i++) {
|
||||
tab[i].templ = Persistent<FunctionTemplate>::New(node_isolate,
|
||||
FunctionTemplate::New(tab[i].func));
|
||||
target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
|
||||
Local<String> key = String::New(tab[i].name);
|
||||
Local<Value> val = FunctionTemplate::New(tab[i].func)->GetFunction();
|
||||
target->Set(key, val);
|
||||
}
|
||||
|
||||
#ifdef HAVE_ETW
|
||||
|
208
src/node_file.cc
208
src/node_file.cc
@ -39,12 +39,23 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using v8::Array;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
#define MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
|
||||
#define TYPE_ERROR(msg) \
|
||||
ThrowException(Exception::TypeError(String::New(msg)));
|
||||
#define TYPE_ERROR(msg) ThrowTypeError(msg)
|
||||
|
||||
#define THROW_BAD_ARGS TYPE_ERROR("Bad argument")
|
||||
|
||||
@ -61,16 +72,16 @@ class FSReqWrap: public ReqWrap<uv_fs_t> {
|
||||
};
|
||||
|
||||
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
|
||||
|
||||
#define ASSERT_OFFSET(a) \
|
||||
if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \
|
||||
return ThrowException(Exception::TypeError(String::New("Not an integer"))); \
|
||||
return ThrowTypeError("Not an integer"); \
|
||||
}
|
||||
#define ASSERT_TRUNCATE_LENGTH(a) \
|
||||
if (!(a)->IsUndefined() && !(a)->IsNull() && !IsInt64((a)->NumberValue())) { \
|
||||
return ThrowException(Exception::TypeError(String::New("Not an integer"))); \
|
||||
return ThrowTypeError("Not an integer"); \
|
||||
}
|
||||
#define GET_OFFSET(a) ((a)->IsNumber() ? (a)->IntegerValue() : -1)
|
||||
#define GET_TRUNCATE_LENGTH(a) ((a)->IntegerValue())
|
||||
@ -192,9 +203,9 @@ static void After(uv_fs_t *req) {
|
||||
}
|
||||
|
||||
if (oncomplete_sym.IsEmpty()) {
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
}
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, argc, argv);
|
||||
MakeCallback(req_wrap->object(), oncomplete_sym, argc, argv);
|
||||
|
||||
uv_fs_req_cleanup(&req_wrap->req_);
|
||||
delete req_wrap;
|
||||
@ -216,7 +227,7 @@ struct fs_req_wrap {
|
||||
FSReqWrap* req_wrap = new FSReqWrap(#func); \
|
||||
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
|
||||
__VA_ARGS__, After); \
|
||||
req_wrap->object_->Set(oncomplete_sym, callback); \
|
||||
req_wrap->object()->Set(oncomplete_sym, callback); \
|
||||
req_wrap->Dispatched(); \
|
||||
if (r < 0) { \
|
||||
uv_fs_t* req = &req_wrap->req_; \
|
||||
@ -225,14 +236,14 @@ struct fs_req_wrap {
|
||||
req->errorno = uv_last_error(uv_default_loop()).code; \
|
||||
After(req); \
|
||||
} \
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
|
||||
#define SYNC_CALL(func, path, ...) \
|
||||
fs_req_wrap req_wrap; \
|
||||
int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
|
||||
if (result < 0) { \
|
||||
int code = uv_last_error(uv_default_loop()).code; \
|
||||
return ThrowException(UVException(code, #func, "", path)); \
|
||||
return ThrowUVException(code, #func, "", path); \
|
||||
}
|
||||
|
||||
#define SYNC_REQ req_wrap.req
|
||||
@ -240,7 +251,7 @@ struct fs_req_wrap {
|
||||
#define SYNC_RESULT result
|
||||
|
||||
|
||||
static Handle<Value> Close(const Arguments& args) {
|
||||
static void Close(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
@ -253,49 +264,49 @@ static Handle<Value> Close(const Arguments& args) {
|
||||
ASYNC_CALL(close, args[1], fd)
|
||||
} else {
|
||||
SYNC_CALL(close, 0, fd)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Persistent<FunctionTemplate> stats_constructor_template;
|
||||
static Persistent<Function> stats_constructor;
|
||||
|
||||
static Persistent<String> dev_symbol;
|
||||
static Persistent<String> ino_symbol;
|
||||
static Persistent<String> mode_symbol;
|
||||
static Persistent<String> nlink_symbol;
|
||||
static Persistent<String> uid_symbol;
|
||||
static Persistent<String> gid_symbol;
|
||||
static Persistent<String> rdev_symbol;
|
||||
static Persistent<String> size_symbol;
|
||||
static Persistent<String> blksize_symbol;
|
||||
static Persistent<String> blocks_symbol;
|
||||
static Persistent<String> atime_symbol;
|
||||
static Persistent<String> mtime_symbol;
|
||||
static Persistent<String> ctime_symbol;
|
||||
static Cached<String> dev_symbol;
|
||||
static Cached<String> ino_symbol;
|
||||
static Cached<String> mode_symbol;
|
||||
static Cached<String> nlink_symbol;
|
||||
static Cached<String> uid_symbol;
|
||||
static Cached<String> gid_symbol;
|
||||
static Cached<String> rdev_symbol;
|
||||
static Cached<String> size_symbol;
|
||||
static Cached<String> blksize_symbol;
|
||||
static Cached<String> blocks_symbol;
|
||||
static Cached<String> atime_symbol;
|
||||
static Cached<String> mtime_symbol;
|
||||
static Cached<String> ctime_symbol;
|
||||
|
||||
Local<Object> BuildStatsObject(const uv_stat_t* s) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (dev_symbol.IsEmpty()) {
|
||||
dev_symbol = NODE_PSYMBOL("dev");
|
||||
ino_symbol = NODE_PSYMBOL("ino");
|
||||
mode_symbol = NODE_PSYMBOL("mode");
|
||||
nlink_symbol = NODE_PSYMBOL("nlink");
|
||||
uid_symbol = NODE_PSYMBOL("uid");
|
||||
gid_symbol = NODE_PSYMBOL("gid");
|
||||
rdev_symbol = NODE_PSYMBOL("rdev");
|
||||
size_symbol = NODE_PSYMBOL("size");
|
||||
blksize_symbol = NODE_PSYMBOL("blksize");
|
||||
blocks_symbol = NODE_PSYMBOL("blocks");
|
||||
atime_symbol = NODE_PSYMBOL("atime");
|
||||
mtime_symbol = NODE_PSYMBOL("mtime");
|
||||
ctime_symbol = NODE_PSYMBOL("ctime");
|
||||
dev_symbol = String::New("dev");
|
||||
ino_symbol = String::New("ino");
|
||||
mode_symbol = String::New("mode");
|
||||
nlink_symbol = String::New("nlink");
|
||||
uid_symbol = String::New("uid");
|
||||
gid_symbol = String::New("gid");
|
||||
rdev_symbol = String::New("rdev");
|
||||
size_symbol = String::New("size");
|
||||
blksize_symbol = String::New("blksize");
|
||||
blocks_symbol = String::New("blocks");
|
||||
atime_symbol = String::New("atime");
|
||||
mtime_symbol = String::New("mtime");
|
||||
ctime_symbol = String::New("ctime");
|
||||
}
|
||||
|
||||
Local<Object> stats =
|
||||
stats_constructor_template->GetFunction()->NewInstance();
|
||||
Local<Function> constructor =
|
||||
Local<Function>::New(node_isolate, stats_constructor);
|
||||
|
||||
Local<Object> stats = constructor->NewInstance();
|
||||
if (stats.IsEmpty()) return Local<Object>();
|
||||
|
||||
// The code below is very nasty-looking but it prevents a segmentation fault
|
||||
@ -355,7 +366,7 @@ Local<Object> BuildStatsObject(const uv_stat_t* s) {
|
||||
return scope.Close(stats);
|
||||
}
|
||||
|
||||
static Handle<Value> Stat(const Arguments& args) {
|
||||
static void Stat(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -367,12 +378,12 @@ static Handle<Value> Stat(const Arguments& args) {
|
||||
ASYNC_CALL(stat, args[1], *path)
|
||||
} else {
|
||||
SYNC_CALL(stat, *path, *path)
|
||||
return scope.Close(
|
||||
args.GetReturnValue().Set(
|
||||
BuildStatsObject(static_cast<const uv_stat_t*>(SYNC_REQ.ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> LStat(const Arguments& args) {
|
||||
static void LStat(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -384,12 +395,12 @@ static Handle<Value> LStat(const Arguments& args) {
|
||||
ASYNC_CALL(lstat, args[1], *path)
|
||||
} else {
|
||||
SYNC_CALL(lstat, *path, *path)
|
||||
return scope.Close(
|
||||
args.GetReturnValue().Set(
|
||||
BuildStatsObject(static_cast<const uv_stat_t*>(SYNC_REQ.ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> FStat(const Arguments& args) {
|
||||
static void FStat(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
@ -402,12 +413,12 @@ static Handle<Value> FStat(const Arguments& args) {
|
||||
ASYNC_CALL(fstat, args[1], fd)
|
||||
} else {
|
||||
SYNC_CALL(fstat, 0, fd)
|
||||
return scope.Close(
|
||||
args.GetReturnValue().Set(
|
||||
BuildStatsObject(static_cast<const uv_stat_t*>(SYNC_REQ.ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Symlink(const Arguments& args) {
|
||||
static void Symlink(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -427,8 +438,7 @@ static Handle<Value> Symlink(const Arguments& args) {
|
||||
} else if (strcmp(*mode, "junction") == 0) {
|
||||
flags |= UV_FS_SYMLINK_JUNCTION;
|
||||
} else if (strcmp(*mode, "file") != 0) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Unknown symlink type")));
|
||||
return ThrowError("Unknown symlink type");
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,11 +446,10 @@ static Handle<Value> Symlink(const Arguments& args) {
|
||||
ASYNC_CALL(symlink, args[3], *dest, *path, flags)
|
||||
} else {
|
||||
SYNC_CALL(symlink, *path, *dest, *path, flags)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Link(const Arguments& args) {
|
||||
static void Link(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -456,11 +465,10 @@ static Handle<Value> Link(const Arguments& args) {
|
||||
ASYNC_CALL(link, args[2], *orig_path, *new_path)
|
||||
} else {
|
||||
SYNC_CALL(link, *orig_path, *orig_path, *new_path)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> ReadLink(const Arguments& args) {
|
||||
static void ReadLink(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -472,11 +480,12 @@ static Handle<Value> ReadLink(const Arguments& args) {
|
||||
ASYNC_CALL(readlink, args[1], *path)
|
||||
} else {
|
||||
SYNC_CALL(readlink, *path, *path)
|
||||
return scope.Close(String::New((char*)SYNC_REQ.ptr));
|
||||
args.GetReturnValue().Set(
|
||||
String::New(static_cast<const char*>(SYNC_REQ.ptr)));
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Rename(const Arguments& args) {
|
||||
static void Rename(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -492,11 +501,10 @@ static Handle<Value> Rename(const Arguments& args) {
|
||||
ASYNC_CALL(rename, args[2], *old_path, *new_path)
|
||||
} else {
|
||||
SYNC_CALL(rename, *old_path, *old_path, *new_path)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> FTruncate(const Arguments& args) {
|
||||
static void FTruncate(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsInt32()) {
|
||||
@ -512,11 +520,10 @@ static Handle<Value> FTruncate(const Arguments& args) {
|
||||
ASYNC_CALL(ftruncate, args[2], fd, len)
|
||||
} else {
|
||||
SYNC_CALL(ftruncate, 0, fd, len)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Fdatasync(const Arguments& args) {
|
||||
static void Fdatasync(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
@ -529,11 +536,10 @@ static Handle<Value> Fdatasync(const Arguments& args) {
|
||||
ASYNC_CALL(fdatasync, args[1], fd)
|
||||
} else {
|
||||
SYNC_CALL(fdatasync, 0, fd)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Fsync(const Arguments& args) {
|
||||
static void Fsync(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
@ -546,11 +552,10 @@ static Handle<Value> Fsync(const Arguments& args) {
|
||||
ASYNC_CALL(fsync, args[1], fd)
|
||||
} else {
|
||||
SYNC_CALL(fsync, 0, fd)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Unlink(const Arguments& args) {
|
||||
static void Unlink(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -562,11 +567,10 @@ static Handle<Value> Unlink(const Arguments& args) {
|
||||
ASYNC_CALL(unlink, args[1], *path)
|
||||
} else {
|
||||
SYNC_CALL(unlink, *path, *path)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> RMDir(const Arguments& args) {
|
||||
static void RMDir(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -578,11 +582,10 @@ static Handle<Value> RMDir(const Arguments& args) {
|
||||
ASYNC_CALL(rmdir, args[1], *path)
|
||||
} else {
|
||||
SYNC_CALL(rmdir, *path, *path)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> MKDir(const Arguments& args) {
|
||||
static void MKDir(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsString() || !args[1]->IsInt32()) {
|
||||
@ -596,11 +599,10 @@ static Handle<Value> MKDir(const Arguments& args) {
|
||||
ASYNC_CALL(mkdir, args[2], *path, mode)
|
||||
} else {
|
||||
SYNC_CALL(mkdir, *path, *path, mode)
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> ReadDir(const Arguments& args) {
|
||||
static void ReadDir(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1) return TYPE_ERROR("path required");
|
||||
@ -629,11 +631,11 @@ static Handle<Value> ReadDir(const Arguments& args) {
|
||||
#endif
|
||||
}
|
||||
|
||||
return scope.Close(names);
|
||||
args.GetReturnValue().Set(names);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Open(const Arguments& args) {
|
||||
static void Open(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -652,8 +654,7 @@ static Handle<Value> Open(const Arguments& args) {
|
||||
ASYNC_CALL(open, args[3], *path, flags, mode)
|
||||
} else {
|
||||
SYNC_CALL(open, *path, *path, flags, mode)
|
||||
int fd = SYNC_RESULT;
|
||||
return scope.Close(Integer::New(fd, node_isolate));
|
||||
args.GetReturnValue().Set(SYNC_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,7 +667,7 @@ static Handle<Value> Open(const Arguments& args) {
|
||||
// 3 length how much to write
|
||||
// 4 position if integer, position to write at in the file.
|
||||
// if null, write from the current position
|
||||
static Handle<Value> Write(const Arguments& args) {
|
||||
static void Write(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (!args[0]->IsInt32()) {
|
||||
@ -676,8 +677,7 @@ static Handle<Value> Write(const Arguments& args) {
|
||||
int fd = args[0]->Int32Value();
|
||||
|
||||
if (!Buffer::HasInstance(args[1])) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Second argument needs to be a buffer")));
|
||||
return ThrowError("Second argument needs to be a buffer");
|
||||
}
|
||||
|
||||
Local<Object> buffer_obj = args[1]->ToObject();
|
||||
@ -686,14 +686,12 @@ static Handle<Value> Write(const Arguments& args) {
|
||||
|
||||
size_t off = args[2]->Int32Value();
|
||||
if (off >= buffer_length) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Offset is out of bounds")));
|
||||
return ThrowError("Offset is out of bounds");
|
||||
}
|
||||
|
||||
ssize_t len = args[3]->Int32Value();
|
||||
if (off + len > buffer_length) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("off + len > buffer.length")));
|
||||
return ThrowError("off + len > buffer.length");
|
||||
}
|
||||
|
||||
ASSERT_OFFSET(args[4]);
|
||||
@ -706,7 +704,7 @@ static Handle<Value> Write(const Arguments& args) {
|
||||
ASYNC_CALL(write, cb, fd, buf, len, pos)
|
||||
} else {
|
||||
SYNC_CALL(write, 0, fd, buf, len, pos)
|
||||
return scope.Close(Integer::New(SYNC_RESULT, node_isolate));
|
||||
args.GetReturnValue().Set(SYNC_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -722,7 +720,7 @@ static Handle<Value> Write(const Arguments& args) {
|
||||
* 4 position file position - null for current position
|
||||
*
|
||||
*/
|
||||
static Handle<Value> Read(const Arguments& args) {
|
||||
static void Read(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 2 || !args[0]->IsInt32()) {
|
||||
@ -739,8 +737,7 @@ static Handle<Value> Read(const Arguments& args) {
|
||||
char * buf = NULL;
|
||||
|
||||
if (!Buffer::HasInstance(args[1])) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Second argument needs to be a buffer")));
|
||||
return ThrowError("Second argument needs to be a buffer");
|
||||
}
|
||||
|
||||
Local<Object> buffer_obj = args[1]->ToObject();
|
||||
@ -749,14 +746,12 @@ static Handle<Value> Read(const Arguments& args) {
|
||||
|
||||
size_t off = args[2]->Int32Value();
|
||||
if (off >= buffer_length) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Offset is out of bounds")));
|
||||
return ThrowError("Offset is out of bounds");
|
||||
}
|
||||
|
||||
len = args[3]->Int32Value();
|
||||
if (off + len > buffer_length) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Length extends beyond buffer")));
|
||||
return ThrowError("Length extends beyond buffer");
|
||||
}
|
||||
|
||||
pos = GET_OFFSET(args[4]);
|
||||
@ -769,8 +764,7 @@ static Handle<Value> Read(const Arguments& args) {
|
||||
ASYNC_CALL(read, cb, fd, buf, len, pos);
|
||||
} else {
|
||||
SYNC_CALL(read, 0, fd, buf, len, pos)
|
||||
Local<Integer> bytesRead = Integer::New(SYNC_RESULT, node_isolate);
|
||||
return scope.Close(bytesRead);
|
||||
args.GetReturnValue().Set(SYNC_RESULT);
|
||||
}
|
||||
}
|
||||
|
||||
@ -778,7 +772,7 @@ static Handle<Value> Read(const Arguments& args) {
|
||||
/* fs.chmod(path, mode);
|
||||
* Wrapper for chmod(1) / EIO_CHMOD
|
||||
*/
|
||||
static Handle<Value> Chmod(const Arguments& args) {
|
||||
static void Chmod(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if(args.Length() < 2 || !args[0]->IsString() || !args[1]->IsInt32()) {
|
||||
@ -791,7 +785,6 @@ static Handle<Value> Chmod(const Arguments& args) {
|
||||
ASYNC_CALL(chmod, args[2], *path, mode);
|
||||
} else {
|
||||
SYNC_CALL(chmod, *path, *path, mode);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -799,7 +792,7 @@ static Handle<Value> Chmod(const Arguments& args) {
|
||||
/* fs.fchmod(fd, mode);
|
||||
* Wrapper for fchmod(1) / EIO_FCHMOD
|
||||
*/
|
||||
static Handle<Value> FChmod(const Arguments& args) {
|
||||
static void FChmod(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if(args.Length() < 2 || !args[0]->IsInt32() || !args[1]->IsInt32()) {
|
||||
@ -812,7 +805,6 @@ static Handle<Value> FChmod(const Arguments& args) {
|
||||
ASYNC_CALL(fchmod, args[2], fd, mode);
|
||||
} else {
|
||||
SYNC_CALL(fchmod, 0, fd, mode);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -820,7 +812,7 @@ static Handle<Value> FChmod(const Arguments& args) {
|
||||
/* fs.chown(path, uid, gid);
|
||||
* Wrapper for chown(1) / EIO_CHOWN
|
||||
*/
|
||||
static Handle<Value> Chown(const Arguments& args) {
|
||||
static void Chown(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -839,7 +831,6 @@ static Handle<Value> Chown(const Arguments& args) {
|
||||
ASYNC_CALL(chown, args[3], *path, uid, gid);
|
||||
} else {
|
||||
SYNC_CALL(chown, *path, *path, uid, gid);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -847,7 +838,7 @@ static Handle<Value> Chown(const Arguments& args) {
|
||||
/* fs.fchown(fd, uid, gid);
|
||||
* Wrapper for fchown(1) / EIO_FCHOWN
|
||||
*/
|
||||
static Handle<Value> FChown(const Arguments& args) {
|
||||
static void FChown(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -866,12 +857,11 @@ static Handle<Value> FChown(const Arguments& args) {
|
||||
ASYNC_CALL(fchown, args[3], fd, uid, gid);
|
||||
} else {
|
||||
SYNC_CALL(fchown, 0, fd, uid, gid);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> UTimes(const Arguments& args) {
|
||||
static void UTimes(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -890,11 +880,10 @@ static Handle<Value> UTimes(const Arguments& args) {
|
||||
ASYNC_CALL(utime, args[3], *path, atime, mtime);
|
||||
} else {
|
||||
SYNC_CALL(utime, *path, *path, atime, mtime);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> FUTimes(const Arguments& args) {
|
||||
static void FUTimes(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
int len = args.Length();
|
||||
@ -913,7 +902,6 @@ static Handle<Value> FUTimes(const Arguments& args) {
|
||||
ASYNC_CALL(futime, args[3], fd, atime, mtime);
|
||||
} else {
|
||||
SYNC_CALL(futime, 0, fd, atime, mtime);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
}
|
||||
|
||||
@ -954,15 +942,15 @@ void File::Initialize(Handle<Object> target) {
|
||||
|
||||
void InitFs(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// Initialize the stats object
|
||||
Local<FunctionTemplate> stat_templ = FunctionTemplate::New();
|
||||
stats_constructor_template = Persistent<FunctionTemplate>::New(node_isolate,
|
||||
stat_templ);
|
||||
target->Set(String::NewSymbol("Stats"),
|
||||
stats_constructor_template->GetFunction());
|
||||
Local<Function> constructor = FunctionTemplate::New()->GetFunction();
|
||||
target->Set(String::NewSymbol("Stats"), constructor);
|
||||
stats_constructor.Reset(node_isolate, constructor);
|
||||
|
||||
File::Initialize(target);
|
||||
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
|
||||
StatWatcher::Initialize(target);
|
||||
}
|
||||
|
@ -47,26 +47,37 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using v8::Array;
|
||||
using v8::Exception;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> on_headers_sym;
|
||||
static Persistent<String> on_headers_complete_sym;
|
||||
static Persistent<String> on_body_sym;
|
||||
static Persistent<String> on_message_complete_sym;
|
||||
static Cached<String> on_headers_sym;
|
||||
static Cached<String> on_headers_complete_sym;
|
||||
static Cached<String> on_body_sym;
|
||||
static Cached<String> on_message_complete_sym;
|
||||
|
||||
static Persistent<String> method_sym;
|
||||
static Persistent<String> status_code_sym;
|
||||
static Persistent<String> http_version_sym;
|
||||
static Persistent<String> version_major_sym;
|
||||
static Persistent<String> version_minor_sym;
|
||||
static Persistent<String> should_keep_alive_sym;
|
||||
static Persistent<String> upgrade_sym;
|
||||
static Persistent<String> headers_sym;
|
||||
static Persistent<String> url_sym;
|
||||
static Cached<String> method_sym;
|
||||
static Cached<String> status_code_sym;
|
||||
static Cached<String> http_version_sym;
|
||||
static Cached<String> version_major_sym;
|
||||
static Cached<String> version_minor_sym;
|
||||
static Cached<String> should_keep_alive_sym;
|
||||
static Cached<String> upgrade_sym;
|
||||
static Cached<String> headers_sym;
|
||||
static Cached<String> url_sym;
|
||||
|
||||
static Persistent<String> unknown_method_sym;
|
||||
static Cached<String> unknown_method_sym;
|
||||
|
||||
#define X(num, name, string) static Persistent<String> name##_sym;
|
||||
#define X(num, name, string) static Cached<String> name##_sym;
|
||||
HTTP_METHOD_MAP(X)
|
||||
#undef X
|
||||
|
||||
@ -97,7 +108,7 @@ static size_t current_buffer_len;
|
||||
int name##_(const char* at, size_t length)
|
||||
|
||||
|
||||
static inline Persistent<String>
|
||||
static inline Handle<String>
|
||||
method_to_str(unsigned short m) {
|
||||
switch (m) {
|
||||
#define X(num, name, string) case HTTP_##name: return name##_sym;
|
||||
@ -243,7 +254,8 @@ public:
|
||||
|
||||
|
||||
HTTP_CB(on_headers_complete) {
|
||||
Local<Value> cb = handle_->Get(on_headers_complete_sym);
|
||||
Local<Object> obj = handle(node_isolate);
|
||||
Local<Value> cb = obj->Get(on_headers_complete_sym);
|
||||
|
||||
if (!cb->IsFunction())
|
||||
return 0;
|
||||
@ -288,9 +300,8 @@ public:
|
||||
: False(node_isolate));
|
||||
|
||||
Local<Value> argv[1] = { message_info };
|
||||
|
||||
Local<Value> head_response =
|
||||
Local<Function>::Cast(cb)->Call(handle_, 1, argv);
|
||||
cb.As<Function>()->Call(obj, ARRAY_SIZE(argv), argv);
|
||||
|
||||
if (head_response.IsEmpty()) {
|
||||
got_exception_ = true;
|
||||
@ -304,7 +315,9 @@ public:
|
||||
HTTP_DATA_CB(on_body) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Value> cb = handle_->Get(on_body_sym);
|
||||
Local<Object> obj = handle(node_isolate);
|
||||
Local<Value> cb = obj->Get(on_body_sym);
|
||||
|
||||
if (!cb->IsFunction())
|
||||
return 0;
|
||||
|
||||
@ -314,7 +327,7 @@ public:
|
||||
Integer::New(length, node_isolate)
|
||||
};
|
||||
|
||||
Local<Value> r = Local<Function>::Cast(cb)->Call(handle_, 3, argv);
|
||||
Local<Value> r = cb.As<Function>()->Call(obj, ARRAY_SIZE(argv), argv);
|
||||
|
||||
if (r.IsEmpty()) {
|
||||
got_exception_ = true;
|
||||
@ -331,12 +344,13 @@ public:
|
||||
if (num_fields_)
|
||||
Flush(); // Flush trailing HTTP headers.
|
||||
|
||||
Local<Value> cb = handle_->Get(on_message_complete_sym);
|
||||
Local<Object> obj = handle(node_isolate);
|
||||
Local<Value> cb = obj->Get(on_message_complete_sym);
|
||||
|
||||
if (!cb->IsFunction())
|
||||
return 0;
|
||||
|
||||
Local<Value> r = Local<Function>::Cast(cb)->Call(handle_, 0, NULL);
|
||||
Local<Value> r = cb.As<Function>()->Call(obj, 0, NULL);
|
||||
|
||||
if (r.IsEmpty()) {
|
||||
got_exception_ = true;
|
||||
@ -347,21 +361,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> New(const Arguments& args) {
|
||||
static void New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
http_parser_type type =
|
||||
static_cast<http_parser_type>(args[0]->Int32Value());
|
||||
|
||||
if (type != HTTP_REQUEST && type != HTTP_RESPONSE) {
|
||||
return ThrowException(Exception::Error(String::New(
|
||||
"Argument must be HTTPParser.REQUEST or HTTPParser.RESPONSE")));
|
||||
}
|
||||
|
||||
assert(type == HTTP_REQUEST || type == HTTP_RESPONSE);
|
||||
Parser* parser = new Parser(type);
|
||||
parser->Wrap(args.This());
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
|
||||
@ -379,7 +387,7 @@ public:
|
||||
|
||||
|
||||
// var bytesParsed = parser->execute(buffer);
|
||||
static Handle<Value> Execute(const Arguments& args) {
|
||||
static void Execute(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
|
||||
@ -388,15 +396,13 @@ public:
|
||||
assert(!current_buffer_data);
|
||||
|
||||
if (current_buffer) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("Already parsing a buffer")));
|
||||
return ThrowTypeError("Already parsing a buffer");
|
||||
}
|
||||
|
||||
Local<Value> buffer_v = args[0];
|
||||
|
||||
if (!Buffer::HasInstance(buffer_v)) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("Argument should be a buffer")));
|
||||
return ThrowTypeError("Argument should be a buffer");
|
||||
}
|
||||
|
||||
Local<Object> buffer_obj = buffer_v->ToObject();
|
||||
@ -420,7 +426,7 @@ public:
|
||||
current_buffer_data = NULL;
|
||||
|
||||
// If there was an exception in one of the callbacks
|
||||
if (parser->got_exception_) return Local<Value>();
|
||||
if (parser->got_exception_) return;
|
||||
|
||||
Local<Integer> nparsed_obj = Integer::New(nparsed, node_isolate);
|
||||
// If there was a parse error in one of the callbacks
|
||||
@ -432,14 +438,14 @@ public:
|
||||
Local<Object> obj = e->ToObject();
|
||||
obj->Set(String::NewSymbol("bytesParsed"), nparsed_obj);
|
||||
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
|
||||
return scope.Close(e);
|
||||
args.GetReturnValue().Set(e);
|
||||
} else {
|
||||
return scope.Close(nparsed_obj);
|
||||
args.GetReturnValue().Set(nparsed_obj);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> Finish(const Arguments& args) {
|
||||
static void Finish(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
|
||||
@ -449,7 +455,7 @@ public:
|
||||
|
||||
int rv = http_parser_execute(&(parser->parser_), &settings, NULL, 0);
|
||||
|
||||
if (parser->got_exception_) return Local<Value>();
|
||||
if (parser->got_exception_) return;
|
||||
|
||||
if (rv != 0) {
|
||||
enum http_errno err = HTTP_PARSER_ERRNO(&parser->parser_);
|
||||
@ -458,28 +464,20 @@ public:
|
||||
Local<Object> obj = e->ToObject();
|
||||
obj->Set(String::NewSymbol("bytesParsed"), Integer::New(0, node_isolate));
|
||||
obj->Set(String::NewSymbol("code"), String::New(http_errno_name(err)));
|
||||
return scope.Close(e);
|
||||
args.GetReturnValue().Set(e);
|
||||
}
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> Reinitialize(const Arguments& args) {
|
||||
static void Reinitialize(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
http_parser_type type =
|
||||
static_cast<http_parser_type>(args[0]->Int32Value());
|
||||
|
||||
if (type != HTTP_REQUEST && type != HTTP_RESPONSE) {
|
||||
return ThrowException(Exception::Error(String::New(
|
||||
"Argument must be HTTPParser.REQUEST or HTTPParser.RESPONSE")));
|
||||
}
|
||||
|
||||
assert(type == HTTP_REQUEST || type == HTTP_RESPONSE);
|
||||
Parser* parser = ObjectWrap::Unwrap<Parser>(args.This());
|
||||
parser->Init(type);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -503,7 +501,8 @@ private:
|
||||
void Flush() {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Value> cb = handle_->Get(on_headers_sym);
|
||||
Local<Object> obj = handle(node_isolate);
|
||||
Local<Value> cb = obj->Get(on_headers_sym);
|
||||
|
||||
if (!cb->IsFunction())
|
||||
return;
|
||||
@ -513,7 +512,7 @@ private:
|
||||
url_.ToString()
|
||||
};
|
||||
|
||||
Local<Value> r = Local<Function>::Cast(cb)->Call(handle_, 2, argv);
|
||||
Local<Value> r = cb.As<Function>()->Call(obj, ARRAY_SIZE(argv), argv);
|
||||
|
||||
if (r.IsEmpty())
|
||||
got_exception_ = true;
|
||||
@ -551,13 +550,10 @@ void InitHttpParser(Handle<Object> target) {
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
t->SetClassName(String::NewSymbol("HTTPParser"));
|
||||
|
||||
PropertyAttribute attrib = (PropertyAttribute) (ReadOnly | DontDelete);
|
||||
t->Set(String::NewSymbol("REQUEST"),
|
||||
Integer::New(HTTP_REQUEST, node_isolate),
|
||||
attrib);
|
||||
Integer::New(HTTP_REQUEST, node_isolate));
|
||||
t->Set(String::NewSymbol("RESPONSE"),
|
||||
Integer::New(HTTP_RESPONSE, node_isolate),
|
||||
attrib);
|
||||
Integer::New(HTTP_RESPONSE, node_isolate));
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "execute", Parser::Execute);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "finish", Parser::Finish);
|
||||
@ -565,25 +561,25 @@ void InitHttpParser(Handle<Object> target) {
|
||||
|
||||
target->Set(String::NewSymbol("HTTPParser"), t->GetFunction());
|
||||
|
||||
on_headers_sym = NODE_PSYMBOL("onHeaders");
|
||||
on_headers_complete_sym = NODE_PSYMBOL("onHeadersComplete");
|
||||
on_body_sym = NODE_PSYMBOL("onBody");
|
||||
on_message_complete_sym = NODE_PSYMBOL("onMessageComplete");
|
||||
on_headers_sym = String::New("onHeaders");
|
||||
on_headers_complete_sym = String::New("onHeadersComplete");
|
||||
on_body_sym = String::New("onBody");
|
||||
on_message_complete_sym = String::New("onMessageComplete");
|
||||
|
||||
#define X(num, name, string) name##_sym = NODE_PSYMBOL(#string);
|
||||
#define X(num, name, string) name##_sym = String::New(#string);
|
||||
HTTP_METHOD_MAP(X)
|
||||
#undef X
|
||||
unknown_method_sym = NODE_PSYMBOL("UNKNOWN_METHOD");
|
||||
unknown_method_sym = String::New("UNKNOWN_METHOD");
|
||||
|
||||
method_sym = NODE_PSYMBOL("method");
|
||||
status_code_sym = NODE_PSYMBOL("statusCode");
|
||||
http_version_sym = NODE_PSYMBOL("httpVersion");
|
||||
version_major_sym = NODE_PSYMBOL("versionMajor");
|
||||
version_minor_sym = NODE_PSYMBOL("versionMinor");
|
||||
should_keep_alive_sym = NODE_PSYMBOL("shouldKeepAlive");
|
||||
upgrade_sym = NODE_PSYMBOL("upgrade");
|
||||
headers_sym = NODE_PSYMBOL("headers");
|
||||
url_sym = NODE_PSYMBOL("url");
|
||||
method_sym = String::New("method");
|
||||
status_code_sym = String::New("statusCode");
|
||||
http_version_sym = String::New("httpVersion");
|
||||
version_major_sym = String::New("versionMajor");
|
||||
version_minor_sym = String::New("versionMinor");
|
||||
should_keep_alive_sym = String::New("shouldKeepAlive");
|
||||
upgrade_sym = String::New("upgrade");
|
||||
headers_sym = String::New("headers");
|
||||
url_sym = String::New("url");
|
||||
|
||||
settings.on_message_begin = Parser::on_message_begin;
|
||||
settings.on_url = Parser::on_url;
|
||||
|
@ -22,6 +22,7 @@
|
||||
#ifndef SRC_NODE_INTERNALS_H_
|
||||
#define SRC_NODE_INTERNALS_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "v8.h"
|
||||
@ -32,7 +33,67 @@ namespace node {
|
||||
extern v8::Isolate* node_isolate;
|
||||
|
||||
// Defined in node.cc at startup.
|
||||
extern v8::Persistent<v8::Object> process;
|
||||
extern v8::Persistent<v8::Object> process_p;
|
||||
|
||||
template <typename TypeName>
|
||||
class CachedBase {
|
||||
public:
|
||||
CachedBase();
|
||||
operator v8::Handle<TypeName>() const;
|
||||
void operator=(v8::Handle<TypeName> that); // Can only assign once.
|
||||
bool IsEmpty() const;
|
||||
private:
|
||||
CachedBase(const CachedBase&);
|
||||
void operator=(const CachedBase&);
|
||||
v8::Persistent<TypeName> handle_;
|
||||
};
|
||||
|
||||
template <typename TypeName>
|
||||
class Cached : public CachedBase<TypeName> {
|
||||
public:
|
||||
operator v8::Handle<v8::Value>() const;
|
||||
void operator=(v8::Handle<TypeName> that);
|
||||
};
|
||||
|
||||
template <>
|
||||
class Cached<v8::Value> : public CachedBase<v8::Value> {
|
||||
public:
|
||||
operator v8::Handle<v8::Value>() const;
|
||||
void operator=(v8::Handle<v8::Value> that);
|
||||
};
|
||||
|
||||
template <typename TypeName>
|
||||
v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Persistent<v8::Object>& recv,
|
||||
const TypeName method,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
|
||||
template <typename TypeName>
|
||||
v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Persistent<v8::Object>& recv,
|
||||
const Cached<TypeName>& method,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
|
||||
inline bool HasInstance(v8::Persistent<v8::FunctionTemplate>& function_template,
|
||||
v8::Handle<v8::Value> value);
|
||||
|
||||
inline v8::Local<v8::Object> NewInstance(v8::Persistent<v8::Function>& ctor,
|
||||
int argc = 0,
|
||||
v8::Handle<v8::Value>* argv = NULL);
|
||||
|
||||
// TODO(bnoordhuis) Move to src/node_buffer.h once it's been established
|
||||
// that the current approach to dealing with Persistent is working out.
|
||||
namespace Buffer {
|
||||
|
||||
template <typename TypeName>
|
||||
inline char* Data(v8::Persistent<TypeName>& val);
|
||||
|
||||
template <typename TypeName>
|
||||
inline size_t Length(v8::Persistent<TypeName>& val);
|
||||
|
||||
} // namespace Buffer
|
||||
|
||||
#ifdef _WIN32
|
||||
// emulate snprintf() on windows, _snprintf() doesn't zero-terminate the buffer
|
||||
@ -87,22 +148,44 @@ inline static int snprintf(char* buf, unsigned int len, const char* fmt, ...) {
|
||||
#define THROW_ERROR(fun) \
|
||||
do { \
|
||||
v8::HandleScope scope(node_isolate); \
|
||||
return v8::ThrowException(fun(v8::String::New(errmsg))); \
|
||||
v8::ThrowException(fun(v8::String::New(errmsg))); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
inline static v8::Handle<v8::Value> ThrowError(const char* errmsg) {
|
||||
inline static void ThrowError(const char* errmsg) {
|
||||
THROW_ERROR(v8::Exception::Error);
|
||||
}
|
||||
|
||||
inline static v8::Handle<v8::Value> ThrowTypeError(const char* errmsg) {
|
||||
inline static void ThrowTypeError(const char* errmsg) {
|
||||
THROW_ERROR(v8::Exception::TypeError);
|
||||
}
|
||||
|
||||
inline static v8::Handle<v8::Value> ThrowRangeError(const char* errmsg) {
|
||||
inline static void ThrowRangeError(const char* errmsg) {
|
||||
THROW_ERROR(v8::Exception::RangeError);
|
||||
}
|
||||
|
||||
inline static void ThrowErrnoException(int errorno,
|
||||
const char* syscall = NULL,
|
||||
const char* message = NULL,
|
||||
const char* path = NULL) {
|
||||
NODE_EXTERN v8::Local<v8::Value> ErrnoException(int errorno,
|
||||
const char* syscall = NULL,
|
||||
const char* message = NULL,
|
||||
const char* path = NULL);
|
||||
v8::ThrowException(ErrnoException(errorno, syscall, message, path));
|
||||
}
|
||||
|
||||
inline static void ThrowUVException(int errorno,
|
||||
const char* syscall = NULL,
|
||||
const char* message = NULL,
|
||||
const char* path = NULL) {
|
||||
NODE_EXTERN v8::Local<v8::Value> UVException(int errorno,
|
||||
const char* syscall = NULL,
|
||||
const char* message = NULL,
|
||||
const char* path = NULL);
|
||||
v8::ThrowException(UVException(errorno, syscall, message, path));
|
||||
}
|
||||
|
||||
NO_RETURN void FatalError(const char* location, const char* message);
|
||||
|
||||
#define UNWRAP(type) \
|
||||
@ -116,10 +199,6 @@ NO_RETURN void FatalError(const char* location, const char* message);
|
||||
abort(); \
|
||||
}
|
||||
|
||||
v8::Handle<v8::Value> FromConstructorTemplate(
|
||||
v8::Persistent<v8::FunctionTemplate> t,
|
||||
const v8::Arguments& args);
|
||||
|
||||
// allow for quick domain check
|
||||
extern bool using_domains;
|
||||
|
||||
@ -165,6 +244,115 @@ inline MUST_USE_RESULT bool ParseArrayIndex(v8::Handle<v8::Value> arg,
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
CachedBase<TypeName>::CachedBase() {
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
CachedBase<TypeName>::operator v8::Handle<TypeName>() const {
|
||||
return v8::Local<TypeName>::New(node_isolate, handle_);
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
void CachedBase<TypeName>::operator=(v8::Handle<TypeName> that) {
|
||||
assert(handle_.IsEmpty() == true); // Can only assign once.
|
||||
handle_.Reset(node_isolate, that);
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
bool CachedBase<TypeName>::IsEmpty() const {
|
||||
return handle_.IsEmpty();
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
Cached<TypeName>::operator v8::Handle<v8::Value>() const {
|
||||
return CachedBase<TypeName>::operator v8::Handle<TypeName>();
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
void Cached<TypeName>::operator=(v8::Handle<TypeName> that) {
|
||||
CachedBase<TypeName>::operator=(that);
|
||||
}
|
||||
|
||||
inline Cached<v8::Value>::operator v8::Handle<v8::Value>() const {
|
||||
return CachedBase<v8::Value>::operator v8::Handle<v8::Value>();
|
||||
}
|
||||
|
||||
inline void Cached<v8::Value>::operator=(v8::Handle<v8::Value> that) {
|
||||
CachedBase<v8::Value>::operator=(that);
|
||||
}
|
||||
|
||||
// Forward declarations, see node.h
|
||||
NODE_EXTERN v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Handle<v8::Object> recv,
|
||||
const char* method,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
NODE_EXTERN v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Handle<v8::Object> object,
|
||||
const v8::Handle<v8::String> symbol,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
NODE_EXTERN v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Handle<v8::Object> object,
|
||||
const v8::Handle<v8::Function> callback,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv);
|
||||
|
||||
template <typename TypeName>
|
||||
v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Persistent<v8::Object>& recv,
|
||||
const TypeName method,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv) {
|
||||
v8::Local<v8::Object> recv_obj =
|
||||
v8::Local<v8::Object>::New(node_isolate, recv);
|
||||
return MakeCallback(recv_obj, method, argc, argv);
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
v8::Handle<v8::Value> MakeCallback(
|
||||
const v8::Persistent<v8::Object>& recv,
|
||||
const Cached<TypeName>& method,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv) {
|
||||
const v8::Handle<TypeName> handle = method;
|
||||
return MakeCallback(recv, handle, argc, argv);
|
||||
}
|
||||
|
||||
inline bool HasInstance(v8::Persistent<v8::FunctionTemplate>& function_template,
|
||||
v8::Handle<v8::Value> value) {
|
||||
v8::Local<v8::FunctionTemplate> function_template_handle =
|
||||
v8::Local<v8::FunctionTemplate>::New(node_isolate, function_template);
|
||||
return function_template_handle->HasInstance(value);
|
||||
}
|
||||
|
||||
inline v8::Local<v8::Object> NewInstance(v8::Persistent<v8::Function>& ctor,
|
||||
int argc,
|
||||
v8::Handle<v8::Value>* argv) {
|
||||
v8::Local<v8::Function> constructor_handle =
|
||||
v8::Local<v8::Function>::New(node_isolate, ctor);
|
||||
return constructor_handle->NewInstance(argc, argv);
|
||||
}
|
||||
|
||||
namespace Buffer {
|
||||
|
||||
template <typename TypeName>
|
||||
inline char* Data(v8::Persistent<TypeName>& val) {
|
||||
NODE_EXTERN char* Data(v8::Handle<v8::Value>);
|
||||
NODE_EXTERN char* Data(v8::Handle<v8::Object>);
|
||||
return Data(v8::Local<TypeName>::New(node_isolate, val));
|
||||
}
|
||||
|
||||
template <typename TypeName>
|
||||
inline size_t Length(v8::Persistent<TypeName>& val) {
|
||||
NODE_EXTERN size_t Length(v8::Handle<v8::Value>);
|
||||
NODE_EXTERN size_t Length(v8::Handle<v8::Object>);
|
||||
return Length(v8::Local<TypeName>::New(node_isolate, val));
|
||||
}
|
||||
|
||||
} // namespace Buffer
|
||||
|
||||
} // namespace node
|
||||
|
||||
#endif // SRC_NODE_INTERNALS_H_
|
||||
|
@ -38,49 +38,56 @@
|
||||
namespace node {
|
||||
|
||||
class NODE_EXTERN ObjectWrap {
|
||||
public:
|
||||
ObjectWrap ( ) {
|
||||
public:
|
||||
ObjectWrap() {
|
||||
refs_ = 0;
|
||||
}
|
||||
|
||||
|
||||
virtual ~ObjectWrap ( ) {
|
||||
if (!handle_.IsEmpty()) {
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
assert(handle_.IsNearDeath(isolate));
|
||||
handle_.ClearWeak(isolate);
|
||||
handle_->SetAlignedPointerInInternalField(0, 0);
|
||||
handle_.Dispose(isolate);
|
||||
handle_.Clear();
|
||||
}
|
||||
virtual ~ObjectWrap() {
|
||||
if (persistent().IsEmpty()) return;
|
||||
assert(persistent().IsNearDeath());
|
||||
persistent().ClearWeak();
|
||||
persistent().Dispose();
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
static inline T* Unwrap (v8::Handle<v8::Object> handle) {
|
||||
static inline T* Unwrap(v8::Handle<v8::Object> handle) {
|
||||
assert(!handle.IsEmpty());
|
||||
assert(handle->InternalFieldCount() > 0);
|
||||
return static_cast<T*>(handle->GetAlignedPointerFromInternalField(0));
|
||||
}
|
||||
|
||||
|
||||
v8::Persistent<v8::Object> handle_; // ro
|
||||
inline v8::Local<v8::Object> handle() {
|
||||
return handle(v8::Isolate::GetCurrent());
|
||||
}
|
||||
|
||||
protected:
|
||||
inline void Wrap (v8::Handle<v8::Object> handle) {
|
||||
assert(handle_.IsEmpty());
|
||||
|
||||
inline v8::Local<v8::Object> handle(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Object>::New(isolate, persistent());
|
||||
}
|
||||
|
||||
|
||||
inline v8::Persistent<v8::Object>& persistent() {
|
||||
return handle_;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
inline void Wrap(v8::Handle<v8::Object> handle) {
|
||||
assert(persistent().IsEmpty());
|
||||
assert(handle->InternalFieldCount() > 0);
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
handle_ = v8::Persistent<v8::Object>::New(isolate, handle);
|
||||
handle_->SetAlignedPointerInInternalField(0, this);
|
||||
handle->SetAlignedPointerInInternalField(0, this);
|
||||
persistent().Reset(v8::Isolate::GetCurrent(), handle);
|
||||
MakeWeak();
|
||||
}
|
||||
|
||||
|
||||
inline void MakeWeak (void) {
|
||||
v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
handle_.MakeWeak(isolate, this, WeakCallback);
|
||||
handle_.MarkIndependent(isolate);
|
||||
inline void MakeWeak(void) {
|
||||
persistent().MakeWeak(this, WeakCallback);
|
||||
persistent().MarkIndependent();
|
||||
}
|
||||
|
||||
/* Ref() marks the object as being attached to an event loop.
|
||||
@ -88,9 +95,9 @@ class NODE_EXTERN ObjectWrap {
|
||||
* all references are lost.
|
||||
*/
|
||||
virtual void Ref() {
|
||||
assert(!handle_.IsEmpty());
|
||||
assert(!persistent().IsEmpty());
|
||||
persistent().ClearWeak();
|
||||
refs_++;
|
||||
handle_.ClearWeak(v8::Isolate::GetCurrent());
|
||||
}
|
||||
|
||||
/* Unref() marks an object as detached from the event loop. This is its
|
||||
@ -103,26 +110,26 @@ class NODE_EXTERN ObjectWrap {
|
||||
* DO NOT CALL THIS FROM DESTRUCTOR
|
||||
*/
|
||||
virtual void Unref() {
|
||||
assert(!handle_.IsEmpty());
|
||||
assert(!handle_.IsWeak(v8::Isolate::GetCurrent()));
|
||||
assert(!persistent().IsEmpty());
|
||||
assert(!persistent().IsWeak());
|
||||
assert(refs_ > 0);
|
||||
if (--refs_ == 0) { MakeWeak(); }
|
||||
if (--refs_ == 0) MakeWeak();
|
||||
}
|
||||
|
||||
int refs_; // ro
|
||||
|
||||
int refs_; // ro
|
||||
|
||||
|
||||
private:
|
||||
private:
|
||||
static void WeakCallback(v8::Isolate* isolate,
|
||||
v8::Persistent<v8::Object>* pobj,
|
||||
ObjectWrap* wrap) {
|
||||
v8::HandleScope scope(isolate);
|
||||
assert(wrap->refs_ == 0);
|
||||
assert(*pobj == wrap->handle_);
|
||||
assert((*pobj).IsNearDeath(isolate));
|
||||
assert(*pobj == wrap->persistent());
|
||||
assert((*pobj).IsNearDeath());
|
||||
delete wrap;
|
||||
}
|
||||
|
||||
v8::Persistent<v8::Object> handle_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
|
119
src/node_os.cc
119
src/node_os.cc
@ -46,81 +46,95 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using v8::Array;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Handle<Value> GetEndianness(const Arguments& args) {
|
||||
|
||||
static void GetEndianness(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
return scope.Close(String::New(IsBigEndian() ? "BE" : "LE"));
|
||||
const char* rval = IsBigEndian() ? "BE" : "LE";
|
||||
args.GetReturnValue().Set(String::New(rval));
|
||||
}
|
||||
|
||||
static Handle<Value> GetHostname(const Arguments& args) {
|
||||
|
||||
static void GetHostname(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
char buf[MAXHOSTNAMELEN + 1];
|
||||
|
||||
if (gethostname(buf, sizeof(buf))) {
|
||||
#ifdef __POSIX__
|
||||
return ThrowException(ErrnoException(errno, "gethostname"));
|
||||
int errorno = errno;
|
||||
#else // __MINGW32__
|
||||
return ThrowException(ErrnoException(WSAGetLastError(), "gethostname"));
|
||||
int errorno = WSAGetLastError();
|
||||
#endif // __MINGW32__
|
||||
return ThrowErrnoException(errorno, "gethostname");
|
||||
}
|
||||
buf[sizeof(buf) - 1] = '\0';
|
||||
|
||||
return scope.Close(String::New(buf));
|
||||
args.GetReturnValue().Set(String::New(buf));
|
||||
}
|
||||
|
||||
static Handle<Value> GetOSType(const Arguments& args) {
|
||||
|
||||
static void GetOSType(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
const char* rval;
|
||||
|
||||
#ifdef __POSIX__
|
||||
struct utsname info;
|
||||
if (uname(&info) < 0) {
|
||||
return ThrowException(ErrnoException(errno, "uname"));
|
||||
return ThrowErrnoException(errno, "uname");
|
||||
}
|
||||
return scope.Close(String::New(info.sysname));
|
||||
rval = info.sysname;
|
||||
#else // __MINGW32__
|
||||
return scope.Close(String::New("Windows_NT"));
|
||||
rval ="Windows_NT";
|
||||
#endif
|
||||
|
||||
args.GetReturnValue().Set(String::New(rval));
|
||||
}
|
||||
|
||||
static Handle<Value> GetOSRelease(const Arguments& args) {
|
||||
|
||||
static void GetOSRelease(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
const char* rval;
|
||||
|
||||
#ifdef __POSIX__
|
||||
struct utsname info;
|
||||
if (uname(&info) < 0) {
|
||||
return ThrowException(ErrnoException(errno, "uname"));
|
||||
return ThrowErrnoException(errno, "uname");
|
||||
}
|
||||
return scope.Close(String::New(info.release));
|
||||
rval = info.release;
|
||||
#else // __MINGW32__
|
||||
char release[256];
|
||||
OSVERSIONINFO info;
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
|
||||
if (GetVersionEx(&info) == 0) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
info.dwOSVersionInfoSize = sizeof(info);
|
||||
if (GetVersionEx(&info) == 0) return;
|
||||
|
||||
sprintf(release, "%d.%d.%d", static_cast<int>(info.dwMajorVersion),
|
||||
static_cast<int>(info.dwMinorVersion), static_cast<int>(info.dwBuildNumber));
|
||||
return scope.Close(String::New(release));
|
||||
rval = release;
|
||||
#endif
|
||||
|
||||
args.GetReturnValue().Set(String::New(rval));
|
||||
}
|
||||
|
||||
static Handle<Value> GetCPUInfo(const Arguments& args) {
|
||||
|
||||
static void GetCPUInfo(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
uv_cpu_info_t* cpu_infos;
|
||||
int count, i;
|
||||
|
||||
uv_err_t err = uv_cpu_info(&cpu_infos, &count);
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
if (err.code != UV_OK) return;
|
||||
|
||||
Local<Array> cpus = Array::New();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
Local<Object> times_info = Object::New();
|
||||
times_info->Set(String::New("user"),
|
||||
@ -143,60 +157,48 @@ static Handle<Value> GetCPUInfo(const Arguments& args) {
|
||||
}
|
||||
|
||||
uv_free_cpu_info(cpu_infos, count);
|
||||
|
||||
return scope.Close(cpus);
|
||||
args.GetReturnValue().Set(cpus);
|
||||
}
|
||||
|
||||
static Handle<Value> GetFreeMemory(const Arguments& args) {
|
||||
|
||||
static void GetFreeMemory(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
double amount = uv_get_free_memory();
|
||||
|
||||
if (amount < 0) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
return scope.Close(Number::New(amount));
|
||||
if (amount < 0) return;
|
||||
args.GetReturnValue().Set(amount);
|
||||
}
|
||||
|
||||
static Handle<Value> GetTotalMemory(const Arguments& args) {
|
||||
|
||||
static void GetTotalMemory(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
double amount = uv_get_total_memory();
|
||||
|
||||
if (amount < 0) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
return scope.Close(Number::New(amount));
|
||||
if (amount < 0) return;
|
||||
args.GetReturnValue().Set(amount);
|
||||
}
|
||||
|
||||
static Handle<Value> GetUptime(const Arguments& args) {
|
||||
|
||||
static void GetUptime(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
double uptime;
|
||||
|
||||
uv_err_t err = uv_uptime(&uptime);
|
||||
|
||||
if (err.code != UV_OK) {
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
return scope.Close(Number::New(uptime));
|
||||
if (err.code != UV_OK) return;
|
||||
args.GetReturnValue().Set(uptime);
|
||||
}
|
||||
|
||||
static Handle<Value> GetLoadAvg(const Arguments& args) {
|
||||
|
||||
static void GetLoadAvg(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
double loadavg[3];
|
||||
uv_loadavg(loadavg);
|
||||
|
||||
Local<Array> loads = Array::New(3);
|
||||
loads->Set(0, Number::New(loadavg[0]));
|
||||
loads->Set(1, Number::New(loadavg[1]));
|
||||
loads->Set(2, Number::New(loadavg[2]));
|
||||
|
||||
return scope.Close(loads);
|
||||
args.GetReturnValue().Set(loads);
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> GetInterfaceAddresses(const Arguments& args) {
|
||||
static void GetInterfaceAddresses(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
uv_interface_address_t* interfaces;
|
||||
int count, i;
|
||||
@ -207,9 +209,9 @@ static Handle<Value> GetInterfaceAddresses(const Arguments& args) {
|
||||
Local<Array> ifarr;
|
||||
|
||||
uv_err_t err = uv_interface_addresses(&interfaces, &count);
|
||||
|
||||
if (err.code != UV_OK)
|
||||
return ThrowException(UVException(err.code, "uv_interface_addresses"));
|
||||
if (err.code != UV_OK) {
|
||||
return ThrowUVException(err.code, "uv_interface_addresses");
|
||||
}
|
||||
|
||||
ret = Object::New();
|
||||
|
||||
@ -248,8 +250,7 @@ static Handle<Value> GetInterfaceAddresses(const Arguments& args) {
|
||||
}
|
||||
|
||||
uv_free_interface_addresses(interfaces, count);
|
||||
|
||||
return scope.Close(ret);
|
||||
args.GetReturnValue().Set(ret);
|
||||
}
|
||||
|
||||
|
||||
|
@ -26,11 +26,11 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Array;
|
||||
using v8::Context;
|
||||
using v8::Exception;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -39,7 +39,6 @@ using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::Script;
|
||||
using v8::String;
|
||||
using v8::ThrowException;
|
||||
using v8::TryCatch;
|
||||
using v8::V8;
|
||||
using v8::Value;
|
||||
@ -48,9 +47,9 @@ using v8::Value;
|
||||
class WrappedContext : ObjectWrap {
|
||||
public:
|
||||
static void Initialize(Handle<Object> target);
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
static void New(const FunctionCallbackInfo<Value>& args);
|
||||
|
||||
Persistent<Context> GetV8Context();
|
||||
Local<Context> GetV8Context();
|
||||
static Local<Object> NewInstance();
|
||||
static bool InstanceOf(Handle<Value> value);
|
||||
|
||||
@ -81,57 +80,55 @@ class WrappedScript : ObjectWrap {
|
||||
EvalContextFlags context_flag,
|
||||
EvalOutputFlags output_flag,
|
||||
EvalTimeoutFlags timeout_flag>
|
||||
static Handle<Value> EvalMachine(const Arguments& args);
|
||||
static void EvalMachine(const FunctionCallbackInfo<Value>& args);
|
||||
|
||||
protected:
|
||||
static Persistent<FunctionTemplate> constructor_template;
|
||||
|
||||
WrappedScript() : ObjectWrap() {}
|
||||
~WrappedScript();
|
||||
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
static Handle<Value> CreateContext(const Arguments& arg);
|
||||
static Handle<Value> RunInContext(const Arguments& args);
|
||||
static Handle<Value> RunInThisContext(const Arguments& args);
|
||||
static Handle<Value> RunInNewContext(const Arguments& args);
|
||||
static Handle<Value> CompileRunInContext(const Arguments& args);
|
||||
static Handle<Value> CompileRunInThisContext(const Arguments& args);
|
||||
static Handle<Value> CompileRunInNewContext(const Arguments& args);
|
||||
static void New(const FunctionCallbackInfo<Value>& args);
|
||||
static void CreateContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void RunInContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void RunInThisContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void RunInNewContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void CompileRunInContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void CompileRunInThisContext(const FunctionCallbackInfo<Value>& args);
|
||||
static void CompileRunInNewContext(const FunctionCallbackInfo<Value>& args);
|
||||
|
||||
Persistent<Script> script_;
|
||||
};
|
||||
|
||||
|
||||
Persistent<Function> cloneObjectMethod;
|
||||
|
||||
void CloneObject(Handle<Object> recv,
|
||||
Handle<Value> source, Handle<Value> target) {
|
||||
Handle<Value> source,
|
||||
Handle<Value> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Handle<Value> args[] = {source, target};
|
||||
const char raw_script_source[] =
|
||||
"(function(source, target) { \n"
|
||||
" Object.getOwnPropertyNames(source).forEach(function(key) { \n"
|
||||
" try { \n"
|
||||
" var desc = Object.getOwnPropertyDescriptor(source, key); \n"
|
||||
" if (desc.value === source) desc.value = target; \n"
|
||||
" Object.defineProperty(target, key, desc); \n"
|
||||
" } catch (e) { \n"
|
||||
" // Catch sealed properties errors \n"
|
||||
" } \n"
|
||||
" }); \n"
|
||||
"}); \n";
|
||||
|
||||
// Init
|
||||
if (cloneObjectMethod.IsEmpty()) {
|
||||
Local<Function> cloneObjectMethod_ = Local<Function>::Cast(
|
||||
Script::Compile(String::New(
|
||||
"(function(source, target) {\n\
|
||||
Object.getOwnPropertyNames(source).forEach(function(key) {\n\
|
||||
try {\n\
|
||||
var desc = Object.getOwnPropertyDescriptor(source, key);\n\
|
||||
if (desc.value === source) desc.value = target;\n\
|
||||
Object.defineProperty(target, key, desc);\n\
|
||||
} catch (e) {\n\
|
||||
// Catch sealed properties errors\n\
|
||||
}\n\
|
||||
});\n\
|
||||
})"
|
||||
), String::New("binding:script"))->Run()
|
||||
);
|
||||
cloneObjectMethod = Persistent<Function>::New(node_isolate,
|
||||
cloneObjectMethod_);
|
||||
}
|
||||
Local<String> script_source =
|
||||
String::New(raw_script_source, sizeof(raw_script_source) - 1);
|
||||
Local<Script> script =
|
||||
Script::Compile(script_source, String::New("binding:script"));
|
||||
|
||||
cloneObjectMethod->Call(recv, 2, args);
|
||||
Local<Function> fun = script->Run().As<Function>();
|
||||
assert(fun.IsEmpty() == false);
|
||||
assert(fun->IsFunction() == true);
|
||||
|
||||
Handle<Value> argv[] = { source, target };
|
||||
Handle<Value> rc = fun->Call(recv, ARRAY_SIZE(argv), argv);
|
||||
assert(rc.IsEmpty() == false);
|
||||
}
|
||||
|
||||
|
||||
@ -139,124 +136,110 @@ void WrappedContext::Initialize(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(WrappedContext::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
constructor_template->SetClassName(String::NewSymbol("Context"));
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
t->SetClassName(String::NewSymbol("Context"));
|
||||
|
||||
target->Set(String::NewSymbol("Context"),
|
||||
constructor_template->GetFunction());
|
||||
target->Set(String::NewSymbol("Context"), t->GetFunction());
|
||||
constructor_template.Reset(node_isolate, t);
|
||||
}
|
||||
|
||||
|
||||
bool WrappedContext::InstanceOf(Handle<Value> value) {
|
||||
return !value.IsEmpty() && constructor_template->HasInstance(value);
|
||||
return !value.IsEmpty() && HasInstance(constructor_template, value);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedContext::New(const Arguments& args) {
|
||||
void WrappedContext::New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
WrappedContext *t = new WrappedContext();
|
||||
t->Wrap(args.This());
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
|
||||
WrappedContext::WrappedContext() : ObjectWrap() {
|
||||
context_ = Persistent<Context>::New(node_isolate, Context::New(node_isolate));
|
||||
context_.Reset(node_isolate, Context::New(node_isolate));
|
||||
}
|
||||
|
||||
|
||||
WrappedContext::~WrappedContext() {
|
||||
context_.Dispose(node_isolate);
|
||||
context_.Dispose();
|
||||
}
|
||||
|
||||
|
||||
Local<Object> WrappedContext::NewInstance() {
|
||||
Local<Object> context = constructor_template->GetFunction()->NewInstance();
|
||||
return context;
|
||||
Local<FunctionTemplate> constructor_template_handle =
|
||||
Local<FunctionTemplate>::New(node_isolate, constructor_template);
|
||||
return constructor_template_handle->GetFunction()->NewInstance();
|
||||
}
|
||||
|
||||
|
||||
Persistent<Context> WrappedContext::GetV8Context() {
|
||||
return context_;
|
||||
Local<Context> WrappedContext::GetV8Context() {
|
||||
return Local<Context>::New(node_isolate, context_);
|
||||
}
|
||||
|
||||
|
||||
Persistent<FunctionTemplate> WrappedScript::constructor_template;
|
||||
|
||||
|
||||
void WrappedScript::Initialize(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(WrappedScript::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
// Note: We use 'NodeScript' instead of 'Script' so that we do not
|
||||
// conflict with V8's Script class defined in v8/src/messages.js
|
||||
// See GH-203 https://github.com/joyent/node/issues/203
|
||||
constructor_template->SetClassName(String::NewSymbol("NodeScript"));
|
||||
t->SetClassName(String::NewSymbol("NodeScript"));
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template,
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
"createContext",
|
||||
WrappedScript::CreateContext);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template,
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
"runInContext",
|
||||
WrappedScript::RunInContext);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template,
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
"runInThisContext",
|
||||
WrappedScript::RunInThisContext);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template,
|
||||
NODE_SET_PROTOTYPE_METHOD(t,
|
||||
"runInNewContext",
|
||||
WrappedScript::RunInNewContext);
|
||||
|
||||
NODE_SET_METHOD(constructor_template,
|
||||
NODE_SET_METHOD(t,
|
||||
"createContext",
|
||||
WrappedScript::CreateContext);
|
||||
|
||||
NODE_SET_METHOD(constructor_template,
|
||||
NODE_SET_METHOD(t,
|
||||
"runInContext",
|
||||
WrappedScript::CompileRunInContext);
|
||||
|
||||
NODE_SET_METHOD(constructor_template,
|
||||
NODE_SET_METHOD(t,
|
||||
"runInThisContext",
|
||||
WrappedScript::CompileRunInThisContext);
|
||||
|
||||
NODE_SET_METHOD(constructor_template,
|
||||
NODE_SET_METHOD(t,
|
||||
"runInNewContext",
|
||||
WrappedScript::CompileRunInNewContext);
|
||||
|
||||
target->Set(String::NewSymbol("NodeScript"),
|
||||
constructor_template->GetFunction());
|
||||
target->Set(String::NewSymbol("NodeScript"), t->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::New(const Arguments& args) {
|
||||
if (!args.IsConstructCall()) {
|
||||
return FromConstructorTemplate(constructor_template, args);
|
||||
}
|
||||
|
||||
void WrappedScript::New(const FunctionCallbackInfo<Value>& args) {
|
||||
assert(args.IsConstructCall() == true);
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
WrappedScript *t = new WrappedScript();
|
||||
t->Wrap(args.This());
|
||||
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
WrappedScript::EvalMachine<
|
||||
compileCode, thisContext, wrapExternal, noTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
WrappedScript::~WrappedScript() {
|
||||
script_.Dispose(node_isolate);
|
||||
script_.Dispose();
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::CreateContext(const Arguments& args) {
|
||||
void WrappedScript::CreateContext(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> context = WrappedContext::NewInstance();
|
||||
@ -267,54 +250,50 @@ Handle<Value> WrappedScript::CreateContext(const Arguments& args) {
|
||||
|
||||
CloneObject(args.This(), sandbox, context);
|
||||
} else {
|
||||
return ThrowException(Exception::TypeError(String::New(
|
||||
"createContext() accept only object as first argument.")));
|
||||
return ThrowTypeError(
|
||||
"createContext() accept only object as first argument.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return scope.Close(context);
|
||||
args.GetReturnValue().Set(context);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::RunInContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::RunInContext(const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
unwrapExternal, userContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::RunInThisContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::RunInThisContext(const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
unwrapExternal, thisContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::RunInNewContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::RunInNewContext(const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
unwrapExternal, newContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::CompileRunInContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::CompileRunInContext(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
compileCode, userContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::CompileRunInThisContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::CompileRunInThisContext(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
compileCode, thisContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> WrappedScript::CompileRunInNewContext(const Arguments& args) {
|
||||
return
|
||||
WrappedScript::EvalMachine<
|
||||
void WrappedScript::CompileRunInNewContext(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
WrappedScript::EvalMachine<
|
||||
compileCode, newContext, returnResult, useTimeout>(args);
|
||||
}
|
||||
|
||||
@ -323,23 +302,20 @@ template <WrappedScript::EvalInputFlags input_flag,
|
||||
WrappedScript::EvalContextFlags context_flag,
|
||||
WrappedScript::EvalOutputFlags output_flag,
|
||||
WrappedScript::EvalTimeoutFlags timeout_flag>
|
||||
Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
void WrappedScript::EvalMachine(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (input_flag == compileCode && args.Length() < 1) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("needs at least 'code' argument.")));
|
||||
return ThrowTypeError("needs at least 'code' argument.");
|
||||
}
|
||||
|
||||
const int sandbox_index = input_flag == compileCode ? 1 : 0;
|
||||
if (context_flag == userContext
|
||||
&& !WrappedContext::InstanceOf(args[sandbox_index]))
|
||||
{
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("needs a 'context' argument.")));
|
||||
return ThrowTypeError("needs a 'context' argument.");
|
||||
}
|
||||
|
||||
|
||||
Local<String> code;
|
||||
if (input_flag == compileCode) code = args[0]->ToString();
|
||||
|
||||
@ -361,8 +337,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
const int timeout_index = filename_index + 1;
|
||||
if (timeout_flag == useTimeout && args.Length() > timeout_index) {
|
||||
if (!args[timeout_index]->IsUint32()) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("needs an unsigned integer 'ms' argument.")));
|
||||
return ThrowTypeError("needs an unsigned integer 'ms' argument.");
|
||||
}
|
||||
timeout = args[timeout_index]->Uint32Value();
|
||||
}
|
||||
@ -376,7 +351,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
display_error = true;
|
||||
}
|
||||
|
||||
Handle<Context> context = Context::GetCurrent();
|
||||
Local<Context> context = Context::GetCurrent();
|
||||
|
||||
Local<Array> keys;
|
||||
if (context_flag == newContext) {
|
||||
@ -406,7 +381,7 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
try_catch.SetVerbose(false);
|
||||
|
||||
Handle<Value> result;
|
||||
Handle<Script> script;
|
||||
Local<Script> script;
|
||||
|
||||
if (input_flag == compileCode) {
|
||||
// well, here WrappedScript::New would suffice in all cases, but maybe
|
||||
@ -418,23 +393,21 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
if (display_error) DisplayExceptionLine(try_catch.Message());
|
||||
|
||||
// Hack because I can't get a proper stacktrace on SyntaxError
|
||||
return try_catch.ReThrow();
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.This());
|
||||
if (!n_script) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Must be called as a method of Script.")));
|
||||
return ThrowError("Must be called as a method of Script.");
|
||||
} else if (n_script->script_.IsEmpty()) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("'this' must be a result of previous "
|
||||
"new Script(code) call.")));
|
||||
return ThrowError(
|
||||
"'this' must be a result of previous new Script(code) call.");
|
||||
}
|
||||
|
||||
script = n_script->script_;
|
||||
script = Local<Script>::New(node_isolate, n_script->script_);
|
||||
}
|
||||
|
||||
|
||||
if (output_flag == returnResult) {
|
||||
if (timeout) {
|
||||
Watchdog wd(timeout);
|
||||
@ -444,20 +417,19 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
}
|
||||
if (try_catch.HasCaught() && try_catch.HasTerminated()) {
|
||||
V8::CancelTerminateExecution(args.GetIsolate());
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Script execution timed out.")));
|
||||
return ThrowError("Script execution timed out.");
|
||||
}
|
||||
if (result.IsEmpty()) {
|
||||
if (display_error) DisplayExceptionLine(try_catch.Message());
|
||||
return try_catch.ReThrow();
|
||||
try_catch.ReThrow();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
WrappedScript *n_script = ObjectWrap::Unwrap<WrappedScript>(args.This());
|
||||
if (!n_script) {
|
||||
return ThrowException(Exception::Error(
|
||||
String::New("Must be called as a method of Script.")));
|
||||
return ThrowError("Must be called as a method of Script.");
|
||||
}
|
||||
n_script->script_ = Persistent<Script>::New(node_isolate, script);
|
||||
n_script->script_.Reset(node_isolate, script);
|
||||
result = args.This();
|
||||
}
|
||||
|
||||
@ -466,13 +438,12 @@ Handle<Value> WrappedScript::EvalMachine(const Arguments& args) {
|
||||
CloneObject(args.This(), context->Global()->GetPrototype(), sandbox);
|
||||
}
|
||||
|
||||
return result == args.This() ? result : scope.Close(result);
|
||||
args.GetReturnValue().Set(result);
|
||||
}
|
||||
|
||||
|
||||
void InitEvals(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
WrappedContext::Initialize(target);
|
||||
WrappedScript::Initialize(target);
|
||||
}
|
||||
@ -480,6 +451,4 @@ void InitEvals(Handle<Object> target) {
|
||||
|
||||
} // namespace node
|
||||
|
||||
|
||||
NODE_MODULE(node_evals, node::InitEvals)
|
||||
|
||||
|
@ -27,25 +27,31 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
Persistent<FunctionTemplate> StatWatcher::constructor_template;
|
||||
static Persistent<String> onchange_sym;
|
||||
static Persistent<String> onstop_sym;
|
||||
static Cached<String> onchange_sym;
|
||||
static Cached<String> onstop_sym;
|
||||
|
||||
|
||||
void StatWatcher::Initialize(Handle<Object> target) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(StatWatcher::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
constructor_template->SetClassName(String::NewSymbol("StatWatcher"));
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
t->SetClassName(String::NewSymbol("StatWatcher"));
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", StatWatcher::Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", StatWatcher::Stop);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "start", StatWatcher::Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "stop", StatWatcher::Stop);
|
||||
|
||||
target->Set(String::NewSymbol("StatWatcher"), constructor_template->GetFunction());
|
||||
target->Set(String::NewSymbol("StatWatcher"), t->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
@ -84,22 +90,24 @@ void StatWatcher::Callback(uv_fs_poll_t* handle,
|
||||
SetErrno(uv_last_error(wrap->watcher_->loop));
|
||||
}
|
||||
if (onchange_sym.IsEmpty()) {
|
||||
onchange_sym = NODE_PSYMBOL("onchange");
|
||||
onchange_sym = String::New("onchange");
|
||||
}
|
||||
MakeCallback(wrap->handle_, onchange_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->handle(node_isolate),
|
||||
onchange_sym,
|
||||
ARRAY_SIZE(argv),
|
||||
argv);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StatWatcher::New(const Arguments& args) {
|
||||
void StatWatcher::New(const FunctionCallbackInfo<Value>& args) {
|
||||
assert(args.IsConstructCall());
|
||||
HandleScope scope(node_isolate);
|
||||
StatWatcher* s = new StatWatcher();
|
||||
s->Wrap(args.This());
|
||||
return args.This();
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StatWatcher::Start(const Arguments& args) {
|
||||
void StatWatcher::Start(const FunctionCallbackInfo<Value>& args) {
|
||||
assert(args.Length() == 3);
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
@ -111,20 +119,17 @@ Handle<Value> StatWatcher::Start(const Arguments& args) {
|
||||
if (!persistent) uv_unref(reinterpret_cast<uv_handle_t*>(wrap->watcher_));
|
||||
uv_fs_poll_start(wrap->watcher_, Callback, *path, interval);
|
||||
wrap->Ref();
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StatWatcher::Stop(const Arguments& args) {
|
||||
void StatWatcher::Stop(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
StatWatcher* wrap = ObjectWrap::Unwrap<StatWatcher>(args.This());
|
||||
if (onstop_sym.IsEmpty()) {
|
||||
onstop_sym = NODE_PSYMBOL("onstop");
|
||||
onstop_sym = String::New("onstop");
|
||||
}
|
||||
MakeCallback(wrap->handle_, onstop_sym, 0, NULL);
|
||||
MakeCallback(wrap->handle(node_isolate), onstop_sym, 0, NULL);
|
||||
wrap->Stop();
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
|
@ -37,9 +37,9 @@ class StatWatcher : ObjectWrap {
|
||||
StatWatcher();
|
||||
virtual ~StatWatcher();
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Stop(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Stop(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
private:
|
||||
static void Callback(uv_fs_poll_t* handle,
|
||||
|
@ -39,15 +39,15 @@ extern v8::Persistent<v8::FunctionTemplate> tcpConstructorTmpl;
|
||||
#define WITH_GENERIC_STREAM(obj, BODY) \
|
||||
do { \
|
||||
if (!tcpConstructorTmpl.IsEmpty() && \
|
||||
tcpConstructorTmpl->HasInstance(obj)) { \
|
||||
HasInstance(tcpConstructorTmpl, obj)) { \
|
||||
PipeWrap* wrap = PipeWrap::Unwrap(obj); \
|
||||
BODY \
|
||||
} else if (!ttyConstructorTmpl.IsEmpty() && \
|
||||
ttyConstructorTmpl->HasInstance(obj)) { \
|
||||
HasInstance(ttyConstructorTmpl, obj)) { \
|
||||
TTYWrap* wrap = TTYWrap::Unwrap(obj); \
|
||||
BODY \
|
||||
} else if (!pipeConstructorTmpl.IsEmpty() && \
|
||||
pipeConstructorTmpl->HasInstance(obj)) { \
|
||||
HasInstance(pipeConstructorTmpl, obj)) { \
|
||||
TCPWrap* wrap = TCPWrap::Unwrap(obj); \
|
||||
BODY \
|
||||
} \
|
||||
|
@ -32,11 +32,20 @@
|
||||
|
||||
|
||||
namespace node {
|
||||
using namespace v8;
|
||||
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> callback_sym;
|
||||
static Persistent<String> onerror_sym;
|
||||
static Cached<String> callback_sym;
|
||||
static Cached<String> onerror_sym;
|
||||
|
||||
enum node_zlib_mode {
|
||||
NONE,
|
||||
@ -104,16 +113,15 @@ class ZCtx : public ObjectWrap {
|
||||
}
|
||||
|
||||
|
||||
static Handle<Value> Close(const Arguments& args) {
|
||||
static void Close(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
|
||||
ctx->Close();
|
||||
return scope.Close(Undefined(node_isolate));
|
||||
}
|
||||
|
||||
|
||||
// write(flush, in, in_off, in_len, out, out_off, out_len)
|
||||
static Handle<Value> Write(const Arguments& args) {
|
||||
static void Write(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
assert(args.Length() == 7);
|
||||
|
||||
@ -183,7 +191,7 @@ class ZCtx : public ObjectWrap {
|
||||
ZCtx::Process,
|
||||
ZCtx::After);
|
||||
|
||||
return ctx->handle_;
|
||||
args.GetReturnValue().Set(ctx->persistent());
|
||||
}
|
||||
|
||||
|
||||
@ -273,10 +281,10 @@ class ZCtx : public ObjectWrap {
|
||||
ctx->write_in_progress_ = false;
|
||||
|
||||
// call the write() cb
|
||||
assert(ctx->handle_->Get(callback_sym)->IsFunction() &&
|
||||
"Invalid callback");
|
||||
Local<Object> handle = ctx->handle(node_isolate);
|
||||
assert(handle->Get(callback_sym)->IsFunction() && "Invalid callback");
|
||||
Local<Value> args[2] = { avail_in, avail_out };
|
||||
MakeCallback(ctx->handle_, callback_sym, ARRAY_SIZE(args), args);
|
||||
MakeCallback(handle, callback_sym, ARRAY_SIZE(args), args);
|
||||
|
||||
ctx->Unref();
|
||||
}
|
||||
@ -289,37 +297,37 @@ class ZCtx : public ObjectWrap {
|
||||
msg = msg_;
|
||||
}
|
||||
|
||||
assert(ctx->handle_->Get(onerror_sym)->IsFunction() &&
|
||||
"Invalid error handler");
|
||||
Local<Object> handle = ctx->handle(node_isolate);
|
||||
assert(handle->Get(onerror_sym)->IsFunction() && "Invalid error handler");
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Value> args[2] = { String::New(msg),
|
||||
Local<Value>::New(node_isolate,
|
||||
Number::New(ctx->err_)) };
|
||||
MakeCallback(ctx->handle_, onerror_sym, ARRAY_SIZE(args), args);
|
||||
Local<Value> args[2] = {
|
||||
String::New(msg),
|
||||
Number::New(ctx->err_)
|
||||
};
|
||||
MakeCallback(handle, onerror_sym, ARRAY_SIZE(args), args);
|
||||
|
||||
// no hope of rescue.
|
||||
ctx->write_in_progress_ = false;
|
||||
ctx->Unref();
|
||||
}
|
||||
|
||||
static Handle<Value> New(const Arguments& args) {
|
||||
static void New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
if (args.Length() < 1 || !args[0]->IsInt32()) {
|
||||
return ThrowException(Exception::TypeError(String::New("Bad argument")));
|
||||
return ThrowTypeError("Bad argument");
|
||||
}
|
||||
node_zlib_mode mode = (node_zlib_mode) args[0]->Int32Value();
|
||||
|
||||
if (mode < DEFLATE || mode > UNZIP) {
|
||||
return ThrowException(Exception::TypeError(String::New("Bad argument")));
|
||||
return ThrowTypeError("Bad argument");
|
||||
}
|
||||
|
||||
ZCtx *ctx = new ZCtx(mode);
|
||||
ctx->Wrap(args.This());
|
||||
return args.This();
|
||||
}
|
||||
|
||||
// just pull the ints out of the args and call the other Init
|
||||
static Handle<Value> Init(const Arguments& args) {
|
||||
static void Init(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert((args.Length() == 4 || args.Length() == 5) &&
|
||||
@ -357,10 +365,9 @@ class ZCtx : public ObjectWrap {
|
||||
Init(ctx, level, windowBits, memLevel, strategy,
|
||||
dictionary, dictionary_len);
|
||||
SetDictionary(ctx);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
static Handle<Value> Params(const Arguments& args) {
|
||||
static void Params(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(args.Length() == 2 && "params(level, strategy)");
|
||||
@ -368,18 +375,15 @@ class ZCtx : public ObjectWrap {
|
||||
ZCtx* ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
|
||||
|
||||
Params(ctx, args[0]->Int32Value(), args[1]->Int32Value());
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
static Handle<Value> Reset(const Arguments &args) {
|
||||
static void Reset(const FunctionCallbackInfo<Value> &args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
ZCtx *ctx = ObjectWrap::Unwrap<ZCtx>(args.This());
|
||||
|
||||
Reset(ctx);
|
||||
SetDictionary(ctx);
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
static void Init(ZCtx *ctx, int level, int windowBits, int memLevel,
|
||||
@ -549,8 +553,8 @@ void InitZlib(Handle<Object> target) {
|
||||
z->SetClassName(String::NewSymbol("Zlib"));
|
||||
target->Set(String::NewSymbol("Zlib"), z->GetFunction());
|
||||
|
||||
callback_sym = NODE_PSYMBOL("callback");
|
||||
onerror_sym = NODE_PSYMBOL("onerror");
|
||||
callback_sym = String::New("callback");
|
||||
onerror_sym = String::New("onerror");
|
||||
|
||||
// valid flush values.
|
||||
NODE_DEFINE_CONSTANT(target, Z_NO_FLUSH);
|
||||
|
@ -29,9 +29,9 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Boolean;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -43,11 +43,9 @@ using v8::PropertyAttribute;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
extern Persistent<FunctionTemplate> pipeConstructorTmpl;
|
||||
static Persistent<Function> pipeConstructor;
|
||||
|
||||
static Persistent<String> onconnection_sym;
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Cached<String> onconnection_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
|
||||
|
||||
// TODO share with TCPWrap?
|
||||
@ -62,7 +60,7 @@ uv_pipe_t* PipeWrap::UVHandle() {
|
||||
Local<Object> PipeWrap::Instantiate() {
|
||||
HandleScope scope(node_isolate);
|
||||
assert(!pipeConstructor.IsEmpty());
|
||||
return scope.Close(pipeConstructor->NewInstance());
|
||||
return scope.Close(NewInstance(pipeConstructor));
|
||||
}
|
||||
|
||||
|
||||
@ -114,14 +112,13 @@ void PipeWrap::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "setPendingInstances", SetPendingInstances);
|
||||
#endif
|
||||
|
||||
pipeConstructorTmpl = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
pipeConstructor = Persistent<Function>::New(node_isolate, t->GetFunction());
|
||||
|
||||
target->Set(String::NewSymbol("Pipe"), pipeConstructor);
|
||||
pipeConstructorTmpl.Reset(node_isolate, t);
|
||||
pipeConstructor.Reset(node_isolate, t->GetFunction());
|
||||
target->Set(String::NewSymbol("Pipe"), t->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> PipeWrap::New(const Arguments& args) {
|
||||
void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
|
||||
// This constructor should not be exposed to public javascript.
|
||||
// Therefore we assert that we are not trying to call this as a
|
||||
// normal function.
|
||||
@ -130,8 +127,6 @@ Handle<Value> PipeWrap::New(const Arguments& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
PipeWrap* wrap = new PipeWrap(args.This(), args[0]->IsTrue());
|
||||
assert(wrap);
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
|
||||
@ -144,7 +139,7 @@ PipeWrap::PipeWrap(Handle<Object> object, bool ipc)
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> PipeWrap::Bind(const Arguments& args) {
|
||||
void PipeWrap::Bind(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(PipeWrap)
|
||||
@ -156,12 +151,12 @@ Handle<Value> PipeWrap::Bind(const Arguments& args) {
|
||||
// Error starting the pipe.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
Handle<Value> PipeWrap::SetPendingInstances(const Arguments& args) {
|
||||
void PipeWrap::SetPendingInstances(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(PipeWrap)
|
||||
@ -169,13 +164,11 @@ Handle<Value> PipeWrap::SetPendingInstances(const Arguments& args) {
|
||||
int instances = args[0]->Int32Value();
|
||||
|
||||
uv_pipe_pending_instances(&wrap->handle_, instances);
|
||||
|
||||
return v8::Null(node_isolate);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Handle<Value> PipeWrap::Listen(const Arguments& args) {
|
||||
void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(PipeWrap)
|
||||
@ -189,7 +182,7 @@ Handle<Value> PipeWrap::Listen(const Arguments& args) {
|
||||
// Error starting the pipe.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
@ -202,16 +195,16 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
|
||||
|
||||
// We should not be getting this callback if someone as already called
|
||||
// uv_close() on the handle.
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
if (status != 0) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
MakeCallback(wrap->object_, "onconnection", 0, NULL);
|
||||
MakeCallback(wrap->object(), "onconnection", 0, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
// Instanciate the client javascript object and handle.
|
||||
Local<Object> client_obj = pipeConstructor->NewInstance();
|
||||
Local<Object> client_obj = NewInstance(pipeConstructor);
|
||||
|
||||
// Unwrap the client javascript object.
|
||||
assert(client_obj->InternalFieldCount() > 0);
|
||||
@ -224,9 +217,9 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
|
||||
// Successful accept. Call the onconnection callback in JavaScript land.
|
||||
Local<Value> argv[1] = { client_obj };
|
||||
if (onconnection_sym.IsEmpty()) {
|
||||
onconnection_sym = NODE_PSYMBOL("onconnection");
|
||||
onconnection_sym = String::New("onconnection");
|
||||
}
|
||||
MakeCallback(wrap->object_, onconnection_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
// TODO Maybe share this with TCPWrap?
|
||||
@ -237,8 +230,8 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// The wrap and request objects should still be there.
|
||||
assert(req_wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
bool readable, writable;
|
||||
|
||||
@ -250,24 +243,25 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
|
||||
writable = uv_is_writable(req->handle) != 0;
|
||||
}
|
||||
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> argv[5] = {
|
||||
Integer::New(status, node_isolate),
|
||||
Local<Value>::New(node_isolate, wrap->object_),
|
||||
Local<Value>::New(node_isolate, req_wrap->object_),
|
||||
wrap->object(),
|
||||
req_wrap_obj,
|
||||
Local<Value>::New(node_isolate, Boolean::New(readable)),
|
||||
Local<Value>::New(node_isolate, Boolean::New(writable))
|
||||
};
|
||||
|
||||
if (oncomplete_sym.IsEmpty()) {
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
}
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> PipeWrap::Open(const Arguments& args) {
|
||||
void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(PipeWrap)
|
||||
@ -275,12 +269,10 @@ Handle<Value> PipeWrap::Open(const Arguments& args) {
|
||||
int fd = args[0]->IntegerValue();
|
||||
|
||||
uv_pipe_open(&wrap->handle_, fd);
|
||||
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> PipeWrap::Connect(const Arguments& args) {
|
||||
void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(PipeWrap)
|
||||
@ -296,7 +288,7 @@ Handle<Value> PipeWrap::Connect(const Arguments& args) {
|
||||
|
||||
req_wrap->Dispatched();
|
||||
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
|
||||
|
||||
|
@ -36,14 +36,15 @@ class PipeWrap : public StreamWrap {
|
||||
private:
|
||||
PipeWrap(v8::Handle<v8::Object> object, bool ipc);
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Bind(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Listen(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Connect(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Open(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Listen(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Open(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
#ifdef _WIN32
|
||||
static v8::Handle<v8::Value> SetPendingInstances(const v8::Arguments& args);
|
||||
static void SetPendingInstances(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
#endif
|
||||
|
||||
static void OnConnection(uv_stream_t* handle, int status);
|
||||
|
@ -28,10 +28,9 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Array;
|
||||
using v8::Exception;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -39,12 +38,10 @@ using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::ThrowException;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> onexit_sym;
|
||||
static Cached<String> onexit_sym;
|
||||
|
||||
class ProcessWrap : public HandleWrap {
|
||||
public:
|
||||
@ -69,17 +66,13 @@ class ProcessWrap : public HandleWrap {
|
||||
}
|
||||
|
||||
private:
|
||||
static Handle<Value> New(const Arguments& args) {
|
||||
static void New(const FunctionCallbackInfo<Value>& args) {
|
||||
// This constructor should not be exposed to public javascript.
|
||||
// Therefore we assert that we are not trying to call this as a
|
||||
// normal function.
|
||||
assert(args.IsConstructCall());
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
ProcessWrap *wrap = new ProcessWrap(args.This());
|
||||
assert(wrap);
|
||||
|
||||
return scope.Close(args.This());
|
||||
new ProcessWrap(args.This());
|
||||
}
|
||||
|
||||
ProcessWrap(Handle<Object> object)
|
||||
@ -127,7 +120,7 @@ class ProcessWrap : public HandleWrap {
|
||||
}
|
||||
}
|
||||
|
||||
static Handle<Value> Spawn(const Arguments& args) {
|
||||
static void Spawn(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(ProcessWrap)
|
||||
@ -144,14 +137,12 @@ class ProcessWrap : public HandleWrap {
|
||||
if (uid_v->IsInt32()) {
|
||||
int32_t uid = uid_v->Int32Value();
|
||||
if (uid & ~((uv_uid_t) ~0)) {
|
||||
return ThrowException(Exception::RangeError(
|
||||
String::New("options.uid is out of range")));
|
||||
return ThrowRangeError("options.uid is out of range");
|
||||
}
|
||||
options.flags |= UV_PROCESS_SETUID;
|
||||
options.uid = (uv_uid_t) uid;
|
||||
} else if (!uid_v->IsUndefined() && !uid_v->IsNull()) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("options.uid should be a number")));
|
||||
return ThrowTypeError("options.uid should be a number");
|
||||
}
|
||||
|
||||
// options.gid
|
||||
@ -159,14 +150,12 @@ class ProcessWrap : public HandleWrap {
|
||||
if (gid_v->IsInt32()) {
|
||||
int32_t gid = gid_v->Int32Value();
|
||||
if (gid & ~((uv_gid_t) ~0)) {
|
||||
return ThrowException(Exception::RangeError(
|
||||
String::New("options.gid is out of range")));
|
||||
return ThrowRangeError("options.gid is out of range");
|
||||
}
|
||||
options.flags |= UV_PROCESS_SETGID;
|
||||
options.gid = (uv_gid_t) gid;
|
||||
} else if (!gid_v->IsUndefined() && !gid_v->IsNull()) {
|
||||
return ThrowException(Exception::TypeError(
|
||||
String::New("options.gid should be a number")));
|
||||
return ThrowTypeError("options.gid should be a number");
|
||||
}
|
||||
|
||||
// TODO is this possible to do without mallocing ?
|
||||
@ -177,7 +166,7 @@ class ProcessWrap : public HandleWrap {
|
||||
if (file.length() > 0) {
|
||||
options.file = *file;
|
||||
} else {
|
||||
return ThrowException(Exception::TypeError(String::New("Bad argument")));
|
||||
return ThrowTypeError("Bad argument");
|
||||
}
|
||||
|
||||
// options.args
|
||||
@ -235,8 +224,8 @@ class ProcessWrap : public HandleWrap {
|
||||
}
|
||||
else {
|
||||
assert(wrap->process_.data == wrap);
|
||||
wrap->object_->Set(String::New("pid"),
|
||||
Integer::New(wrap->process_.pid, node_isolate));
|
||||
wrap->object()->Set(String::New("pid"),
|
||||
Integer::New(wrap->process_.pid, node_isolate));
|
||||
}
|
||||
|
||||
if (options.args) {
|
||||
@ -251,21 +240,17 @@ class ProcessWrap : public HandleWrap {
|
||||
|
||||
delete[] options.stdio;
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static Handle<Value> Kill(const Arguments& args) {
|
||||
static void Kill(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(ProcessWrap)
|
||||
|
||||
int signal = args[0]->Int32Value();
|
||||
|
||||
int r = uv_process_kill(&wrap->process_, signal);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static void OnExit(uv_process_t* handle, int exit_status, int term_signal) {
|
||||
@ -285,10 +270,10 @@ class ProcessWrap : public HandleWrap {
|
||||
}
|
||||
|
||||
if (onexit_sym.IsEmpty()) {
|
||||
onexit_sym = NODE_PSYMBOL("onexit");
|
||||
onexit_sym = String::New("onexit");
|
||||
}
|
||||
|
||||
MakeCallback(wrap->object_, onexit_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->object(), onexit_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
uv_process_t process_;
|
||||
|
@ -28,16 +28,17 @@
|
||||
namespace node {
|
||||
|
||||
// defined in node.cc
|
||||
extern v8::Persistent<v8::String> process_symbol;
|
||||
extern v8::Persistent<v8::String> domain_symbol;
|
||||
extern Cached<v8::String> process_symbol;
|
||||
extern Cached<v8::String> domain_symbol;
|
||||
extern QUEUE req_wrap_queue;
|
||||
|
||||
template <typename T>
|
||||
class ReqWrap {
|
||||
public:
|
||||
public:
|
||||
ReqWrap() {
|
||||
v8::HandleScope scope(node_isolate);
|
||||
object_ = v8::Persistent<v8::Object>::New(node_isolate, v8::Object::New());
|
||||
v8::Local<v8::Object> object = v8::Object::New();
|
||||
persistent().Reset(node_isolate, object);
|
||||
|
||||
if (using_domains) {
|
||||
v8::Local<v8::Value> domain = v8::Context::GetCurrent()
|
||||
@ -47,7 +48,7 @@ class ReqWrap {
|
||||
->Get(domain_symbol);
|
||||
|
||||
if (!domain->IsUndefined()) {
|
||||
object_->Set(domain_symbol, domain);
|
||||
object->Set(domain_symbol, domain);
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,9 +60,8 @@ class ReqWrap {
|
||||
QUEUE_REMOVE(&req_wrap_queue_);
|
||||
// Assert that someone has called Dispatched()
|
||||
assert(req_.data == this);
|
||||
assert(!object_.IsEmpty());
|
||||
object_.Dispose(node_isolate);
|
||||
object_.Clear();
|
||||
assert(!persistent().IsEmpty());
|
||||
persistent().Dispose();
|
||||
}
|
||||
|
||||
// Call this after the req has been dispatched.
|
||||
@ -69,6 +69,14 @@ class ReqWrap {
|
||||
req_.data = this;
|
||||
}
|
||||
|
||||
inline v8::Local<v8::Object> object() {
|
||||
return v8::Local<v8::Object>::New(node_isolate, persistent());
|
||||
}
|
||||
|
||||
inline v8::Persistent<v8::Object>& persistent() {
|
||||
return object_;
|
||||
}
|
||||
|
||||
v8::Persistent<v8::Object> object_;
|
||||
QUEUE req_wrap_queue_;
|
||||
void* data_;
|
||||
|
@ -25,19 +25,18 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> onsignal_sym;
|
||||
static Cached<String> onsignal_sym;
|
||||
|
||||
|
||||
class SignalWrap : public HandleWrap {
|
||||
@ -57,13 +56,13 @@ class SignalWrap : public HandleWrap {
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor, "start", Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop);
|
||||
|
||||
onsignal_sym = NODE_PSYMBOL("onsignal");
|
||||
onsignal_sym = String::New("onsignal");
|
||||
|
||||
target->Set(String::NewSymbol("Signal"), constructor->GetFunction());
|
||||
}
|
||||
|
||||
private:
|
||||
static Handle<Value> New(const Arguments& args) {
|
||||
static void New(const FunctionCallbackInfo<Value>& args) {
|
||||
// This constructor should not be exposed to public javascript.
|
||||
// Therefore we assert that we are not trying to call this as a
|
||||
// normal function.
|
||||
@ -71,8 +70,6 @@ class SignalWrap : public HandleWrap {
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
new SignalWrap(args.This());
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
SignalWrap(Handle<Object> object)
|
||||
@ -84,30 +81,23 @@ class SignalWrap : public HandleWrap {
|
||||
~SignalWrap() {
|
||||
}
|
||||
|
||||
static Handle<Value> Start(const Arguments& args) {
|
||||
static void Start(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(SignalWrap)
|
||||
|
||||
int signum = args[0]->Int32Value();
|
||||
|
||||
int r = uv_signal_start(&wrap->handle_, OnSignal, signum);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static Handle<Value> Stop(const Arguments& args) {
|
||||
static void Stop(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(SignalWrap)
|
||||
|
||||
int r = uv_signal_stop(&wrap->handle_);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static void OnSignal(uv_signal_t* handle, int signum) {
|
||||
@ -117,7 +107,7 @@ class SignalWrap : public HandleWrap {
|
||||
assert(wrap);
|
||||
|
||||
Local<Value> argv[1] = { Integer::New(signum, node_isolate) };
|
||||
MakeCallback(wrap->object_, onsignal_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->object(), onsignal_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
uv_signal_t handle_;
|
||||
|
@ -34,8 +34,7 @@
|
||||
namespace node {
|
||||
namespace smalloc {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::HeapProfiler;
|
||||
@ -58,17 +57,16 @@ struct CallbackInfo {
|
||||
typedef v8::WeakReferenceCallbacks<Object, char>::Revivable Callback;
|
||||
typedef v8::WeakReferenceCallbacks<Object, void>::Revivable CallbackFree;
|
||||
|
||||
Callback target_cb;
|
||||
CallbackFree target_free_cb;
|
||||
|
||||
void TargetCallback(Isolate* isolate, Persistent<Object>* target, char* arg);
|
||||
void TargetCallback(Isolate* isolate,
|
||||
Persistent<Object>* target,
|
||||
char* arg);
|
||||
void TargetFreeCallback(Isolate* isolate,
|
||||
Persistent<Object>* target,
|
||||
void* arg);
|
||||
|
||||
|
||||
// for internal use: copyOnto(source, source_start, dest, dest_start, length)
|
||||
Handle<Value> CopyOnto(const Arguments& args) {
|
||||
void CopyOnto(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> source = args[0]->ToObject();
|
||||
@ -95,13 +93,11 @@ Handle<Value> CopyOnto(const Arguments& args) {
|
||||
assert(dest_start + length <= dest_length);
|
||||
|
||||
memmove(dest_data + dest_start, source_data + source_start, length);
|
||||
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
// for internal use: dest._data = sliceOnto(source, dest, start, end);
|
||||
Handle<Value> SliceOnto(const Arguments& args) {
|
||||
void SliceOnto(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> source = args[0]->ToObject();
|
||||
@ -120,21 +116,19 @@ Handle<Value> SliceOnto(const Arguments& args) {
|
||||
dest->SetIndexedPropertiesToExternalArrayData(source_data + start,
|
||||
kExternalUnsignedByteArray,
|
||||
end - start);
|
||||
|
||||
return scope.Close(source);
|
||||
args.GetReturnValue().Set(source);
|
||||
}
|
||||
|
||||
|
||||
// for internal use: alloc(obj, n);
|
||||
Handle<Value> Alloc(const Arguments& args) {
|
||||
void Alloc(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
Local<Object> obj = args[0]->ToObject();
|
||||
size_t length = args[1]->Uint32Value();
|
||||
|
||||
Alloc(obj, length);
|
||||
|
||||
return scope.Close(obj);
|
||||
args.GetReturnValue().Set(obj);
|
||||
}
|
||||
|
||||
|
||||
@ -153,31 +147,32 @@ void Alloc(Handle<Object> obj, size_t length) {
|
||||
|
||||
void Alloc(Handle<Object> obj, char* data, size_t length) {
|
||||
Persistent<Object> p_obj(node_isolate, obj);
|
||||
|
||||
node_isolate->AdjustAmountOfExternalAllocatedMemory(length);
|
||||
p_obj.MakeWeak(node_isolate, data, target_cb);
|
||||
p_obj.MarkIndependent(node_isolate);
|
||||
p_obj.SetWrapperClassId(node_isolate, ALLOC_ID);
|
||||
p_obj->SetIndexedPropertiesToExternalArrayData(data,
|
||||
kExternalUnsignedByteArray,
|
||||
length);
|
||||
p_obj.MakeWeak(data, TargetCallback);
|
||||
p_obj.MarkIndependent();
|
||||
p_obj.SetWrapperClassId(ALLOC_ID);
|
||||
obj->SetIndexedPropertiesToExternalArrayData(data,
|
||||
kExternalUnsignedByteArray,
|
||||
length);
|
||||
}
|
||||
|
||||
|
||||
void TargetCallback(Isolate* isolate, Persistent<Object>* target, char* data) {
|
||||
int len = (*target)->GetIndexedPropertiesExternalArrayDataLength();
|
||||
void TargetCallback(Isolate* isolate,
|
||||
Persistent<Object>* target,
|
||||
char* data) {
|
||||
HandleScope handle_scope(node_isolate);
|
||||
Local<Object> obj = Local<Object>::New(isolate, *target);
|
||||
int len = obj->GetIndexedPropertiesExternalArrayDataLength();
|
||||
if (data != NULL && len > 0) {
|
||||
isolate->AdjustAmountOfExternalAllocatedMemory(-len);
|
||||
free(data);
|
||||
}
|
||||
(*target).Dispose();
|
||||
(*target).Clear();
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> AllocDispose(const Arguments& args) {
|
||||
void AllocDispose(const FunctionCallbackInfo<Value>& args) {
|
||||
AllocDispose(args[0]->ToObject());
|
||||
return Undefined(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -218,12 +213,12 @@ void Alloc(Handle<Object> obj,
|
||||
|
||||
node_isolate->AdjustAmountOfExternalAllocatedMemory(length +
|
||||
sizeof(*cb_info));
|
||||
p_obj.MakeWeak(node_isolate, static_cast<void*>(cb_info), target_free_cb);
|
||||
p_obj.MarkIndependent(node_isolate);
|
||||
p_obj.SetWrapperClassId(node_isolate, ALLOC_ID);
|
||||
p_obj->SetIndexedPropertiesToExternalArrayData(data,
|
||||
kExternalUnsignedByteArray,
|
||||
length);
|
||||
p_obj.MakeWeak(static_cast<void*>(cb_info), TargetFreeCallback);
|
||||
p_obj.MarkIndependent();
|
||||
p_obj.SetWrapperClassId(ALLOC_ID);
|
||||
obj->SetIndexedPropertiesToExternalArrayData(data,
|
||||
kExternalUnsignedByteArray,
|
||||
length);
|
||||
}
|
||||
|
||||
|
||||
@ -232,13 +227,13 @@ void Alloc(Handle<Object> obj,
|
||||
void TargetFreeCallback(Isolate* isolate,
|
||||
Persistent<Object>* target,
|
||||
void* arg) {
|
||||
Local<Object> obj = **target;
|
||||
HandleScope handle_scope(node_isolate);
|
||||
Local<Object> obj = Local<Object>::New(isolate, *target);
|
||||
int len = obj->GetIndexedPropertiesExternalArrayDataLength();
|
||||
char* data = static_cast<char*>(obj->GetIndexedPropertiesExternalArrayData());
|
||||
CallbackInfo* cb_info = static_cast<CallbackInfo*>(arg);
|
||||
isolate->AdjustAmountOfExternalAllocatedMemory(-(len + sizeof(*cb_info)));
|
||||
(*target).Dispose();
|
||||
(*target).Clear();
|
||||
cb_info->cb(data, cb_info->hint);
|
||||
delete cb_info;
|
||||
}
|
||||
@ -312,9 +307,6 @@ void Initialize(Handle<Object> exports) {
|
||||
exports->Set(String::New("kMaxLength"),
|
||||
Uint32::New(kMaxLength, node_isolate));
|
||||
|
||||
target_cb = TargetCallback;
|
||||
target_free_cb = TargetFreeCallback;
|
||||
|
||||
HeapProfiler* heap_profiler = node_isolate->GetHeapProfiler();
|
||||
heap_profiler->SetWrapperClassInfoProvider(ALLOC_ID, WrapperInfo);
|
||||
}
|
||||
|
@ -35,27 +35,25 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::AccessorInfo;
|
||||
using v8::Arguments;
|
||||
using v8::Array;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Number;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::PropertyCallbackInfo;
|
||||
using v8::String;
|
||||
using v8::Uint32;
|
||||
using v8::Value;
|
||||
|
||||
|
||||
static Persistent<String> buffer_sym;
|
||||
static Persistent<String> bytes_sym;
|
||||
static Persistent<String> write_queue_size_sym;
|
||||
static Persistent<String> onread_sym;
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Persistent<String> handle_sym;
|
||||
static Cached<String> buffer_sym;
|
||||
static Cached<String> bytes_sym;
|
||||
static Cached<String> write_queue_size_sym;
|
||||
static Cached<String> onread_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
static Cached<String> handle_sym;
|
||||
static bool initialized;
|
||||
|
||||
|
||||
@ -67,11 +65,11 @@ void StreamWrap::Initialize(Handle<Object> target) {
|
||||
|
||||
HandleWrap::Initialize(target);
|
||||
|
||||
buffer_sym = NODE_PSYMBOL("buffer");
|
||||
bytes_sym = NODE_PSYMBOL("bytes");
|
||||
write_queue_size_sym = NODE_PSYMBOL("writeQueueSize");
|
||||
onread_sym = NODE_PSYMBOL("onread");
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
buffer_sym = String::New("buffer");
|
||||
bytes_sym = String::New("bytes");
|
||||
write_queue_size_sym = String::New("writeQueueSize");
|
||||
onread_sym = String::New("onread");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
}
|
||||
|
||||
|
||||
@ -83,27 +81,25 @@ StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream)
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::GetFD(Local<String>, const AccessorInfo& args) {
|
||||
#if defined(_WIN32)
|
||||
return v8::Null(node_isolate);
|
||||
#else
|
||||
void StreamWrap::GetFD(Local<String>, const PropertyCallbackInfo<Value>& args) {
|
||||
#if !defined(_WIN32)
|
||||
HandleScope scope(node_isolate);
|
||||
UNWRAP_NO_ABORT(StreamWrap)
|
||||
int fd = -1;
|
||||
if (wrap != NULL && wrap->stream_ != NULL) fd = wrap->stream_->io_watcher.fd;
|
||||
return scope.Close(Integer::New(fd, node_isolate));
|
||||
args.GetReturnValue().Set(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void StreamWrap::UpdateWriteQueueSize() {
|
||||
HandleScope scope(node_isolate);
|
||||
object_->Set(write_queue_size_sym,
|
||||
Integer::New(stream_->write_queue_size, node_isolate));
|
||||
object()->Set(write_queue_size_sym,
|
||||
Integer::New(stream_->write_queue_size, node_isolate));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
|
||||
void StreamWrap::ReadStart(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(StreamWrap)
|
||||
@ -120,11 +116,11 @@ Handle<Value> StreamWrap::ReadStart(const Arguments& args) {
|
||||
// Error starting the tcp.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
|
||||
void StreamWrap::ReadStop(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(StreamWrap)
|
||||
@ -134,7 +130,7 @@ Handle<Value> StreamWrap::ReadStop(const Arguments& args) {
|
||||
// Error starting the tcp.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
@ -178,7 +174,7 @@ void StreamWrap::OnReadCommon(uv_stream_t* handle,
|
||||
|
||||
// We should not be getting this callback if someone as already called
|
||||
// uv_close() on the handle.
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
if (nread > 0) {
|
||||
if (wrap->stream_->type == UV_TCP) {
|
||||
@ -214,7 +210,7 @@ size_t StreamWrap::WriteBuffer(Handle<Value> val, uv_buf_t* buf) {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
|
||||
void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(StreamWrap)
|
||||
@ -225,7 +221,8 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
|
||||
char* storage = new char[sizeof(WriteWrap)];
|
||||
WriteWrap* req_wrap = new (storage) WriteWrap(wrap);
|
||||
|
||||
req_wrap->object_->SetHiddenValue(buffer_sym, args[0]);
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
req_wrap_obj->SetHiddenValue(buffer_sym, args[0]);
|
||||
|
||||
uv_buf_t buf;
|
||||
WriteBuffer(args[0], &buf);
|
||||
@ -237,22 +234,20 @@ Handle<Value> StreamWrap::WriteBuffer(const Arguments& args) {
|
||||
StreamWrap::AfterWrite);
|
||||
|
||||
req_wrap->Dispatched();
|
||||
req_wrap->object_->Set(bytes_sym,
|
||||
Integer::NewFromUnsigned(length, node_isolate));
|
||||
req_wrap_obj->Set(bytes_sym, Integer::NewFromUnsigned(length, node_isolate));
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
req_wrap->~WriteWrap();
|
||||
delete[] storage;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <enum encoding encoding>
|
||||
Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
|
||||
void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
int r;
|
||||
|
||||
@ -276,7 +271,7 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
|
||||
uv_err_t err;
|
||||
err.code = UV_ENOBUFS;
|
||||
SetErrno(err);
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
return;
|
||||
}
|
||||
|
||||
char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
|
||||
@ -317,10 +312,10 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
|
||||
// Reference StreamWrap instance to prevent it from being garbage
|
||||
// collected before `AfterWrite` is called.
|
||||
if (handle_sym.IsEmpty()) {
|
||||
handle_sym = NODE_PSYMBOL("handle");
|
||||
handle_sym = String::New("handle");
|
||||
}
|
||||
assert(!req_wrap->object_.IsEmpty());
|
||||
req_wrap->object_->Set(handle_sym, send_handle_obj);
|
||||
assert(!req_wrap->persistent().IsEmpty());
|
||||
req_wrap->object()->Set(handle_sym, send_handle_obj);
|
||||
}
|
||||
|
||||
r = wrap->callbacks_->DoWrite(req_wrap,
|
||||
@ -331,20 +326,19 @@ Handle<Value> StreamWrap::WriteStringImpl(const Arguments& args) {
|
||||
}
|
||||
|
||||
req_wrap->Dispatched();
|
||||
req_wrap->object_->Set(bytes_sym, Number::New((uint32_t) data_size));
|
||||
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, data_size));
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
req_wrap->~WriteWrap();
|
||||
delete[] storage;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::Writev(const Arguments& args) {
|
||||
void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope;
|
||||
|
||||
UNWRAP(StreamWrap)
|
||||
@ -386,7 +380,7 @@ Handle<Value> StreamWrap::Writev(const Arguments& args) {
|
||||
uv_err_t err;
|
||||
err.code = UV_ENOBUFS;
|
||||
SetErrno(err);
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ARRAY_SIZE(bufs_) < count)
|
||||
@ -435,31 +429,30 @@ Handle<Value> StreamWrap::Writev(const Arguments& args) {
|
||||
delete[] bufs;
|
||||
|
||||
req_wrap->Dispatched();
|
||||
req_wrap->object_->Set(bytes_sym, Number::New(bytes));
|
||||
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, bytes));
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
req_wrap->~WriteWrap();
|
||||
delete[] storage;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::WriteAsciiString(const Arguments& args) {
|
||||
return WriteStringImpl<ASCII>(args);
|
||||
void StreamWrap::WriteAsciiString(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteStringImpl<ASCII>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::WriteUtf8String(const Arguments& args) {
|
||||
return WriteStringImpl<UTF8>(args);
|
||||
void StreamWrap::WriteUtf8String(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteStringImpl<UTF8>(args);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::WriteUcs2String(const Arguments& args) {
|
||||
return WriteStringImpl<UCS2>(args);
|
||||
void StreamWrap::WriteUcs2String(const FunctionCallbackInfo<Value>& args) {
|
||||
WriteStringImpl<UCS2>(args);
|
||||
}
|
||||
|
||||
|
||||
@ -470,12 +463,13 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// The wrap and request objects should still be there.
|
||||
assert(req_wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
// Unref handle property
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
if (!handle_sym.IsEmpty()) {
|
||||
req_wrap->object_->Delete(handle_sym);
|
||||
req_wrap_obj->Delete(handle_sym);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
@ -486,18 +480,18 @@ void StreamWrap::AfterWrite(uv_write_t* req, int status) {
|
||||
|
||||
Local<Value> argv[] = {
|
||||
Integer::New(status, node_isolate),
|
||||
Local<Value>::New(node_isolate, wrap->object_),
|
||||
Local<Value>::New(node_isolate, req_wrap->object_)
|
||||
wrap->object(),
|
||||
req_wrap_obj
|
||||
};
|
||||
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
req_wrap->~WriteWrap();
|
||||
delete[] reinterpret_cast<char*>(req_wrap);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
|
||||
void StreamWrap::Shutdown(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(StreamWrap)
|
||||
@ -511,9 +505,8 @@ Handle<Value> StreamWrap::Shutdown(const Arguments& args) {
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
@ -523,8 +516,8 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
|
||||
StreamWrap* wrap = (StreamWrap*) req->handle->data;
|
||||
|
||||
// The wrap and request objects should still be there.
|
||||
assert(req_wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
@ -532,13 +525,14 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> argv[3] = {
|
||||
Integer::New(status, node_isolate),
|
||||
Local<Value>::New(node_isolate, wrap->object_),
|
||||
Local<Value>::New(node_isolate, req_wrap->object_)
|
||||
wrap->object(),
|
||||
req_wrap_obj
|
||||
};
|
||||
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
delete req_wrap;
|
||||
}
|
||||
@ -634,7 +628,7 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
|
||||
argc++;
|
||||
}
|
||||
|
||||
MakeCallback(wrap_->object_, onread_sym, argc, argv);
|
||||
MakeCallback(wrap_->object(), onread_sym, argc, argv);
|
||||
}
|
||||
|
||||
|
||||
@ -644,7 +638,7 @@ int StreamWrapCallbacks::DoShutdown(ShutdownWrap* req_wrap, uv_shutdown_cb cb) {
|
||||
|
||||
|
||||
Handle<Object> StreamWrapCallbacks::Self() {
|
||||
return wrap_->object_;
|
||||
return wrap_->object();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -104,19 +104,19 @@ class StreamWrap : public HandleWrap {
|
||||
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
|
||||
static v8::Handle<v8::Value> GetFD(v8::Local<v8::String>,
|
||||
const v8::AccessorInfo&);
|
||||
static void GetFD(v8::Local<v8::String>,
|
||||
const v8::PropertyCallbackInfo<v8::Value>&);
|
||||
|
||||
// JavaScript functions
|
||||
static v8::Handle<v8::Value> ReadStart(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> ReadStop(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Shutdown(const v8::Arguments& args);
|
||||
static void ReadStart(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ReadStop(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Shutdown(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
static v8::Handle<v8::Value> Writev(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> WriteBuffer(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> WriteAsciiString(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> WriteUtf8String(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> WriteUcs2String(const v8::Arguments& args);
|
||||
static void Writev(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void WriteBuffer(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void WriteAsciiString(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void WriteUtf8String(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void WriteUcs2String(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
// Overridable callbacks
|
||||
StreamWrapCallbacks* callbacks_;
|
||||
@ -147,7 +147,7 @@ class StreamWrap : public HandleWrap {
|
||||
uv_buf_t buf, uv_handle_type pending);
|
||||
|
||||
template <enum encoding encoding>
|
||||
static v8::Handle<v8::Value> WriteStringImpl(const v8::Arguments& args);
|
||||
static void WriteStringImpl(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
uv_stream_t* stream_;
|
||||
|
||||
|
130
src/tcp_wrap.cc
130
src/tcp_wrap.cc
@ -32,8 +32,8 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -44,12 +44,11 @@ using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::PropertyAttribute;
|
||||
using v8::String;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<Function> tcpConstructor;
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Persistent<String> onconnection_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
static Cached<String> onconnection_sym;
|
||||
|
||||
|
||||
typedef class ReqWrap<uv_connect_t> ConnectWrap;
|
||||
@ -63,7 +62,7 @@ Local<Object> TCPWrap::Instantiate() {
|
||||
assert(tcpConstructor.IsEmpty() == false);
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Object> obj = tcpConstructor->NewInstance();
|
||||
Local<Object> obj = NewInstance(tcpConstructor);
|
||||
|
||||
return scope.Close(obj);
|
||||
}
|
||||
@ -119,13 +118,12 @@ void TCPWrap::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "setSimultaneousAccepts", SetSimultaneousAccepts);
|
||||
#endif
|
||||
|
||||
tcpConstructorTmpl = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
tcpConstructor = Persistent<Function>::New(node_isolate, t->GetFunction());
|
||||
onconnection_sym = String::New("onconnection");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
|
||||
onconnection_sym = NODE_PSYMBOL("onconnection");
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
|
||||
target->Set(String::NewSymbol("TCP"), tcpConstructor);
|
||||
tcpConstructorTmpl.Reset(node_isolate, t);
|
||||
tcpConstructor.Reset(node_isolate, t->GetFunction());
|
||||
target->Set(String::NewSymbol("TCP"), t->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
@ -141,17 +139,14 @@ uv_tcp_t* TCPWrap::UVHandle() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::New(const Arguments& args) {
|
||||
void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
|
||||
// This constructor should not be exposed to public javascript.
|
||||
// Therefore we assert that we are not trying to call this as a
|
||||
// normal function.
|
||||
assert(args.IsConstructCall());
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
TCPWrap* wrap = new TCPWrap(args.This());
|
||||
assert(wrap);
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
|
||||
@ -165,11 +160,11 @@ TCPWrap::TCPWrap(Handle<Object> object)
|
||||
|
||||
|
||||
TCPWrap::~TCPWrap() {
|
||||
assert(object_.IsEmpty());
|
||||
assert(persistent().IsEmpty());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::GetSockName(const Arguments& args) {
|
||||
void TCPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
struct sockaddr_storage address;
|
||||
|
||||
@ -179,18 +174,14 @@ Handle<Value> TCPWrap::GetSockName(const Arguments& args) {
|
||||
int r = uv_tcp_getsockname(&wrap->handle_,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&addrlen);
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
return Null(node_isolate);
|
||||
}
|
||||
if (r) return SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
|
||||
return scope.Close(AddressToJS(addr));
|
||||
args.GetReturnValue().Set(AddressToJS(addr));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::GetPeerName(const Arguments& args) {
|
||||
void TCPWrap::GetPeerName(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
struct sockaddr_storage address;
|
||||
|
||||
@ -200,32 +191,25 @@ Handle<Value> TCPWrap::GetPeerName(const Arguments& args) {
|
||||
int r = uv_tcp_getpeername(&wrap->handle_,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&addrlen);
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
return Null(node_isolate);
|
||||
}
|
||||
if (r) return SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
|
||||
return scope.Close(AddressToJS(addr));
|
||||
args.GetReturnValue().Set(AddressToJS(addr));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::SetNoDelay(const Arguments& args) {
|
||||
void TCPWrap::SetNoDelay(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
|
||||
int enable = static_cast<int>(args[0]->BooleanValue());
|
||||
int r = uv_tcp_nodelay(&wrap->handle_, enable);
|
||||
if (r)
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return Undefined(node_isolate);
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::SetKeepAlive(const Arguments& args) {
|
||||
void TCPWrap::SetKeepAlive(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -234,40 +218,32 @@ Handle<Value> TCPWrap::SetKeepAlive(const Arguments& args) {
|
||||
unsigned int delay = args[1]->Uint32Value();
|
||||
|
||||
int r = uv_tcp_keepalive(&wrap->handle_, enable, delay);
|
||||
if (r)
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return Undefined(node_isolate);
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
Handle<Value> TCPWrap::SetSimultaneousAccepts(const Arguments& args) {
|
||||
void TCPWrap::SetSimultaneousAccepts(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
|
||||
bool enable = args[0]->BooleanValue();
|
||||
|
||||
int r = uv_tcp_simultaneous_accepts(&wrap->handle_, enable ? 1 : 0);
|
||||
if (r)
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return Undefined(node_isolate);
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Open(const Arguments& args) {
|
||||
void TCPWrap::Open(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
UNWRAP(TCPWrap)
|
||||
int fd = args[0]->IntegerValue();
|
||||
uv_tcp_open(&wrap->handle_, fd);
|
||||
return Null(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Bind(const Arguments& args) {
|
||||
void TCPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -281,11 +257,11 @@ Handle<Value> TCPWrap::Bind(const Arguments& args) {
|
||||
// Error starting the tcp.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Bind6(const Arguments& args) {
|
||||
void TCPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -299,11 +275,11 @@ Handle<Value> TCPWrap::Bind6(const Arguments& args) {
|
||||
// Error starting the tcp.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Listen(const Arguments& args) {
|
||||
void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -317,7 +293,7 @@ Handle<Value> TCPWrap::Listen(const Arguments& args) {
|
||||
// Error starting the tcp.
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
@ -329,7 +305,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
|
||||
|
||||
// We should not be getting this callback if someone as already called
|
||||
// uv_close() on the handle.
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
Local<Value> argv[1];
|
||||
|
||||
@ -353,7 +329,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
|
||||
argv[0] = Local<Value>::New(node_isolate, Null(node_isolate));
|
||||
}
|
||||
|
||||
MakeCallback(wrap->object_, onconnection_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
|
||||
@ -364,28 +340,28 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// The wrap and request objects should still be there.
|
||||
assert(req_wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
if (status) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> argv[5] = {
|
||||
Integer::New(status, node_isolate),
|
||||
Local<Value>::New(node_isolate, wrap->object_),
|
||||
Local<Value>::New(node_isolate, req_wrap->object_),
|
||||
wrap->object(),
|
||||
req_wrap_obj,
|
||||
Local<Value>::New(node_isolate, v8::True(node_isolate)),
|
||||
Local<Value>::New(node_isolate, v8::True(node_isolate))
|
||||
};
|
||||
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Connect(const Arguments& args) {
|
||||
void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -408,14 +384,13 @@ Handle<Value> TCPWrap::Connect(const Arguments& args) {
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TCPWrap::Connect6(const Arguments& args) {
|
||||
void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TCPWrap)
|
||||
@ -435,20 +410,19 @@ Handle<Value> TCPWrap::Connect6(const Arguments& args) {
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return scope.Close(v8::Null(node_isolate));
|
||||
} else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// also used by udp_wrap.cc
|
||||
Local<Object> AddressToJS(const sockaddr* addr) {
|
||||
static Persistent<String> address_sym;
|
||||
static Persistent<String> family_sym;
|
||||
static Persistent<String> port_sym;
|
||||
static Persistent<String> ipv4_sym;
|
||||
static Persistent<String> ipv6_sym;
|
||||
static Cached<String> address_sym;
|
||||
static Cached<String> family_sym;
|
||||
static Cached<String> port_sym;
|
||||
static Cached<String> ipv4_sym;
|
||||
static Cached<String> ipv6_sym;
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
char ip[INET6_ADDRSTRLEN];
|
||||
@ -457,11 +431,11 @@ Local<Object> AddressToJS(const sockaddr* addr) {
|
||||
int port;
|
||||
|
||||
if (address_sym.IsEmpty()) {
|
||||
address_sym = NODE_PSYMBOL("address");
|
||||
family_sym = NODE_PSYMBOL("family");
|
||||
port_sym = NODE_PSYMBOL("port");
|
||||
ipv4_sym = NODE_PSYMBOL("IPv4");
|
||||
ipv6_sym = NODE_PSYMBOL("IPv6");
|
||||
address_sym = String::New("address");
|
||||
family_sym = String::New("family");
|
||||
port_sym = String::New("port");
|
||||
ipv4_sym = String::New("IPv4");
|
||||
ipv6_sym = String::New("IPv6");
|
||||
}
|
||||
|
||||
Local<Object> info = Object::New();
|
||||
|
@ -37,20 +37,21 @@ class TCPWrap : public StreamWrap {
|
||||
TCPWrap(v8::Handle<v8::Object> object);
|
||||
~TCPWrap();
|
||||
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetSockName(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPeerName(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetNoDelay(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetKeepAlive(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Bind(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Bind6(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Listen(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Connect(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Connect6(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Open(const v8::Arguments& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetSockName(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPeerName(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetNoDelay(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetKeepAlive(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Bind6(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Listen(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Connect(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Connect6(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Open(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
#ifdef _WIN32
|
||||
static v8::Handle<v8::Value> SetSimultaneousAccepts(const v8::Arguments& args);
|
||||
static void SetSimultaneousAccepts(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
#endif
|
||||
|
||||
static void OnConnection(uv_stream_t* handle, int status);
|
||||
|
@ -24,19 +24,18 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> ontimeout_sym;
|
||||
static Cached<String> ontimeout_sym;
|
||||
|
||||
class TimerWrap : public HandleWrap {
|
||||
public:
|
||||
@ -61,23 +60,19 @@ class TimerWrap : public HandleWrap {
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor, "getRepeat", GetRepeat);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor, "again", Again);
|
||||
|
||||
ontimeout_sym = NODE_PSYMBOL("ontimeout");
|
||||
ontimeout_sym = String::New("ontimeout");
|
||||
|
||||
target->Set(String::NewSymbol("Timer"), constructor->GetFunction());
|
||||
}
|
||||
|
||||
private:
|
||||
static Handle<Value> New(const Arguments& args) {
|
||||
static void New(const FunctionCallbackInfo<Value>& args) {
|
||||
// This constructor should not be exposed to public javascript.
|
||||
// Therefore we assert that we are not trying to call this as a
|
||||
// normal function.
|
||||
assert(args.IsConstructCall());
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
TimerWrap *wrap = new TimerWrap(args.This());
|
||||
assert(wrap);
|
||||
|
||||
return scope.Close(args.This());
|
||||
new TimerWrap(args.This());
|
||||
}
|
||||
|
||||
TimerWrap(Handle<Object> object)
|
||||
@ -89,67 +84,51 @@ class TimerWrap : public HandleWrap {
|
||||
~TimerWrap() {
|
||||
}
|
||||
|
||||
static Handle<Value> Start(const Arguments& args) {
|
||||
static void Start(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TimerWrap)
|
||||
|
||||
int64_t timeout = args[0]->IntegerValue();
|
||||
int64_t repeat = args[1]->IntegerValue();
|
||||
|
||||
int r = uv_timer_start(&wrap->handle_, OnTimeout, timeout, repeat);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static Handle<Value> Stop(const Arguments& args) {
|
||||
static void Stop(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TimerWrap)
|
||||
|
||||
int r = uv_timer_stop(&wrap->handle_);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static Handle<Value> Again(const Arguments& args) {
|
||||
static void Again(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TimerWrap)
|
||||
|
||||
int r = uv_timer_again(&wrap->handle_);
|
||||
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
static Handle<Value> SetRepeat(const Arguments& args) {
|
||||
static void SetRepeat(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TimerWrap)
|
||||
|
||||
int64_t repeat = args[0]->IntegerValue();
|
||||
|
||||
uv_timer_set_repeat(&wrap->handle_, repeat);
|
||||
|
||||
return scope.Close(Integer::New(0, node_isolate));
|
||||
args.GetReturnValue().Set(0);
|
||||
}
|
||||
|
||||
static Handle<Value> GetRepeat(const Arguments& args) {
|
||||
static void GetRepeat(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TimerWrap)
|
||||
|
||||
int64_t repeat = uv_timer_get_repeat(&wrap->handle_);
|
||||
|
||||
if (repeat < 0) SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(repeat, node_isolate));
|
||||
args.GetReturnValue().Set(static_cast<double>(repeat));
|
||||
}
|
||||
|
||||
static void OnTimeout(uv_timer_t* handle, int status) {
|
||||
@ -159,14 +138,13 @@ class TimerWrap : public HandleWrap {
|
||||
assert(wrap);
|
||||
|
||||
Local<Value> argv[1] = { Integer::New(status, node_isolate) };
|
||||
MakeCallback(wrap->object_, ontimeout_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap->object(), ontimeout_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
static Handle<Value> Now(const Arguments& args) {
|
||||
static void Now(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
double now = static_cast<double>(uv_now(uv_default_loop()));
|
||||
return scope.Close(v8::Number::New(now));
|
||||
args.GetReturnValue().Set(now);
|
||||
}
|
||||
|
||||
uv_timer_t handle_;
|
||||
|
347
src/tls_wrap.cc
347
src/tls_wrap.cc
@ -28,28 +28,39 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using namespace v8;
|
||||
using crypto::SecureContext;
|
||||
using v8::Array;
|
||||
using v8::Exception;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Null;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::String;
|
||||
using v8::Value;
|
||||
|
||||
static Persistent<String> onread_sym;
|
||||
static Persistent<String> onerror_sym;
|
||||
static Persistent<String> onsniselect_sym;
|
||||
static Persistent<String> onhandshakestart_sym;
|
||||
static Persistent<String> onhandshakedone_sym;
|
||||
static Persistent<String> onclienthello_sym;
|
||||
static Persistent<String> onnewsession_sym;
|
||||
static Persistent<String> subject_sym;
|
||||
static Persistent<String> subjectaltname_sym;
|
||||
static Persistent<String> modulus_sym;
|
||||
static Persistent<String> exponent_sym;
|
||||
static Persistent<String> issuer_sym;
|
||||
static Persistent<String> valid_from_sym;
|
||||
static Persistent<String> valid_to_sym;
|
||||
static Persistent<String> fingerprint_sym;
|
||||
static Persistent<String> name_sym;
|
||||
static Persistent<String> version_sym;
|
||||
static Persistent<String> ext_key_usage_sym;
|
||||
static Persistent<String> sessionid_sym;
|
||||
static Cached<String> onread_sym;
|
||||
static Cached<String> onerror_sym;
|
||||
static Cached<String> onsniselect_sym;
|
||||
static Cached<String> onhandshakestart_sym;
|
||||
static Cached<String> onhandshakedone_sym;
|
||||
static Cached<String> onclienthello_sym;
|
||||
static Cached<String> onnewsession_sym;
|
||||
static Cached<String> subject_sym;
|
||||
static Cached<String> subjectaltname_sym;
|
||||
static Cached<String> modulus_sym;
|
||||
static Cached<String> exponent_sym;
|
||||
static Cached<String> issuer_sym;
|
||||
static Cached<String> valid_from_sym;
|
||||
static Cached<String> valid_to_sym;
|
||||
static Cached<String> fingerprint_sym;
|
||||
static Cached<String> name_sym;
|
||||
static Cached<String> version_sym;
|
||||
static Cached<String> ext_key_usage_sym;
|
||||
static Cached<String> sessionid_sym;
|
||||
|
||||
static Persistent<Function> tlsWrap;
|
||||
|
||||
@ -78,10 +89,11 @@ TLSCallbacks::TLSCallbacks(Kind kind,
|
||||
|
||||
// Persist SecureContext
|
||||
sc_ = ObjectWrap::Unwrap<SecureContext>(sc);
|
||||
sc_handle_ = Persistent<Object>::New(node_isolate, sc);
|
||||
sc_handle_.Reset(node_isolate, sc);
|
||||
|
||||
handle_ = Persistent<Object>::New(node_isolate, tlsWrap->NewInstance());
|
||||
handle_->SetAlignedPointerInInternalField(0, this);
|
||||
Local<Object> object = NewInstance(tlsWrap);
|
||||
object->SetAlignedPointerInInternalField(0, this);
|
||||
persistent().Reset(node_isolate, object);
|
||||
|
||||
// Initialize queue for clearIn writes
|
||||
QUEUE_INIT(&write_item_queue_);
|
||||
@ -137,8 +149,7 @@ int TLSCallbacks::NewSessionCallback(SSL* s, SSL_SESSION* sess) {
|
||||
Local<Object> session = Buffer::New(reinterpret_cast<char*>(sess->session_id),
|
||||
sess->session_id_length);
|
||||
Handle<Value> argv[2] = { session, buff };
|
||||
|
||||
MakeCallback(c->handle_, onnewsession_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(c->object(), onnewsession_sym, ARRAY_SIZE(argv), argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -153,24 +164,17 @@ TLSCallbacks::~TLSCallbacks() {
|
||||
clear_in_ = NULL;
|
||||
|
||||
sc_ = NULL;
|
||||
sc_handle_.Dispose(node_isolate);
|
||||
sc_handle_.Clear();
|
||||
|
||||
handle_.Dispose(node_isolate);
|
||||
handle_.Clear();
|
||||
sc_handle_.Dispose();
|
||||
persistent().Dispose();
|
||||
|
||||
#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
npn_protos_.Dispose(node_isolate);
|
||||
npn_protos_.Clear();
|
||||
selected_npn_proto_.Dispose(node_isolate);
|
||||
selected_npn_proto_.Clear();
|
||||
npn_protos_.Dispose();
|
||||
selected_npn_proto_.Dispose();
|
||||
#endif // OPENSSL_NPN_NEGOTIATED
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
servername_.Dispose(node_isolate);
|
||||
servername_.Clear();
|
||||
sni_context_.Dispose(node_isolate);
|
||||
sni_context_.Clear();
|
||||
servername_.Dispose();
|
||||
sni_context_.Dispose();
|
||||
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
}
|
||||
|
||||
@ -295,7 +299,7 @@ void TLSCallbacks::InitSSL() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::Wrap(const Arguments& args) {
|
||||
void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
if (args.Length() < 1 || !args[0]->IsObject())
|
||||
@ -315,14 +319,15 @@ Handle<Value> TLSCallbacks::Wrap(const Arguments& args) {
|
||||
wrap->OverrideCallbacks(callbacks);
|
||||
});
|
||||
|
||||
if (callbacks == NULL)
|
||||
return Null(node_isolate);
|
||||
if (callbacks == NULL) {
|
||||
return args.GetReturnValue().SetNull();
|
||||
}
|
||||
|
||||
return scope.Close(callbacks->handle_);
|
||||
args.GetReturnValue().Set(callbacks->persistent());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::Start(const Arguments& args) {
|
||||
void TLSCallbacks::Start(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -335,8 +340,6 @@ Handle<Value> TLSCallbacks::Start(const Arguments& args) {
|
||||
assert(wrap->kind_ == kTLSClient);
|
||||
wrap->ClearOut();
|
||||
wrap->EncOut();
|
||||
|
||||
return Null(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -347,15 +350,17 @@ void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
|
||||
if (where & SSL_CB_HANDSHAKE_START) {
|
||||
HandleScope scope(node_isolate);
|
||||
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
|
||||
if (c->handle_->Has(onhandshakestart_sym))
|
||||
MakeCallback(c->handle_, onhandshakestart_sym, 0, NULL);
|
||||
Local<Object> object = c->object();
|
||||
if (object->Has(onhandshakestart_sym))
|
||||
MakeCallback(object, onhandshakestart_sym, 0, NULL);
|
||||
}
|
||||
if (where & SSL_CB_HANDSHAKE_DONE) {
|
||||
HandleScope scope(node_isolate);
|
||||
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
|
||||
c->established_ = true;
|
||||
if (c->handle_->Has(onhandshakedone_sym))
|
||||
MakeCallback(c->handle_, onhandshakedone_sym, 0, NULL);
|
||||
Local<Object> object = c->object();
|
||||
if (object->Has(onhandshakedone_sym))
|
||||
MakeCallback(object, onhandshakedone_sym, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -417,7 +422,7 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
|
||||
Local<Value> arg = String::Concat(
|
||||
String::New("write cb error, status: "),
|
||||
Integer::New(status, node_isolate)->ToString());
|
||||
MakeCallback(callbacks->handle_, onerror_sym, 1, &arg);
|
||||
MakeCallback(callbacks->object(), onerror_sym, 1, &arg);
|
||||
callbacks->InvokeQueued(status);
|
||||
return;
|
||||
}
|
||||
@ -488,7 +493,7 @@ void TLSCallbacks::ClearOut() {
|
||||
Handle<Value> argv = GetSSLError(read, &err);
|
||||
|
||||
if (!argv.IsEmpty())
|
||||
MakeCallback(handle_, onerror_sym, 1, &argv);
|
||||
MakeCallback(object(), onerror_sym, 1, &argv);
|
||||
}
|
||||
}
|
||||
|
||||
@ -521,7 +526,7 @@ bool TLSCallbacks::ClearIn() {
|
||||
int err;
|
||||
Handle<Value> argv = GetSSLError(written, &err);
|
||||
if (!argv.IsEmpty())
|
||||
MakeCallback(handle_, onerror_sym, 1, &argv);
|
||||
MakeCallback(object(), onerror_sym, 1, &argv);
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -583,7 +588,7 @@ int TLSCallbacks::DoWrite(WriteWrap* w,
|
||||
int err;
|
||||
Handle<Value> argv = GetSSLError(written, &err);
|
||||
if (!argv.IsEmpty()) {
|
||||
MakeCallback(handle_, onerror_sym, 1, &argv);
|
||||
MakeCallback(object(), onerror_sym, 1, &argv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -772,7 +777,7 @@ void TLSCallbacks::ParseClientHello() {
|
||||
session_size));
|
||||
|
||||
argv[0] = hello_obj;
|
||||
MakeCallback(handle_, onclienthello_sym, 1, argv);
|
||||
MakeCallback(object(), onclienthello_sym, 1, argv);
|
||||
break;
|
||||
case kParseEnded:
|
||||
default:
|
||||
@ -782,7 +787,7 @@ void TLSCallbacks::ParseClientHello() {
|
||||
|
||||
|
||||
#define CASE_X509_ERR(CODE) case X509_V_ERR_##CODE: reason = #CODE; break;
|
||||
Handle<Value> TLSCallbacks::VerifyError(const Arguments& args) {
|
||||
void TLSCallbacks::VerifyError(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -793,8 +798,7 @@ Handle<Value> TLSCallbacks::VerifyError(const Arguments& args) {
|
||||
// We requested a certificate and they did not send us one.
|
||||
// Definitely an error.
|
||||
// XXX is this the right error message?
|
||||
return scope.Close(Exception::Error(
|
||||
String::New("UNABLE_TO_GET_ISSUER_CERT")));
|
||||
return ThrowError("UNABLE_TO_GET_ISSUER_CERT");
|
||||
}
|
||||
X509_free(peer_cert);
|
||||
|
||||
@ -803,36 +807,36 @@ Handle<Value> TLSCallbacks::VerifyError(const Arguments& args) {
|
||||
const char* reason = NULL;
|
||||
Local<String> s;
|
||||
switch (x509_verify_error) {
|
||||
case X509_V_OK:
|
||||
return Null(node_isolate);
|
||||
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
|
||||
CASE_X509_ERR(UNABLE_TO_GET_CRL)
|
||||
CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
|
||||
CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
|
||||
CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
|
||||
CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
|
||||
CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
|
||||
CASE_X509_ERR(CERT_NOT_YET_VALID)
|
||||
CASE_X509_ERR(CERT_HAS_EXPIRED)
|
||||
CASE_X509_ERR(CRL_NOT_YET_VALID)
|
||||
CASE_X509_ERR(CRL_HAS_EXPIRED)
|
||||
CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
|
||||
CASE_X509_ERR(OUT_OF_MEM)
|
||||
CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
|
||||
CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
|
||||
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
|
||||
CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
|
||||
CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
|
||||
CASE_X509_ERR(CERT_REVOKED)
|
||||
CASE_X509_ERR(INVALID_CA)
|
||||
CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
|
||||
CASE_X509_ERR(INVALID_PURPOSE)
|
||||
CASE_X509_ERR(CERT_UNTRUSTED)
|
||||
CASE_X509_ERR(CERT_REJECTED)
|
||||
default:
|
||||
case X509_V_OK:
|
||||
return args.GetReturnValue().SetNull();
|
||||
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT)
|
||||
CASE_X509_ERR(UNABLE_TO_GET_CRL)
|
||||
CASE_X509_ERR(UNABLE_TO_DECRYPT_CERT_SIGNATURE)
|
||||
CASE_X509_ERR(UNABLE_TO_DECRYPT_CRL_SIGNATURE)
|
||||
CASE_X509_ERR(UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY)
|
||||
CASE_X509_ERR(CERT_SIGNATURE_FAILURE)
|
||||
CASE_X509_ERR(CRL_SIGNATURE_FAILURE)
|
||||
CASE_X509_ERR(CERT_NOT_YET_VALID)
|
||||
CASE_X509_ERR(CERT_HAS_EXPIRED)
|
||||
CASE_X509_ERR(CRL_NOT_YET_VALID)
|
||||
CASE_X509_ERR(CRL_HAS_EXPIRED)
|
||||
CASE_X509_ERR(ERROR_IN_CERT_NOT_BEFORE_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CERT_NOT_AFTER_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CRL_LAST_UPDATE_FIELD)
|
||||
CASE_X509_ERR(ERROR_IN_CRL_NEXT_UPDATE_FIELD)
|
||||
CASE_X509_ERR(OUT_OF_MEM)
|
||||
CASE_X509_ERR(DEPTH_ZERO_SELF_SIGNED_CERT)
|
||||
CASE_X509_ERR(SELF_SIGNED_CERT_IN_CHAIN)
|
||||
CASE_X509_ERR(UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
|
||||
CASE_X509_ERR(UNABLE_TO_VERIFY_LEAF_SIGNATURE)
|
||||
CASE_X509_ERR(CERT_CHAIN_TOO_LONG)
|
||||
CASE_X509_ERR(CERT_REVOKED)
|
||||
CASE_X509_ERR(INVALID_CA)
|
||||
CASE_X509_ERR(PATH_LENGTH_EXCEEDED)
|
||||
CASE_X509_ERR(INVALID_PURPOSE)
|
||||
CASE_X509_ERR(CERT_UNTRUSTED)
|
||||
CASE_X509_ERR(CERT_REJECTED)
|
||||
default:
|
||||
s = String::New(X509_verify_cert_error_string(x509_verify_error));
|
||||
break;
|
||||
}
|
||||
@ -841,12 +845,12 @@ Handle<Value> TLSCallbacks::VerifyError(const Arguments& args) {
|
||||
s = String::New(reason);
|
||||
}
|
||||
|
||||
return scope.Close(Exception::Error(s));
|
||||
args.GetReturnValue().Set(Exception::Error(s));
|
||||
}
|
||||
#undef CASE_X509_ERR
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::SetVerifyMode(const Arguments& args) {
|
||||
void TLSCallbacks::SetVerifyMode(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -872,21 +876,19 @@ Handle<Value> TLSCallbacks::SetVerifyMode(const Arguments& args) {
|
||||
|
||||
// Always allow a connection. We'll reject in javascript.
|
||||
SSL_set_verify(wrap->ssl_, verify_mode, VerifyCallback);
|
||||
|
||||
return True(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::IsSessionReused(const Arguments& args) {
|
||||
void TLSCallbacks::IsSessionReused(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
|
||||
return scope.Close(Boolean::New(SSL_session_reused(wrap->ssl_)));
|
||||
bool yes = SSL_session_reused(wrap->ssl_);
|
||||
args.GetReturnValue().Set(yes);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::EnableSessionCallbacks(const Arguments& args) {
|
||||
void TLSCallbacks::EnableSessionCallbacks(
|
||||
const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -895,12 +897,10 @@ Handle<Value> TLSCallbacks::EnableSessionCallbacks(const Arguments& args) {
|
||||
wrap->hello_.state = kParseWaiting;
|
||||
wrap->hello_.frame_len = 0;
|
||||
wrap->hello_.body_offset = 0;
|
||||
|
||||
return scope.Close(Null(node_isolate));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::GetPeerCertificate(const Arguments& args) {
|
||||
void TLSCallbacks::GetPeerCertificate(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1021,18 +1021,17 @@ Handle<Value> TLSCallbacks::GetPeerCertificate(const Arguments& args) {
|
||||
X509_free(peer_cert);
|
||||
}
|
||||
|
||||
return scope.Close(info);
|
||||
args.GetReturnValue().Set(info);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::GetSession(const Arguments& args) {
|
||||
void TLSCallbacks::GetSession(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
|
||||
SSL_SESSION* sess = SSL_get_session(wrap->ssl_);
|
||||
if (!sess)
|
||||
return Undefined(node_isolate);
|
||||
if (!sess) return;
|
||||
|
||||
int slen = i2d_SSL_SESSION(sess, NULL);
|
||||
assert(slen > 0);
|
||||
@ -1042,15 +1041,16 @@ Handle<Value> TLSCallbacks::GetSession(const Arguments& args) {
|
||||
unsigned char* p = sbuf;
|
||||
i2d_SSL_SESSION(sess, &p);
|
||||
Local<Value> s = Encode(sbuf, slen, BINARY);
|
||||
args.GetReturnValue().Set(s);
|
||||
delete[] sbuf;
|
||||
return scope.Close(s);
|
||||
return;
|
||||
}
|
||||
|
||||
return Null(node_isolate);
|
||||
args.GetReturnValue().SetNull();
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::SetSession(const Arguments& args) {
|
||||
void TLSCallbacks::SetSession(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1074,22 +1074,18 @@ Handle<Value> TLSCallbacks::SetSession(const Arguments& args) {
|
||||
|
||||
delete[] sbuf;
|
||||
|
||||
if (!sess)
|
||||
return Undefined(node_isolate);
|
||||
if (!sess) return;
|
||||
|
||||
int r = SSL_set_session(wrap->ssl_, sess);
|
||||
SSL_SESSION_free(sess);
|
||||
|
||||
if (!r) {
|
||||
Local<String> eStr = String::New("SSL_set_session error");
|
||||
return ThrowException(Exception::Error(eStr));
|
||||
return ThrowError("SSL_set_session error");
|
||||
}
|
||||
|
||||
return True(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::LoadSession(const Arguments& args) {
|
||||
void TLSCallbacks::LoadSession(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1108,12 +1104,10 @@ Handle<Value> TLSCallbacks::LoadSession(const Arguments& args) {
|
||||
}
|
||||
|
||||
wrap->ParseFinish();
|
||||
|
||||
return True(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::GetCurrentCipher(const Arguments& args) {
|
||||
void TLSCallbacks::GetCurrentCipher(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1122,7 +1116,7 @@ Handle<Value> TLSCallbacks::GetCurrentCipher(const Arguments& args) {
|
||||
|
||||
c = SSL_get_current_cipher(wrap->ssl_);
|
||||
if (c == NULL)
|
||||
return Undefined(node_isolate);
|
||||
return;
|
||||
|
||||
const char* cipher_name = SSL_CIPHER_get_name(c);
|
||||
const char* cipher_version = SSL_CIPHER_get_version(c);
|
||||
@ -1130,7 +1124,7 @@ Handle<Value> TLSCallbacks::GetCurrentCipher(const Arguments& args) {
|
||||
Local<Object> info = Object::New();
|
||||
info->Set(name_sym, String::New(cipher_name));
|
||||
info->Set(version_sym, String::New(cipher_version));
|
||||
return scope.Close(info);
|
||||
args.GetReturnValue().Set(info);
|
||||
}
|
||||
|
||||
|
||||
@ -1164,9 +1158,7 @@ int TLSCallbacks::SelectNextProtoCallback(SSL* s,
|
||||
TLSCallbacks* p = static_cast<TLSCallbacks*>(arg);
|
||||
|
||||
// Release old protocol handler if present
|
||||
if (!p->selected_npn_proto_.IsEmpty()) {
|
||||
p->selected_npn_proto_.Dispose(node_isolate);
|
||||
}
|
||||
p->selected_npn_proto_.Dispose();
|
||||
|
||||
if (p->npn_protos_.IsEmpty()) {
|
||||
// We should at least select one protocol
|
||||
@ -1175,8 +1167,7 @@ int TLSCallbacks::SelectNextProtoCallback(SSL* s,
|
||||
*outlen = 8;
|
||||
|
||||
// set status: unsupported
|
||||
p->selected_npn_proto_ = Persistent<Value>::New(node_isolate,
|
||||
False(node_isolate));
|
||||
p->selected_npn_proto_.Reset(node_isolate, False(node_isolate));
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
@ -1202,22 +1193,22 @@ int TLSCallbacks::SelectNextProtoCallback(SSL* s,
|
||||
}
|
||||
|
||||
if (!result.IsEmpty())
|
||||
p->selected_npn_proto_ = Persistent<Value>::New(node_isolate, result);
|
||||
p->selected_npn_proto_.Reset(node_isolate, result);
|
||||
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::GetNegotiatedProto(const Arguments& args) {
|
||||
void TLSCallbacks::GetNegotiatedProto(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
|
||||
if (wrap->kind_ == kTLSClient) {
|
||||
if (wrap->selected_npn_proto_.IsEmpty())
|
||||
return Undefined(node_isolate);
|
||||
else
|
||||
return wrap->selected_npn_proto_;
|
||||
if (wrap->selected_npn_proto_.IsEmpty() == false) {
|
||||
args.GetReturnValue().Set(wrap->selected_npn_proto_);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned char* npn_proto;
|
||||
@ -1225,15 +1216,16 @@ Handle<Value> TLSCallbacks::GetNegotiatedProto(const Arguments& args) {
|
||||
|
||||
SSL_get0_next_proto_negotiated(wrap->ssl_, &npn_proto, &npn_proto_len);
|
||||
|
||||
if (!npn_proto)
|
||||
return False(node_isolate);
|
||||
if (!npn_proto) {
|
||||
return args.GetReturnValue().Set(false);
|
||||
}
|
||||
|
||||
return scope.Close(String::New(reinterpret_cast<const char*>(npn_proto),
|
||||
npn_proto_len));
|
||||
args.GetReturnValue().Set(
|
||||
String::New(reinterpret_cast<const char*>(npn_proto), npn_proto_len));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::SetNPNProtocols(const Arguments& args) {
|
||||
void TLSCallbacks::SetNPNProtocols(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1241,33 +1233,26 @@ Handle<Value> TLSCallbacks::SetNPNProtocols(const Arguments& args) {
|
||||
if (args.Length() < 1 || !Buffer::HasInstance(args[0]))
|
||||
return ThrowTypeError("Must give a Buffer as first argument");
|
||||
|
||||
// Release old handle
|
||||
if (!wrap->npn_protos_.IsEmpty())
|
||||
wrap->npn_protos_.Dispose(node_isolate);
|
||||
|
||||
wrap->npn_protos_ =
|
||||
Persistent<Object>::New(node_isolate, args[0]->ToObject());
|
||||
|
||||
return True(node_isolate);
|
||||
wrap->npn_protos_.Reset(node_isolate, args[0].As<Object>());
|
||||
}
|
||||
#endif // OPENSSL_NPN_NEGOTIATED
|
||||
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
Handle<Value> TLSCallbacks::GetServername(const Arguments& args) {
|
||||
void TLSCallbacks::GetServername(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
|
||||
if (wrap->kind_ == kTLSServer && !wrap->servername_.IsEmpty()) {
|
||||
return wrap->servername_;
|
||||
args.GetReturnValue().Set(wrap->servername_);
|
||||
} else {
|
||||
return False(node_isolate);
|
||||
args.GetReturnValue().Set(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TLSCallbacks::SetServername(const Arguments& args) {
|
||||
void TLSCallbacks::SetServername(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TLSCallbacks);
|
||||
@ -1276,17 +1261,15 @@ Handle<Value> TLSCallbacks::SetServername(const Arguments& args) {
|
||||
return ThrowTypeError("First argument should be a string");
|
||||
|
||||
if (wrap->started_)
|
||||
return ThrowException(Exception::Error(String::New("Already started.")));
|
||||
return ThrowError("Already started.");
|
||||
|
||||
if (wrap->kind_ != kTLSClient)
|
||||
return False(node_isolate);
|
||||
return;
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
String::Utf8Value servername(args[0].As<String>());
|
||||
SSL_set_tlsext_host_name(wrap->ssl_, *servername);
|
||||
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
|
||||
return Null(node_isolate);
|
||||
}
|
||||
|
||||
|
||||
@ -1298,31 +1281,21 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
|
||||
const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
|
||||
|
||||
if (servername) {
|
||||
if (!p->servername_.IsEmpty())
|
||||
p->servername_.Dispose(node_isolate);
|
||||
p->servername_ = Persistent<String>::New(node_isolate,
|
||||
String::New(servername));
|
||||
p->servername_.Reset(node_isolate, String::New(servername));
|
||||
|
||||
// Call the SNI callback and use its return value as context
|
||||
if (p->handle_->Has(onsniselect_sym)) {
|
||||
if (!p->sni_context_.IsEmpty())
|
||||
p->sni_context_.Dispose(node_isolate);
|
||||
Local<Object> object = p->object();
|
||||
if (object->Has(onsniselect_sym)) {
|
||||
p->sni_context_.Dispose();
|
||||
|
||||
// Get callback init args
|
||||
Local<Value> argv[1] = {*p->servername_};
|
||||
|
||||
// Call it
|
||||
Local<Value> ret = Local<Value>::New(node_isolate,
|
||||
MakeCallback(p->handle_,
|
||||
onsniselect_sym,
|
||||
ARRAY_SIZE(argv),
|
||||
argv));
|
||||
Local<Value> arg = Local<String>::New(node_isolate, p->servername_);
|
||||
Handle<Value> ret = MakeCallback(object, onsniselect_sym, 1, &arg);
|
||||
|
||||
// If ret is SecureContext
|
||||
if (ret->IsUndefined())
|
||||
return SSL_TLSEXT_ERR_NOACK;
|
||||
|
||||
p->sni_context_ = Persistent<Value>::New(node_isolate, ret);
|
||||
p->sni_context_.Reset(node_isolate, ret);
|
||||
SecureContext* sc = ObjectWrap::Unwrap<SecureContext>(ret.As<Object>());
|
||||
SSL_set_SSL_CTX(s, sc->ctx_);
|
||||
}
|
||||
@ -1365,28 +1338,28 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "setServername", SetServername);
|
||||
#endif // SSL_CRT_SET_TLSEXT_SERVERNAME_CB
|
||||
|
||||
tlsWrap = Persistent<Function>::New(node_isolate, t->GetFunction());
|
||||
tlsWrap.Reset(node_isolate, t->GetFunction());
|
||||
|
||||
onread_sym = NODE_PSYMBOL("onread");
|
||||
onsniselect_sym = NODE_PSYMBOL("onsniselect");
|
||||
onerror_sym = NODE_PSYMBOL("onerror");
|
||||
onhandshakestart_sym = NODE_PSYMBOL("onhandshakestart");
|
||||
onhandshakedone_sym = NODE_PSYMBOL("onhandshakedone");
|
||||
onclienthello_sym = NODE_PSYMBOL("onclienthello");
|
||||
onnewsession_sym = NODE_PSYMBOL("onnewsession");
|
||||
onread_sym = String::New("onread");
|
||||
onsniselect_sym = String::New("onsniselect");
|
||||
onerror_sym = String::New("onerror");
|
||||
onhandshakestart_sym = String::New("onhandshakestart");
|
||||
onhandshakedone_sym = String::New("onhandshakedone");
|
||||
onclienthello_sym = String::New("onclienthello");
|
||||
onnewsession_sym = String::New("onnewsession");
|
||||
|
||||
subject_sym = NODE_PSYMBOL("subject");
|
||||
issuer_sym = NODE_PSYMBOL("issuer");
|
||||
valid_from_sym = NODE_PSYMBOL("valid_from");
|
||||
valid_to_sym = NODE_PSYMBOL("valid_to");
|
||||
subjectaltname_sym = NODE_PSYMBOL("subjectaltname");
|
||||
modulus_sym = NODE_PSYMBOL("modulus");
|
||||
exponent_sym = NODE_PSYMBOL("exponent");
|
||||
fingerprint_sym = NODE_PSYMBOL("fingerprint");
|
||||
name_sym = NODE_PSYMBOL("name");
|
||||
version_sym = NODE_PSYMBOL("version");
|
||||
ext_key_usage_sym = NODE_PSYMBOL("ext_key_usage");
|
||||
sessionid_sym = NODE_PSYMBOL("sessionId");
|
||||
subject_sym = String::New("subject");
|
||||
issuer_sym = String::New("issuer");
|
||||
valid_from_sym = String::New("valid_from");
|
||||
valid_to_sym = String::New("valid_to");
|
||||
subjectaltname_sym = String::New("subjectaltname");
|
||||
modulus_sym = String::New("modulus");
|
||||
exponent_sym = String::New("exponent");
|
||||
fingerprint_sym = String::New("fingerprint");
|
||||
name_sym = String::New("name");
|
||||
version_sym = String::New("version");
|
||||
ext_key_usage_sym = String::New("ext_key_usage");
|
||||
sessionid_sym = String::New("sessionId");
|
||||
}
|
||||
|
||||
} // namespace node
|
||||
|
@ -118,17 +118,19 @@ class TLSCallbacks : public StreamWrapCallbacks {
|
||||
|
||||
v8::Handle<v8::Value> GetSSLError(int status, int* err);
|
||||
|
||||
static v8::Handle<v8::Value> Wrap(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Start(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetPeerCertificate(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> LoadSession(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetCurrentCipher(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> VerifyError(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetVerifyMode(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> IsSessionReused(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> EnableSessionCallbacks(const v8::Arguments& args);
|
||||
static void Wrap(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Start(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetPeerCertificate(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void LoadSession(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetCurrentCipher(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void VerifyError(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetVerifyMode(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsSessionReused(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void EnableSessionCallbacks(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
// TLS Session API
|
||||
static SSL_SESSION* GetSessionCallback(SSL* s,
|
||||
@ -138,8 +140,9 @@ class TLSCallbacks : public StreamWrapCallbacks {
|
||||
static int NewSessionCallback(SSL* s, SSL_SESSION* sess);
|
||||
|
||||
#ifdef OPENSSL_NPN_NEGOTIATED
|
||||
static v8::Handle<v8::Value> GetNegotiatedProto(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetNPNProtocols(const v8::Arguments& args);
|
||||
static void GetNegotiatedProto(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetNPNProtocols(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static int AdvertiseNextProtoCallback(SSL* s,
|
||||
const unsigned char** data,
|
||||
unsigned int* len,
|
||||
@ -153,15 +156,23 @@ class TLSCallbacks : public StreamWrapCallbacks {
|
||||
#endif // OPENSSL_NPN_NEGOTIATED
|
||||
|
||||
#ifdef SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
static v8::Handle<v8::Value> GetServername(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetServername(const v8::Arguments& args);
|
||||
static void GetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetServername(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static int SelectSNIContextCallback(SSL* s, int* ad, void* arg);
|
||||
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB
|
||||
|
||||
inline v8::Local<v8::Object> object() {
|
||||
return v8::Local<v8::Object>::New(node_isolate, persistent());
|
||||
}
|
||||
|
||||
inline v8::Persistent<v8::Object>& persistent() {
|
||||
return object_;
|
||||
}
|
||||
|
||||
Kind kind_;
|
||||
crypto::SecureContext* sc_;
|
||||
v8::Persistent<v8::Object> sc_handle_;
|
||||
v8::Persistent<v8::Object> handle_;
|
||||
v8::Persistent<v8::Object> object_;
|
||||
SSL* ssl_;
|
||||
BIO* enc_in_;
|
||||
BIO* enc_out_;
|
||||
|
@ -29,18 +29,16 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
using v8::Integer;
|
||||
using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::PropertyAttribute;
|
||||
using v8::String;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
|
||||
|
||||
@ -80,8 +78,7 @@ void TTYWrap::Initialize(Handle<Object> target) {
|
||||
NODE_SET_METHOD(target, "isTTY", IsTTY);
|
||||
NODE_SET_METHOD(target, "guessHandleType", GuessHandleType);
|
||||
|
||||
ttyConstructorTmpl = Persistent<FunctionTemplate>::New(node_isolate, t);
|
||||
|
||||
ttyConstructorTmpl.Reset(node_isolate, t);
|
||||
target->Set(String::NewSymbol("TTY"), t->GetFunction());
|
||||
}
|
||||
|
||||
@ -98,89 +95,66 @@ uv_tty_t* TTYWrap::UVHandle() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TTYWrap::GuessHandleType(const Arguments& args) {
|
||||
void TTYWrap::GuessHandleType(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
int fd = args[0]->Int32Value();
|
||||
assert(fd >= 0);
|
||||
|
||||
uv_handle_type t = uv_guess_handle(fd);
|
||||
const char* type = NULL;
|
||||
|
||||
switch (t) {
|
||||
case UV_TCP:
|
||||
return scope.Close(String::New("TCP"));
|
||||
|
||||
case UV_TTY:
|
||||
return scope.Close(String::New("TTY"));
|
||||
|
||||
case UV_UDP:
|
||||
return scope.Close(String::New("UDP"));
|
||||
|
||||
case UV_NAMED_PIPE:
|
||||
return scope.Close(String::New("PIPE"));
|
||||
|
||||
case UV_FILE:
|
||||
return scope.Close(String::New("FILE"));
|
||||
|
||||
case UV_UNKNOWN_HANDLE:
|
||||
return scope.Close(String::New("UNKNOWN"));
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return v8::Undefined(node_isolate);
|
||||
case UV_TCP: type = "TCP"; break;
|
||||
case UV_TTY: type = "TTY"; break;
|
||||
case UV_UDP: type = "UDP"; break;
|
||||
case UV_FILE: type = "FILE"; break;
|
||||
case UV_NAMED_PIPE: type = "PIPE"; break;
|
||||
case UV_UNKNOWN_HANDLE: type = "UNKNOWN"; break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
args.GetReturnValue().Set(String::New(type));
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TTYWrap::IsTTY(const Arguments& args) {
|
||||
void TTYWrap::IsTTY(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
int fd = args[0]->Int32Value();
|
||||
assert(fd >= 0);
|
||||
|
||||
if (uv_guess_handle(fd) == UV_TTY) {
|
||||
return v8::True(node_isolate);
|
||||
}
|
||||
|
||||
return v8::False(node_isolate);
|
||||
bool rc = uv_guess_handle(fd) == UV_TTY;
|
||||
args.GetReturnValue().Set(rc);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TTYWrap::GetWindowSize(const Arguments& args) {
|
||||
void TTYWrap::GetWindowSize(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TTYWrap)
|
||||
|
||||
int width, height;
|
||||
int r = uv_tty_get_winsize(&wrap->handle_, &width, &height);
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
return v8::Undefined(node_isolate);
|
||||
}
|
||||
if (r) return SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
Local<v8::Array> a = v8::Array::New(2);
|
||||
a->Set(0, Integer::New(width, node_isolate));
|
||||
a->Set(1, Integer::New(height, node_isolate));
|
||||
|
||||
return scope.Close(a);
|
||||
args.GetReturnValue().Set(a);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TTYWrap::SetRawMode(const Arguments& args) {
|
||||
void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(TTYWrap)
|
||||
|
||||
int r = uv_tty_set_mode(&wrap->handle_, args[0]->IsTrue());
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> TTYWrap::New(const Arguments& args) {
|
||||
void TTYWrap::New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
// This constructor should not be exposed to public javascript.
|
||||
@ -192,10 +166,7 @@ Handle<Value> TTYWrap::New(const Arguments& args) {
|
||||
assert(fd >= 0);
|
||||
|
||||
TTYWrap* wrap = new TTYWrap(args.This(), fd, args[1]->IsTrue());
|
||||
assert(wrap);
|
||||
wrap->UpdateWriteQueueSize();
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,28 +27,21 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::Object;
|
||||
using v8::Handle;
|
||||
using v8::Local;
|
||||
using v8::Value;
|
||||
using v8::Arguments;
|
||||
|
||||
|
||||
class TTYWrap : public StreamWrap {
|
||||
public:
|
||||
static void Initialize(Handle<Object> target);
|
||||
static TTYWrap* Unwrap(Local<Object> obj);
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
static TTYWrap* Unwrap(v8::Local<v8::Object> obj);
|
||||
|
||||
uv_tty_t* UVHandle();
|
||||
|
||||
private:
|
||||
TTYWrap(Handle<Object> object, int fd, bool readable);
|
||||
TTYWrap(v8::Handle<v8::Object> object, int fd, bool readable);
|
||||
|
||||
static Handle<Value> GuessHandleType(const Arguments& args);
|
||||
static Handle<Value> IsTTY(const Arguments& args);
|
||||
static Handle<Value> GetWindowSize(const Arguments& args);
|
||||
static Handle<Value> SetRawMode(const Arguments& args);
|
||||
static Handle<Value> New(const Arguments& args);
|
||||
static void GuessHandleType(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void IsTTY(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetWindowSize(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetRawMode(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
uv_tty_t handle_;
|
||||
};
|
||||
|
150
src/udp_wrap.cc
150
src/udp_wrap.cc
@ -30,9 +30,8 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
using v8::AccessorInfo;
|
||||
using v8::Arguments;
|
||||
using v8::Function;
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::FunctionTemplate;
|
||||
using v8::Handle;
|
||||
using v8::HandleScope;
|
||||
@ -41,6 +40,7 @@ using v8::Local;
|
||||
using v8::Object;
|
||||
using v8::Persistent;
|
||||
using v8::PropertyAttribute;
|
||||
using v8::PropertyCallbackInfo;
|
||||
using v8::String;
|
||||
using v8::Uint32;
|
||||
using v8::Value;
|
||||
@ -51,9 +51,9 @@ typedef ReqWrap<uv_udp_send_t> SendWrap;
|
||||
Local<Object> AddressToJS(const sockaddr* addr);
|
||||
|
||||
static Persistent<Function> constructor;
|
||||
static Persistent<String> buffer_sym;
|
||||
static Persistent<String> oncomplete_sym;
|
||||
static Persistent<String> onmessage_sym;
|
||||
static Cached<String> buffer_sym;
|
||||
static Cached<String> oncomplete_sym;
|
||||
static Cached<String> onmessage_sym;
|
||||
|
||||
|
||||
UDPWrap::UDPWrap(Handle<Object> object)
|
||||
@ -72,9 +72,9 @@ void UDPWrap::Initialize(Handle<Object> target) {
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
buffer_sym = NODE_PSYMBOL("buffer");
|
||||
oncomplete_sym = NODE_PSYMBOL("oncomplete");
|
||||
onmessage_sym = NODE_PSYMBOL("onmessage");
|
||||
buffer_sym = String::New("buffer");
|
||||
oncomplete_sym = String::New("oncomplete");
|
||||
onmessage_sym = String::New("onmessage");
|
||||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(New);
|
||||
t->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
@ -107,35 +107,29 @@ void UDPWrap::Initialize(Handle<Object> target) {
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref);
|
||||
NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);
|
||||
|
||||
constructor = Persistent<Function>::New(node_isolate,
|
||||
Persistent<FunctionTemplate>::New(node_isolate, t)->GetFunction());
|
||||
target->Set(String::NewSymbol("UDP"), constructor);
|
||||
constructor.Reset(node_isolate, t->GetFunction());
|
||||
target->Set(String::NewSymbol("UDP"), t->GetFunction());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::New(const Arguments& args) {
|
||||
void UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
assert(args.IsConstructCall());
|
||||
new UDPWrap(args.This());
|
||||
|
||||
return scope.Close(args.This());
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::GetFD(Local<String>, const AccessorInfo& args) {
|
||||
#if defined(_WIN32)
|
||||
return v8::Null(node_isolate);
|
||||
#else
|
||||
void UDPWrap::GetFD(Local<String>, const PropertyCallbackInfo<Value>& args) {
|
||||
#if !defined(_WIN32)
|
||||
HandleScope scope(node_isolate);
|
||||
UNWRAP(UDPWrap)
|
||||
int fd = (wrap == NULL) ? -1 : wrap->handle_.io_watcher.fd;
|
||||
return scope.Close(Integer::New(fd, node_isolate));
|
||||
args.GetReturnValue().Set(fd);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
|
||||
void UDPWrap::DoBind(const FunctionCallbackInfo<Value>& args, int family) {
|
||||
HandleScope scope(node_isolate);
|
||||
int r;
|
||||
|
||||
@ -160,32 +154,30 @@ Handle<Value> UDPWrap::DoBind(const Arguments& args, int family) {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (r)
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::Bind(const Arguments& args) {
|
||||
return DoBind(args, AF_INET);
|
||||
void UDPWrap::Bind(const FunctionCallbackInfo<Value>& args) {
|
||||
DoBind(args, AF_INET);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::Bind6(const Arguments& args) {
|
||||
return DoBind(args, AF_INET6);
|
||||
void UDPWrap::Bind6(const FunctionCallbackInfo<Value>& args) {
|
||||
DoBind(args, AF_INET6);
|
||||
}
|
||||
|
||||
|
||||
#define X(name, fn) \
|
||||
Handle<Value> UDPWrap::name(const Arguments& args) { \
|
||||
void UDPWrap::name(const FunctionCallbackInfo<Value>& args) { \
|
||||
HandleScope scope(node_isolate); \
|
||||
UNWRAP(UDPWrap) \
|
||||
assert(args.Length() == 1); \
|
||||
int flag = args[0]->Int32Value(); \
|
||||
int r = fn(&wrap->handle_, flag); \
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop())); \
|
||||
return scope.Close(Integer::New(r, node_isolate)); \
|
||||
args.GetReturnValue().Set(r); \
|
||||
}
|
||||
|
||||
X(SetTTL, uv_udp_set_ttl)
|
||||
@ -196,8 +188,8 @@ X(SetMulticastLoopback, uv_udp_set_multicast_loop)
|
||||
#undef X
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::SetMembership(const Arguments& args,
|
||||
uv_membership membership) {
|
||||
void UDPWrap::SetMembership(const FunctionCallbackInfo<Value>& args,
|
||||
uv_membership membership) {
|
||||
HandleScope scope(node_isolate);
|
||||
UNWRAP(UDPWrap)
|
||||
|
||||
@ -211,27 +203,26 @@ Handle<Value> UDPWrap::SetMembership(const Arguments& args,
|
||||
iface_cstr = NULL;
|
||||
}
|
||||
|
||||
int r = uv_udp_set_membership(&wrap->handle_, *address, iface_cstr,
|
||||
int r = uv_udp_set_membership(&wrap->handle_,
|
||||
*address,
|
||||
iface_cstr,
|
||||
membership);
|
||||
|
||||
if (r)
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
if (r) SetErrno(uv_last_error(uv_default_loop()));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::AddMembership(const Arguments& args) {
|
||||
return SetMembership(args, UV_JOIN_GROUP);
|
||||
void UDPWrap::AddMembership(const FunctionCallbackInfo<Value>& args) {
|
||||
SetMembership(args, UV_JOIN_GROUP);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::DropMembership(const Arguments& args) {
|
||||
return SetMembership(args, UV_LEAVE_GROUP);
|
||||
void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {
|
||||
SetMembership(args, UV_LEAVE_GROUP);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
|
||||
void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
|
||||
HandleScope scope(node_isolate);
|
||||
int r;
|
||||
|
||||
@ -249,7 +240,7 @@ Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
|
||||
assert(length <= Buffer::Length(buffer_obj) - offset);
|
||||
|
||||
SendWrap* req_wrap = new SendWrap();
|
||||
req_wrap->object_->SetHiddenValue(buffer_sym, buffer_obj);
|
||||
req_wrap->object()->SetHiddenValue(buffer_sym, buffer_obj);
|
||||
|
||||
uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
|
||||
length);
|
||||
@ -276,69 +267,57 @@ Handle<Value> UDPWrap::DoSend(const Arguments& args, int family) {
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
delete req_wrap;
|
||||
return Null(node_isolate);
|
||||
}
|
||||
else {
|
||||
return scope.Close(req_wrap->object_);
|
||||
args.GetReturnValue().Set(req_wrap->persistent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::Send(const Arguments& args) {
|
||||
return DoSend(args, AF_INET);
|
||||
void UDPWrap::Send(const FunctionCallbackInfo<Value>& args) {
|
||||
DoSend(args, AF_INET);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::Send6(const Arguments& args) {
|
||||
return DoSend(args, AF_INET6);
|
||||
void UDPWrap::Send6(const FunctionCallbackInfo<Value>& args) {
|
||||
DoSend(args, AF_INET6);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::RecvStart(const Arguments& args) {
|
||||
void UDPWrap::RecvStart(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(UDPWrap)
|
||||
|
||||
// UV_EALREADY means that the socket is already bound but that's okay
|
||||
int r = uv_udp_recv_start(&wrap->handle_, OnAlloc, OnRecv);
|
||||
if (r && uv_last_error(uv_default_loop()).code != UV_EALREADY) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
return False(node_isolate);
|
||||
}
|
||||
|
||||
return True(node_isolate);
|
||||
bool ok = r == 0 || uv_last_error(uv_default_loop()).code == UV_EALREADY;
|
||||
if (ok == false) SetErrno(uv_last_error(uv_default_loop()));
|
||||
args.GetReturnValue().Set(ok);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::RecvStop(const Arguments& args) {
|
||||
void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
|
||||
UNWRAP(UDPWrap)
|
||||
|
||||
int r = uv_udp_recv_stop(&wrap->handle_);
|
||||
|
||||
return scope.Close(Integer::New(r, node_isolate));
|
||||
args.GetReturnValue().Set(r);
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UDPWrap::GetSockName(const Arguments& args) {
|
||||
void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
|
||||
HandleScope scope(node_isolate);
|
||||
struct sockaddr_storage address;
|
||||
|
||||
UNWRAP(UDPWrap)
|
||||
|
||||
int addrlen = sizeof(address);
|
||||
int r = uv_udp_getsockname(&wrap->handle_,
|
||||
reinterpret_cast<sockaddr*>(&address),
|
||||
&addrlen);
|
||||
|
||||
if (r) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
return Null(node_isolate);
|
||||
}
|
||||
if (r) return SetErrno(uv_last_error(uv_default_loop()));
|
||||
|
||||
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
|
||||
return scope.Close(AddressToJS(addr));
|
||||
args.GetReturnValue().Set(AddressToJS(addr));
|
||||
}
|
||||
|
||||
|
||||
@ -351,21 +330,22 @@ void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
|
||||
SendWrap* req_wrap = reinterpret_cast<SendWrap*>(req->data);
|
||||
UDPWrap* wrap = reinterpret_cast<UDPWrap*>(req->handle->data);
|
||||
|
||||
assert(req_wrap->object_.IsEmpty() == false);
|
||||
assert(wrap->object_.IsEmpty() == false);
|
||||
assert(req_wrap->persistent().IsEmpty() == false);
|
||||
assert(wrap->persistent().IsEmpty() == false);
|
||||
|
||||
if (status) {
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
}
|
||||
|
||||
Local<Object> req_wrap_obj = req_wrap->object();
|
||||
Local<Value> argv[4] = {
|
||||
Integer::New(status, node_isolate),
|
||||
Local<Value>::New(node_isolate, wrap->object_),
|
||||
Local<Value>::New(node_isolate, req_wrap->object_),
|
||||
req_wrap->object_->GetHiddenValue(buffer_sym),
|
||||
wrap->object(),
|
||||
req_wrap_obj,
|
||||
req_wrap_obj->GetHiddenValue(buffer_sym),
|
||||
};
|
||||
|
||||
MakeCallback(req_wrap->object_, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
|
||||
delete req_wrap;
|
||||
}
|
||||
|
||||
@ -392,9 +372,10 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
|
||||
if (nread < 0) {
|
||||
if (buf.base != NULL)
|
||||
free(buf.base);
|
||||
Local<Value> argv[] = { Local<Object>::New(node_isolate, wrap->object_) };
|
||||
Local<Object> wrap_obj = wrap->object();
|
||||
Local<Value> argv[] = { wrap_obj };
|
||||
SetErrno(uv_last_error(uv_default_loop()));
|
||||
MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -406,12 +387,13 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
|
||||
|
||||
buf.base = static_cast<char*>(realloc(buf.base, nread));
|
||||
|
||||
Local<Object> wrap_obj = wrap->object();
|
||||
Local<Value> argv[] = {
|
||||
Local<Object>::New(node_isolate, wrap->object_),
|
||||
wrap_obj,
|
||||
Buffer::Use(buf.base, nread),
|
||||
AddressToJS(addr)
|
||||
};
|
||||
MakeCallback(wrap->object_, onmessage_sym, ARRAY_SIZE(argv), argv);
|
||||
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
|
||||
}
|
||||
|
||||
|
||||
@ -425,11 +407,7 @@ UDPWrap* UDPWrap::Unwrap(Local<Object> obj) {
|
||||
Local<Object> UDPWrap::Instantiate() {
|
||||
// If this assert fires then Initialize hasn't been called yet.
|
||||
assert(constructor.IsEmpty() == false);
|
||||
|
||||
HandleScope scope(node_isolate);
|
||||
Local<Object> obj = constructor->NewInstance();
|
||||
|
||||
return scope.Close(obj);
|
||||
return NewInstance(constructor);
|
||||
}
|
||||
|
||||
|
||||
|
@ -10,22 +10,23 @@ namespace node {
|
||||
class UDPWrap: public HandleWrap {
|
||||
public:
|
||||
static void Initialize(v8::Handle<v8::Object> target);
|
||||
static v8::Handle<v8::Value> GetFD(v8::Local<v8::String>,
|
||||
const v8::AccessorInfo&);
|
||||
static v8::Handle<v8::Value> New(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Bind(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Send(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Bind6(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Send6(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> RecvStart(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> RecvStop(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> GetSockName(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> AddMembership(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> DropMembership(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetMulticastTTL(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetMulticastLoopback(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetBroadcast(const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> SetTTL(const v8::Arguments& args);
|
||||
static void GetFD(v8::Local<v8::String>,
|
||||
const v8::PropertyCallbackInfo<v8::Value>&);
|
||||
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Send(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Bind6(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void Send6(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RecvStart(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void RecvStop(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetSockName(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void AddMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void DropMembership(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetMulticastTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetMulticastLoopback(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetBroadcast(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void SetTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static UDPWrap* Unwrap(v8::Local<v8::Object> obj);
|
||||
|
||||
static v8::Local<v8::Object> Instantiate();
|
||||
@ -35,10 +36,12 @@ class UDPWrap: public HandleWrap {
|
||||
UDPWrap(v8::Handle<v8::Object> object);
|
||||
virtual ~UDPWrap();
|
||||
|
||||
static v8::Handle<v8::Value> DoBind(const v8::Arguments& args, int family);
|
||||
static v8::Handle<v8::Value> DoSend(const v8::Arguments& args, int family);
|
||||
static v8::Handle<v8::Value> SetMembership(const v8::Arguments& args,
|
||||
uv_membership membership);
|
||||
static void DoBind(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
int family);
|
||||
static void DoSend(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
int family);
|
||||
static void SetMembership(const v8::FunctionCallbackInfo<v8::Value>& args,
|
||||
uv_membership membership);
|
||||
|
||||
static uv_buf_t OnAlloc(uv_handle_t* handle, size_t suggested_size);
|
||||
static void OnSend(uv_udp_send_t* req, int status);
|
||||
|
@ -1,874 +0,0 @@
|
||||
// V8 Typed Array implementation.
|
||||
// (c) Dean McNamee <dean@gmail.com>, 2011.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#include <stdlib.h> // calloc, etc
|
||||
#include <string.h> // memmove
|
||||
#include <stdint.h>
|
||||
|
||||
#include "v8_typed_array.h"
|
||||
#include "v8_typed_array_bswap.h"
|
||||
#include "node_buffer.h"
|
||||
#include "node.h"
|
||||
#include "v8.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using node::ThrowError;
|
||||
using node::ThrowRangeError;
|
||||
using node::ThrowTypeError;
|
||||
|
||||
struct BatchedMethods {
|
||||
const char* name;
|
||||
v8::Handle<v8::Value> (*func)(const v8::Arguments& args);
|
||||
};
|
||||
|
||||
class ArrayBuffer {
|
||||
public:
|
||||
static v8::Persistent<v8::FunctionTemplate> GetTemplate() {
|
||||
static v8::Persistent<v8::FunctionTemplate> ft_cache;
|
||||
if (!ft_cache.IsEmpty())
|
||||
return ft_cache;
|
||||
|
||||
v8::HandleScope scope(node::node_isolate);
|
||||
ft_cache = v8::Persistent<v8::FunctionTemplate>::New(node::node_isolate,
|
||||
v8::FunctionTemplate::New(&ArrayBuffer::V8New));
|
||||
ft_cache->SetClassName(v8::String::New("ArrayBuffer"));
|
||||
v8::Local<v8::ObjectTemplate> instance = ft_cache->InstanceTemplate();
|
||||
instance->SetInternalFieldCount(1); // Buffer.
|
||||
|
||||
v8::Local<v8::Signature> default_signature = v8::Signature::New(ft_cache);
|
||||
|
||||
instance->Set(v8::String::New("slice"),
|
||||
v8::FunctionTemplate::New(&ArrayBuffer::slice,
|
||||
v8::Handle<v8::Value>(),
|
||||
default_signature));
|
||||
|
||||
return ft_cache;
|
||||
}
|
||||
|
||||
static bool HasInstance(v8::Handle<v8::Value> value) {
|
||||
return GetTemplate()->HasInstance(value);
|
||||
}
|
||||
|
||||
private:
|
||||
static void WeakCallback(v8::Isolate* isolate,
|
||||
v8::Persistent<v8::Object>* pobj,
|
||||
void* data) {
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Object> obj = v8::Local<v8::Object>::New(*pobj);
|
||||
|
||||
void* ptr = obj->GetIndexedPropertiesExternalArrayData();
|
||||
int element_size = v8_typed_array::SizeOfArrayElementForType(
|
||||
obj->GetIndexedPropertiesExternalArrayDataType());
|
||||
int size =
|
||||
obj->GetIndexedPropertiesExternalArrayDataLength() * element_size;
|
||||
|
||||
node::node_isolate->AdjustAmountOfExternalAllocatedMemory(-size);
|
||||
|
||||
(*pobj).ClearWeak(isolate);
|
||||
(*pobj).Dispose(isolate);
|
||||
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> V8New(const v8::Arguments& args) {
|
||||
if (!args.IsConstructCall())
|
||||
return node::FromConstructorTemplate(GetTemplate(), args);
|
||||
|
||||
// To match Chrome, we allow "new ArrayBuffer()".
|
||||
// if (args.Length() != 1)
|
||||
// return ThrowError("Wrong number of arguments.");
|
||||
|
||||
if (args[0]->Int32Value() < 0) {
|
||||
return ThrowRangeError("ArrayBufferView size is not a small enough "
|
||||
"positive integer.");
|
||||
}
|
||||
|
||||
size_t num_bytes = args[0]->Uint32Value();
|
||||
if (num_bytes > node::Buffer::kMaxLength) {
|
||||
return ThrowRangeError("length > kMaxLength");
|
||||
}
|
||||
|
||||
void* buf = calloc(num_bytes, 1);
|
||||
if (!buf)
|
||||
return ThrowError("Unable to allocate ArrayBuffer.");
|
||||
|
||||
args.This()->SetAlignedPointerInInternalField(0, buf);
|
||||
|
||||
args.This()->Set(v8::String::New("byteLength"),
|
||||
v8::Integer::NewFromUnsigned(num_bytes,
|
||||
node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
|
||||
// NOTE(deanm): This is not in the spec, you shouldn't be able to index
|
||||
// the ArrayBuffer. However, it currently simplifies some handling in our
|
||||
// implementation, so we make ArrayView operator[] act like an Uint8Array.
|
||||
// , This allows DataView to work with both ArrayBuffers and TypedArrays.
|
||||
args.This()->SetIndexedPropertiesToExternalArrayData(
|
||||
buf, v8::kExternalUnsignedByteArray, num_bytes);
|
||||
|
||||
node::node_isolate->AdjustAmountOfExternalAllocatedMemory(num_bytes);
|
||||
|
||||
v8::Persistent<v8::Object> persistent =
|
||||
v8::Persistent<v8::Object>::New(node::node_isolate, args.This());
|
||||
persistent.MakeWeak(node::node_isolate,
|
||||
static_cast<void*>(NULL),
|
||||
&ArrayBuffer::WeakCallback);
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> slice(const v8::Arguments& args) {
|
||||
if (args.Length() < 1)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
unsigned int length =
|
||||
args.This()->Get(v8::String::New("byteLength"))->Uint32Value();
|
||||
int begin = args[0]->Int32Value();
|
||||
int end = length;
|
||||
if (args.Length() > 1)
|
||||
end = args[1]->Int32Value();
|
||||
|
||||
if (begin < 0) begin = length + begin;
|
||||
if (begin < 0) begin = 0;
|
||||
if (static_cast<unsigned>(begin) > length) begin = length;
|
||||
|
||||
if (end < 0) end = length + end;
|
||||
if (end < 0) end = 0;
|
||||
if (static_cast<unsigned>(end) > length) end = length;
|
||||
|
||||
if (begin > end) begin = end;
|
||||
|
||||
unsigned int slice_length = end - begin;
|
||||
v8::Local<v8::Value> argv[] = {
|
||||
v8::Integer::New(slice_length, node::node_isolate)};
|
||||
v8::Local<v8::Object> buffer = ArrayBuffer::GetTemplate()->
|
||||
GetFunction()->NewInstance(1, argv);
|
||||
|
||||
// constructor failed
|
||||
if (buffer.IsEmpty()) return v8::Undefined(node::node_isolate);
|
||||
|
||||
void* src = args.This()->GetAlignedPointerFromInternalField(0);
|
||||
void* dest = buffer->GetAlignedPointerFromInternalField(0);
|
||||
memcpy(dest, static_cast<char*>(src) + begin, slice_length);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
|
||||
static bool checkAlignment(size_t val, unsigned int bytes) {
|
||||
return (val & (bytes - 1)) == 0; // Handles bytes == 0.
|
||||
}
|
||||
|
||||
template <v8::ExternalArrayType TEAType>
|
||||
struct TEANameTrait {
|
||||
static const char* const name;
|
||||
};
|
||||
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalByteArray>::name = "Int8Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalUnsignedByteArray>::name = "Uint8Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalPixelArray>::name = "Uint8ClampedArray";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalShortArray>::name = "Int16Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalUnsignedShortArray>::name = "Uint16Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalIntArray>::name = "Int32Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalUnsignedIntArray>::name = "Uint32Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalFloatArray>::name = "Float32Array";
|
||||
template <> const char* const
|
||||
TEANameTrait<v8::kExternalDoubleArray>::name = "Float64Array";
|
||||
|
||||
template <unsigned int TBytes, v8::ExternalArrayType TEAType>
|
||||
class TypedArray {
|
||||
public:
|
||||
static v8::Persistent<v8::FunctionTemplate> GetTemplate() {
|
||||
static v8::Persistent<v8::FunctionTemplate> ft_cache;
|
||||
if (!ft_cache.IsEmpty())
|
||||
return ft_cache;
|
||||
|
||||
v8::HandleScope scope(node::node_isolate);
|
||||
ft_cache = v8::Persistent<v8::FunctionTemplate>::New(node::node_isolate,
|
||||
v8::FunctionTemplate::New(&TypedArray<TBytes, TEAType>::V8New));
|
||||
ft_cache->SetClassName(v8::String::New(TEANameTrait<TEAType>::name));
|
||||
v8::Local<v8::ObjectTemplate> instance = ft_cache->InstanceTemplate();
|
||||
instance->SetInternalFieldCount(0);
|
||||
|
||||
ft_cache->Set(v8::String::New("BYTES_PER_ELEMENT"),
|
||||
v8::Uint32::New(TBytes, node::node_isolate), v8::ReadOnly);
|
||||
instance->Set(v8::String::New("BYTES_PER_ELEMENT"),
|
||||
v8::Uint32::New(TBytes, node::node_isolate), v8::ReadOnly);
|
||||
|
||||
v8::Local<v8::Signature> default_signature = v8::Signature::New(ft_cache);
|
||||
|
||||
static BatchedMethods methods[] = {
|
||||
{ "get", &TypedArray<TBytes, TEAType>::get },
|
||||
{ "set", &TypedArray<TBytes, TEAType>::set },
|
||||
{ "slice", &TypedArray<TBytes, TEAType>::subarray },
|
||||
{ "subarray", &TypedArray<TBytes, TEAType>::subarray },
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(methods) / sizeof(*methods); ++i) {
|
||||
instance->Set(v8::String::New(methods[i].name),
|
||||
v8::FunctionTemplate::New(methods[i].func,
|
||||
v8::Handle<v8::Value>(),
|
||||
default_signature));
|
||||
}
|
||||
|
||||
return ft_cache;
|
||||
}
|
||||
|
||||
static bool HasInstance(v8::Handle<v8::Value> value) {
|
||||
return GetTemplate()->HasInstance(value);
|
||||
}
|
||||
|
||||
private:
|
||||
static v8::Handle<v8::Value> V8New(const v8::Arguments& args) {
|
||||
if (!args.IsConstructCall())
|
||||
return node::FromConstructorTemplate(GetTemplate(), args);
|
||||
|
||||
// To match Chrome, we allow "new Float32Array()".
|
||||
// if (args.Length() != 1)
|
||||
// return ThrowError("Wrong number of arguments.");
|
||||
|
||||
v8::Local<v8::Object> buffer;
|
||||
unsigned int length = 0;
|
||||
unsigned int byte_offset = 0;
|
||||
|
||||
if (ArrayBuffer::HasInstance(args[0])) { // ArrayBuffer constructor.
|
||||
buffer = v8::Local<v8::Object>::Cast(args[0]);
|
||||
size_t buflen =
|
||||
buffer->GetIndexedPropertiesExternalArrayDataLength();
|
||||
|
||||
if (!args[1]->IsUndefined() && args[1]->Int32Value() < 0)
|
||||
return ThrowRangeError("Byte offset out of range.");
|
||||
byte_offset = args[1]->Uint32Value();
|
||||
|
||||
if (args.Length() > 2) {
|
||||
if (args[2]->Int32Value() < 0)
|
||||
return ThrowRangeError("Length out of range.");
|
||||
length = args[2]->Uint32Value();
|
||||
} else {
|
||||
if (buflen < byte_offset ||
|
||||
!checkAlignment(buflen - byte_offset, TBytes)) {
|
||||
return ThrowRangeError("Byte offset / length is not aligned.");
|
||||
}
|
||||
length = (buflen - byte_offset) / TBytes;
|
||||
}
|
||||
|
||||
// NOTE(deanm): Sloppy integer overflow checks.
|
||||
if (byte_offset > buflen || byte_offset + length > buflen ||
|
||||
byte_offset + length * TBytes > buflen) {
|
||||
return ThrowRangeError("Length is out of range.");
|
||||
}
|
||||
|
||||
void* buf = buffer->GetIndexedPropertiesExternalArrayData();
|
||||
char* begin = reinterpret_cast<char*>(buf) + byte_offset;
|
||||
|
||||
if (!checkAlignment(reinterpret_cast<uintptr_t>(begin), TBytes))
|
||||
return ThrowRangeError("Byte offset is not aligned.");
|
||||
|
||||
args.This()->SetIndexedPropertiesToExternalArrayData(
|
||||
begin, TEAType, length);
|
||||
}
|
||||
else if (args[0]->IsObject()) { // TypedArray / type[] constructor.
|
||||
v8::Local<v8::Object> obj = v8::Local<v8::Object>::Cast(args[0]);
|
||||
length = obj->Get(v8::String::New("length"))->Uint32Value();
|
||||
|
||||
// TODO(deanm): Handle integer overflow.
|
||||
v8::Local<v8::Value> argv[1] = {
|
||||
v8::Integer::NewFromUnsigned(length * TBytes, node::node_isolate)};
|
||||
buffer = ArrayBuffer::GetTemplate()->
|
||||
GetFunction()->NewInstance(1, argv);
|
||||
// constructor failed
|
||||
if (buffer.IsEmpty()) return v8::Undefined(node::node_isolate);
|
||||
|
||||
void* buf = buffer->GetAlignedPointerFromInternalField(0);
|
||||
args.This()->SetIndexedPropertiesToExternalArrayData(
|
||||
buf, TEAType, length);
|
||||
// TODO(deanm): check for failure.
|
||||
for (uint32_t i = 0; i < length; ++i) {
|
||||
// Use the v8 setter to deal with typing. Maybe slow?
|
||||
args.This()->Set(i, obj->Get(i));
|
||||
}
|
||||
} else { // length constructor.
|
||||
// Try to match Chrome, Float32Array(""), Float32Array(true/false) is
|
||||
// okay, but Float32Array(null) throws a TypeError and
|
||||
// Float32Array(undefined) throw a RangeError.
|
||||
if (args.Length() > 0 && (args[0]->IsUndefined() || args[0]->IsNull()))
|
||||
return ThrowTypeError("Type error");
|
||||
|
||||
if (args[0]->Int32Value() < 0) {
|
||||
return ThrowRangeError("ArrayBufferView size is not a small enough "
|
||||
"positive integer.");
|
||||
}
|
||||
|
||||
length = args[0]->Uint32Value();
|
||||
// TODO(deanm): Handle integer overflow.
|
||||
v8::Local<v8::Value> argv[1] = {
|
||||
v8::Integer::NewFromUnsigned(length * TBytes, node::node_isolate)};
|
||||
|
||||
buffer = ArrayBuffer::GetTemplate()->
|
||||
GetFunction()->NewInstance(1, argv);
|
||||
// constructor failed
|
||||
if (buffer.IsEmpty()) return v8::Undefined(node::node_isolate);
|
||||
|
||||
void* buf = buffer->GetAlignedPointerFromInternalField(0);
|
||||
args.This()->SetIndexedPropertiesToExternalArrayData(
|
||||
buf, TEAType, length);
|
||||
// TODO(deanm): check for failure.
|
||||
}
|
||||
|
||||
args.This()->Set(v8::String::New("buffer"),
|
||||
buffer,
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
args.This()->Set(v8::String::New("length"),
|
||||
v8::Integer::NewFromUnsigned(length, node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
args.This()->Set(v8::String::New("byteOffset"),
|
||||
v8::Integer::NewFromUnsigned(byte_offset,
|
||||
node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
args.This()->Set(v8::String::New("byteLength"),
|
||||
v8::Integer::NewFromUnsigned(length * TBytes,
|
||||
node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
|
||||
return args.This();
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> get(const v8::Arguments& args) {
|
||||
if (args.Length() < 1)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
if (args[0]->IsNumber())
|
||||
return args.This()->Get(args[0]->Uint32Value());
|
||||
|
||||
return v8::Undefined(node::node_isolate);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> set(const v8::Arguments& args) {
|
||||
if (args.Length() < 1)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
//if (!args[0]->IsObject())
|
||||
// return ThrowTypeError("Type error.");
|
||||
|
||||
if (args[0]->IsNumber()) { // index, <type> value
|
||||
args.This()->Set(args[0]->Uint32Value(), args[1]);
|
||||
} else if (args[0]->IsObject()) {
|
||||
v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(args[0]);
|
||||
|
||||
if (TypedArray<TBytes, TEAType>::HasInstance(obj)) { // ArrayBufferView.
|
||||
if (args[1]->Int32Value() < 0)
|
||||
return ThrowRangeError("Offset may not be negative.");
|
||||
|
||||
unsigned int offset = args[1]->Uint32Value();
|
||||
unsigned int src_length =
|
||||
obj->Get(v8::String::New("length"))->Uint32Value();
|
||||
unsigned int dst_length =
|
||||
args.This()->Get(v8::String::New("length"))->Uint32Value();
|
||||
if (offset > dst_length)
|
||||
return ThrowRangeError("Offset out of range.");
|
||||
|
||||
if (src_length > dst_length - offset)
|
||||
return ThrowRangeError("Offset/length out of range.");
|
||||
|
||||
// We don't want to get the buffer pointer, because that means we'll have
|
||||
// to just do the calculations for byteOffset / byteLength again.
|
||||
// Instead just use the pointer on the external array data.
|
||||
void* src_ptr = obj->GetIndexedPropertiesExternalArrayData();
|
||||
void* dst_ptr = args.This()->GetIndexedPropertiesExternalArrayData();
|
||||
|
||||
// From the spec:
|
||||
// If the input array is a TypedArray, the two arrays may use the same
|
||||
// underlying ArrayBuffer. In this situation, setting the values takes
|
||||
// place as if all the data is first copied into a temporary buffer that
|
||||
// does not overlap either of the arrays, and then the data from the
|
||||
// temporary buffer is copied into the current array.
|
||||
memmove(reinterpret_cast<char*>(dst_ptr) + offset * TBytes, src_ptr,
|
||||
src_length * TBytes);
|
||||
} else { // type[]
|
||||
if (args[1]->Int32Value() < 0)
|
||||
return ThrowRangeError("Offset may not be negative.");
|
||||
|
||||
unsigned int src_length =
|
||||
obj->Get(v8::String::New("length"))->Uint32Value();
|
||||
unsigned int dst_length =
|
||||
args.This()->Get(v8::String::New("length"))->Uint32Value();
|
||||
unsigned int offset = args[1]->Uint32Value();
|
||||
|
||||
if (offset > dst_length)
|
||||
return ThrowRangeError("Offset out of range.");
|
||||
|
||||
if (src_length > dst_length - offset)
|
||||
return ThrowRangeError("Offset/length out of range.");
|
||||
|
||||
for (uint32_t i = 0; i < src_length; ++i) {
|
||||
// Use the v8 setter to deal with typing. Maybe slow?
|
||||
args.This()->Set(i + offset, obj->Get(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v8::Undefined(node::node_isolate);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> subarray(const v8::Arguments& args) {
|
||||
// TODO(deanm): The unsigned / signed type mixing makes me super nervous.
|
||||
|
||||
unsigned int length =
|
||||
args.This()->Get(v8::String::New("length"))->Uint32Value();
|
||||
int begin = args[0]->Int32Value();
|
||||
int end = length;
|
||||
if (args.Length() > 1)
|
||||
end = args[1]->Int32Value();
|
||||
|
||||
if (begin < 0) begin = length + begin;
|
||||
if (begin < 0) begin = 0;
|
||||
if ((unsigned)begin > length) begin = length;
|
||||
|
||||
if (end < 0) end = length + end;
|
||||
if (end < 0) end = 0;
|
||||
if ((unsigned)end > length) end = length;
|
||||
|
||||
if (begin > end) begin = end;
|
||||
|
||||
int byte_offset = begin * TBytes +
|
||||
args.This()->Get(v8::String::New("byteOffset"))->Uint32Value();
|
||||
|
||||
// Call through to the ArrayBuffer, byteOffset, length constructor.
|
||||
v8::Local<v8::Value> argv[] = {
|
||||
args.This()->Get(v8::String::New("buffer")),
|
||||
v8::Integer::New(byte_offset, node::node_isolate),
|
||||
v8::Integer::New(end - begin, node::node_isolate)};
|
||||
return TypedArray<TBytes, TEAType>::GetTemplate()->
|
||||
GetFunction()->NewInstance(3, argv);
|
||||
}
|
||||
};
|
||||
|
||||
class Int8Array : public TypedArray<1, v8::kExternalByteArray> { };
|
||||
class Uint8Array : public TypedArray<1, v8::kExternalUnsignedByteArray> { };
|
||||
class Uint8ClampedArray : public TypedArray<1, v8::kExternalPixelArray> { };
|
||||
class Int16Array : public TypedArray<2, v8::kExternalShortArray> { };
|
||||
class Uint16Array : public TypedArray<2, v8::kExternalUnsignedShortArray> { };
|
||||
class Int32Array : public TypedArray<4, v8::kExternalIntArray> { };
|
||||
class Uint32Array : public TypedArray<4, v8::kExternalUnsignedIntArray> { };
|
||||
class Float32Array : public TypedArray<4, v8::kExternalFloatArray> { };
|
||||
class Float64Array : public TypedArray<8, v8::kExternalDoubleArray> { };
|
||||
|
||||
template <typename T>
|
||||
v8::Handle<v8::Value> cTypeToValue(T) {
|
||||
return v8::Undefined(node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(unsigned char val) {
|
||||
return v8::Integer::NewFromUnsigned(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(signed char val) {
|
||||
return v8::Integer::New(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(unsigned short val) {
|
||||
return v8::Integer::NewFromUnsigned(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(short val) {
|
||||
return v8::Integer::New(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(unsigned int val) {
|
||||
return v8::Integer::NewFromUnsigned(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(int val) {
|
||||
return v8::Integer::New(val, node::node_isolate);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(float val) {
|
||||
return v8::Number::New(val);
|
||||
}
|
||||
|
||||
template <>
|
||||
v8::Handle<v8::Value> cTypeToValue(double val) {
|
||||
return v8::Number::New(val);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
T valueToCType(v8::Handle<v8::Value> value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned char valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Uint32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
signed char valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Int32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned short valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Uint32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
short valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Int32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned int valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Uint32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
int valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->Int32Value();
|
||||
}
|
||||
|
||||
template <>
|
||||
float valueToCType(v8::Handle<v8::Value> value) {
|
||||
return static_cast<float>(value->NumberValue());
|
||||
}
|
||||
|
||||
template <>
|
||||
double valueToCType(v8::Handle<v8::Value> value) {
|
||||
return value->NumberValue();
|
||||
}
|
||||
|
||||
|
||||
class DataView {
|
||||
public:
|
||||
static v8::Persistent<v8::FunctionTemplate> GetTemplate() {
|
||||
static v8::Persistent<v8::FunctionTemplate> ft_cache;
|
||||
if (!ft_cache.IsEmpty())
|
||||
return ft_cache;
|
||||
|
||||
v8::HandleScope scope(node::node_isolate);
|
||||
ft_cache = v8::Persistent<v8::FunctionTemplate>::New(node::node_isolate,
|
||||
v8::FunctionTemplate::New(&DataView::V8New));
|
||||
ft_cache->SetClassName(v8::String::New("DataView"));
|
||||
v8::Local<v8::ObjectTemplate> instance = ft_cache->InstanceTemplate();
|
||||
instance->SetInternalFieldCount(0);
|
||||
|
||||
v8::Local<v8::Signature> default_signature = v8::Signature::New(ft_cache);
|
||||
|
||||
static BatchedMethods methods[] = {
|
||||
{ "getUint8", &DataView::getUint8 },
|
||||
{ "getInt8", &DataView::getInt8 },
|
||||
{ "getUint16", &DataView::getUint16 },
|
||||
{ "getInt16", &DataView::getInt16 },
|
||||
{ "getUint32", &DataView::getUint32 },
|
||||
{ "getInt32", &DataView::getInt32 },
|
||||
{ "getFloat32", &DataView::getFloat32 },
|
||||
{ "getFloat64", &DataView::getFloat64 },
|
||||
{ "setUint8", &DataView::setUint8 },
|
||||
{ "setInt8", &DataView::setInt8 },
|
||||
{ "setUint16", &DataView::setUint16 },
|
||||
{ "setInt16", &DataView::setInt16 },
|
||||
{ "setUint32", &DataView::setUint32 },
|
||||
{ "setInt32", &DataView::setInt32 },
|
||||
{ "setFloat32", &DataView::setFloat32 },
|
||||
{ "setFloat64", &DataView::setFloat64 },
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < sizeof(methods) / sizeof(*methods); ++i) {
|
||||
instance->Set(v8::String::New(methods[i].name),
|
||||
v8::FunctionTemplate::New(methods[i].func,
|
||||
v8::Handle<v8::Value>(),
|
||||
default_signature));
|
||||
}
|
||||
|
||||
return ft_cache;
|
||||
}
|
||||
|
||||
static bool HasInstance(v8::Handle<v8::Value> value) {
|
||||
return GetTemplate()->HasInstance(value);
|
||||
}
|
||||
|
||||
private:
|
||||
static v8::Handle<v8::Value> V8New(const v8::Arguments& args) {
|
||||
if (!args.IsConstructCall())
|
||||
return node::FromConstructorTemplate(GetTemplate(), args);
|
||||
|
||||
if (args.Length() < 1)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
if (!args[0]->IsObject())
|
||||
return ThrowError("Object must be an ArrayBuffer.");
|
||||
|
||||
v8::Handle<v8::Object> buffer = v8::Handle<v8::Object>::Cast(args[0]);
|
||||
if (!ArrayBuffer::HasInstance(buffer))
|
||||
return ThrowError("Object must be an ArrayBuffer.");
|
||||
|
||||
unsigned int byte_length =
|
||||
buffer->GetIndexedPropertiesExternalArrayDataLength();
|
||||
unsigned int byte_offset = args[1]->Uint32Value();
|
||||
|
||||
if (args[1]->Int32Value() < 0 || byte_offset >= byte_length)
|
||||
return ThrowRangeError("byteOffset out of range.");
|
||||
|
||||
if (!args[2]->IsUndefined()) {
|
||||
if (args[2]->Int32Value() < 0)
|
||||
return ThrowRangeError("byteLength out of range.");
|
||||
unsigned int new_byte_length = args[2]->Uint32Value();
|
||||
if (new_byte_length > byte_length)
|
||||
return ThrowRangeError("byteLength out of range.");
|
||||
if (byte_offset + new_byte_length > byte_length)
|
||||
return ThrowRangeError("byteOffset/byteLength out of range.");
|
||||
byte_length = new_byte_length;
|
||||
} else {
|
||||
// Adjust the original byte_length from total length to length to end.
|
||||
byte_length -= byte_offset;
|
||||
}
|
||||
|
||||
void* buf = buffer->GetIndexedPropertiesExternalArrayData();
|
||||
|
||||
// Like ArrayBuffer, we violate the spec and add an operator[].
|
||||
args.This()->SetIndexedPropertiesToExternalArrayData(
|
||||
reinterpret_cast<char*>(buf) + byte_offset,
|
||||
v8::kExternalUnsignedByteArray, byte_length);
|
||||
|
||||
args.This()->Set(v8::String::New("buffer"),
|
||||
buffer,
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
args.This()->Set(v8::String::New("byteOffset"),
|
||||
v8::Integer::NewFromUnsigned(byte_offset,
|
||||
node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
args.This()->Set(v8::String::New("byteLength"),
|
||||
v8::Integer::NewFromUnsigned(byte_length,
|
||||
node::node_isolate),
|
||||
(v8::PropertyAttribute)(v8::ReadOnly|v8::DontDelete));
|
||||
return args.This();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static v8::Handle<v8::Value> getGeneric(const v8::Arguments& args) {
|
||||
if (args.Length() < 1)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
unsigned int index = args[0]->Uint32Value();
|
||||
// NOTE(deanm): args[1]->BooleanValue when the argument was not passed in
|
||||
// gives us the right answer, but seems to be very slow. This seems to be
|
||||
// the cost of calling BooleanValue() on undefined.
|
||||
bool little_endian = args.Length() > 1 ? args[1]->BooleanValue() : false;
|
||||
// TODO(deanm): All of these things should be cacheable.
|
||||
int element_size = v8_typed_array::SizeOfArrayElementForType(
|
||||
args.This()->GetIndexedPropertiesExternalArrayDataType());
|
||||
assert(element_size > 0);
|
||||
int size = args.This()->GetIndexedPropertiesExternalArrayDataLength();
|
||||
assert(size >= 0);
|
||||
|
||||
if (static_cast<uint64_t>(index) + sizeof(T) >
|
||||
static_cast<uint64_t>(size) * element_size) {
|
||||
return ThrowError("Index out of range.");
|
||||
}
|
||||
|
||||
void* ptr = reinterpret_cast<char*>(
|
||||
args.This()->GetIndexedPropertiesExternalArrayData()) + index;
|
||||
|
||||
T val;
|
||||
#if V8_TYPED_ARRAY_LITTLE_ENDIAN
|
||||
if (!little_endian) {
|
||||
#else
|
||||
if (little_endian) {
|
||||
#endif
|
||||
val = v8_typed_array::LoadAndSwapBytes<T>(ptr);
|
||||
} else {
|
||||
memcpy(&val, ptr, sizeof(T));
|
||||
}
|
||||
return cTypeToValue<T>(val);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static v8::Handle<v8::Value> setGeneric(const v8::Arguments& args) {
|
||||
if (args.Length() < 2)
|
||||
return ThrowError("Wrong number of arguments.");
|
||||
|
||||
unsigned int index = args[0]->Int32Value();
|
||||
// NOTE(deanm): args[1]->BooleanValue when the argument was not passed in
|
||||
// gives us the right answer, but seems to be very slow. This seems to be
|
||||
// the cost of calling BooleanValue() on undefined.
|
||||
bool little_endian = args.Length() > 2 ? args[2]->BooleanValue() : false;
|
||||
// TODO(deanm): All of these things should be cacheable.
|
||||
int element_size = v8_typed_array::SizeOfArrayElementForType(
|
||||
args.This()->GetIndexedPropertiesExternalArrayDataType());
|
||||
assert(element_size > 0);
|
||||
int size = args.This()->GetIndexedPropertiesExternalArrayDataLength();
|
||||
assert(size >= 0);
|
||||
|
||||
if (static_cast<uint64_t>(index) + sizeof(T) >
|
||||
static_cast<uint64_t>(size) * element_size) {
|
||||
return ThrowError("Index out of range.");
|
||||
}
|
||||
|
||||
void* ptr = reinterpret_cast<char*>(
|
||||
args.This()->GetIndexedPropertiesExternalArrayData()) + index;
|
||||
|
||||
T val = valueToCType<T>(args[1]);
|
||||
#if V8_TYPED_ARRAY_LITTLE_ENDIAN
|
||||
if (!little_endian) {
|
||||
#else
|
||||
if (little_endian) {
|
||||
#endif
|
||||
v8_typed_array::SwapBytesAndStore<T>(ptr, val);
|
||||
} else {
|
||||
memcpy(ptr, &val, sizeof(T));
|
||||
}
|
||||
return v8::Undefined(node::node_isolate);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getUint8(const v8::Arguments& args) {
|
||||
return getGeneric<unsigned char>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getInt8(const v8::Arguments& args) {
|
||||
return getGeneric<signed char>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getUint16(const v8::Arguments& args) {
|
||||
return getGeneric<unsigned short>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getInt16(const v8::Arguments& args) {
|
||||
return getGeneric<short>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getUint32(const v8::Arguments& args) {
|
||||
return getGeneric<unsigned int>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getInt32(const v8::Arguments& args) {
|
||||
return getGeneric<int>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getFloat32(const v8::Arguments& args) {
|
||||
return getGeneric<float>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> getFloat64(const v8::Arguments& args) {
|
||||
return getGeneric<double>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setUint8(const v8::Arguments& args) {
|
||||
return setGeneric<unsigned char>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setInt8(const v8::Arguments& args) {
|
||||
return setGeneric<signed char>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setUint16(const v8::Arguments& args) {
|
||||
return setGeneric<unsigned short>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setInt16(const v8::Arguments& args) {
|
||||
return setGeneric<short>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setUint32(const v8::Arguments& args) {
|
||||
return setGeneric<unsigned int>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setInt32(const v8::Arguments& args) {
|
||||
return setGeneric<int>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setFloat32(const v8::Arguments& args) {
|
||||
return setGeneric<float>(args);
|
||||
}
|
||||
|
||||
static v8::Handle<v8::Value> setFloat64(const v8::Arguments& args) {
|
||||
return setGeneric<double>(args);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace v8_typed_array {
|
||||
|
||||
void AttachBindings(v8::Handle<v8::Object> obj) {
|
||||
v8::HandleScope scope(node::node_isolate);
|
||||
|
||||
obj->Set(v8::String::New("ArrayBuffer"),
|
||||
ArrayBuffer::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Int8Array"),
|
||||
Int8Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Uint8Array"),
|
||||
Uint8Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Uint8ClampedArray"),
|
||||
Uint8ClampedArray::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Int16Array"),
|
||||
Int16Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Uint16Array"),
|
||||
Uint16Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Int32Array"),
|
||||
Int32Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Uint32Array"),
|
||||
Uint32Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Float32Array"),
|
||||
Float32Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("Float64Array"),
|
||||
Float64Array::GetTemplate()->GetFunction());
|
||||
obj->Set(v8::String::New("DataView"),
|
||||
DataView::GetTemplate()->GetFunction());
|
||||
}
|
||||
|
||||
int SizeOfArrayElementForType(v8::ExternalArrayType type) {
|
||||
switch (type) {
|
||||
case v8::kExternalByteArray:
|
||||
case v8::kExternalUnsignedByteArray:
|
||||
case v8::kExternalPixelArray:
|
||||
return 1;
|
||||
case v8::kExternalShortArray:
|
||||
case v8::kExternalUnsignedShortArray:
|
||||
return 2;
|
||||
case v8::kExternalIntArray:
|
||||
case v8::kExternalUnsignedIntArray:
|
||||
case v8::kExternalFloatArray:
|
||||
return 4;
|
||||
case v8::kExternalDoubleArray:
|
||||
return 8;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace v8_typed_array
|
@ -1,35 +0,0 @@
|
||||
// V8 Typed Array implementation.
|
||||
// (c) Dean McNamee <dean@gmail.com>, 2011.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef V8_TYPED_ARRAY_H_
|
||||
#define V8_TYPED_ARRAY_H_
|
||||
|
||||
#include "v8.h"
|
||||
|
||||
namespace v8_typed_array {
|
||||
|
||||
void AttachBindings(v8::Handle<v8::Object> obj);
|
||||
|
||||
int SizeOfArrayElementForType(v8::ExternalArrayType type);
|
||||
|
||||
} // namespace v8_typed_array
|
||||
|
||||
#endif // V8_TYPED_ARRAY_H_
|
@ -1,201 +0,0 @@
|
||||
// V8 Typed Array implementation.
|
||||
// (c) Dean McNamee <dean@gmail.com>, 2012.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
|
||||
#ifndef V8_TYPED_ARRAY_BSWAP_H_
|
||||
#define V8_TYPED_ARRAY_BSWAP_H_
|
||||
|
||||
// Windows will always be little endian (including ARM), so we just need to
|
||||
// worry about gcc.
|
||||
#if defined (__ppc__) || defined (__ppc64__) || defined(__ARMEB__)
|
||||
#define V8_TYPED_ARRAY_BIG_ENDIAN 1
|
||||
#else
|
||||
#define V8_TYPED_ARRAY_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER) && (_MSC_VER < 1600)
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef signed __int16 int16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef signed __int32 int32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef signed __int64 int64_t;
|
||||
// Definitions to avoid ICU redefinition issue
|
||||
#define U_HAVE_INT8_T 1
|
||||
#define U_HAVE_UINT8_T 1
|
||||
#define U_HAVE_INT16_T 1
|
||||
#define U_HAVE_UINT16_T 1
|
||||
#define U_HAVE_INT32_T 1
|
||||
#define U_HAVE_UINT32_T 1
|
||||
#define U_HAVE_INT64_T 1
|
||||
#define U_HAVE_UINT64_T 1
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#if defined (_MSC_VER)
|
||||
#define V8_TYPED_ARRAY_BSWAP16 _byteswap_ushort
|
||||
#define V8_TYPED_ARRAY_BSWAP32 _byteswap_ulong
|
||||
#define V8_TYPED_ARRAY_BSWAP64 _byteswap_uint64
|
||||
#else
|
||||
// On LLVM based compilers we can feature test, but for GCC we unfortunately
|
||||
// have to rely on the version. Additionally __builtin_bswap32/64 were added
|
||||
// in GCC 4.3, but __builtin_bswap16 was not added until GCC 4.8.
|
||||
// We should be able to assume GCC/LLVM here (and can use ULL constants, etc).
|
||||
// Fallback swap macros taken from QEMU bswap.h
|
||||
#ifdef __has_builtin
|
||||
#define V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN(x) __has_builtin(x)
|
||||
#define V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN16(x) __has_builtin(x)
|
||||
#else
|
||||
#define V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN(x) (defined(__GNUC__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)))
|
||||
#define V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN16(x) (defined(__GNUC__) && \
|
||||
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)))
|
||||
#endif
|
||||
|
||||
#if V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN(__builtin_bswap64)
|
||||
#define V8_TYPED_ARRAY_BSWAP64 __builtin_bswap64
|
||||
#else
|
||||
#define V8_TYPED_ARRAY_BSWAP64(x) \
|
||||
({ \
|
||||
uint64_t __x = (x); \
|
||||
((uint64_t)( \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
|
||||
(uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN(__builtin_bswap32)
|
||||
#define V8_TYPED_ARRAY_BSWAP32 __builtin_bswap32
|
||||
#else
|
||||
#define V8_TYPED_ARRAY_BSWAP32(x) \
|
||||
({ \
|
||||
uint32_t __x = (x); \
|
||||
((uint32_t)( \
|
||||
(((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
|
||||
(((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
|
||||
(((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
|
||||
(((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#if V8_TYPED_ARRAY_BSWAP_HAS_BUILTIN16(__builtin_bswap16)
|
||||
#define V8_TYPED_ARRAY_BSWAP16 __builtin_bswap16
|
||||
#else
|
||||
#define V8_TYPED_ARRAY_BSWAP16(x) \
|
||||
({ \
|
||||
uint16_t __x = (x); \
|
||||
((uint16_t)( \
|
||||
(((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
|
||||
(((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
|
||||
})
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
namespace v8_typed_array {
|
||||
|
||||
template <typename T>
|
||||
inline T SwapBytes(T x) {
|
||||
typedef char NoSwapBytesForType[sizeof(T) == 0 ? 1 : -1];
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline signed char SwapBytes(signed char x) { return x; }
|
||||
template <>
|
||||
inline unsigned char SwapBytes(unsigned char x) { return x; }
|
||||
template <>
|
||||
inline uint16_t SwapBytes(uint16_t x) { return V8_TYPED_ARRAY_BSWAP16(x); }
|
||||
template <>
|
||||
inline int16_t SwapBytes(int16_t x) { return V8_TYPED_ARRAY_BSWAP16(x); }
|
||||
template <>
|
||||
inline uint32_t SwapBytes(uint32_t x) { return V8_TYPED_ARRAY_BSWAP32(x); }
|
||||
template <>
|
||||
inline int32_t SwapBytes(int32_t x) { return V8_TYPED_ARRAY_BSWAP32(x); }
|
||||
template <>
|
||||
inline uint64_t SwapBytes(uint64_t x) { return V8_TYPED_ARRAY_BSWAP64(x); }
|
||||
template <>
|
||||
inline int64_t SwapBytes(int64_t x) { return V8_TYPED_ARRAY_BSWAP64(x); }
|
||||
|
||||
template <typename T> // General implementation for all non-FP types.
|
||||
inline T LoadAndSwapBytes(void* ptr) {
|
||||
T val;
|
||||
memcpy(&val, ptr, sizeof(T));
|
||||
return SwapBytes(val);
|
||||
}
|
||||
|
||||
template <>
|
||||
inline float LoadAndSwapBytes<float>(void* ptr) {
|
||||
typedef char VerifySizesAreEqual[sizeof(uint32_t) == sizeof(float) ? 1 : -1];
|
||||
uint32_t swappable;
|
||||
float val;
|
||||
memcpy(&swappable, ptr, sizeof(swappable));
|
||||
swappable = SwapBytes(swappable);
|
||||
memcpy(&val, &swappable, sizeof(swappable));
|
||||
return val;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline double LoadAndSwapBytes<double>(void* ptr) {
|
||||
typedef char VerifySizesAreEqual[sizeof(uint64_t) == sizeof(double) ? 1 : -1];
|
||||
uint64_t swappable;
|
||||
double val;
|
||||
memcpy(&swappable, ptr, sizeof(swappable));
|
||||
swappable = SwapBytes(swappable);
|
||||
memcpy(&val, &swappable, sizeof(swappable));
|
||||
return val;
|
||||
}
|
||||
|
||||
template <typename T> // General implementation for all non-FP types.
|
||||
inline void SwapBytesAndStore(void* ptr, T val) {
|
||||
val = SwapBytes(val);
|
||||
memcpy(ptr, &val, sizeof(T));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void SwapBytesAndStore(void* ptr, float val) {
|
||||
typedef char VerifySizesAreEqual[sizeof(uint32_t) == sizeof(float) ? 1 : -1];
|
||||
uint32_t swappable;
|
||||
memcpy(&swappable, &val, sizeof(swappable));
|
||||
swappable = SwapBytes(swappable);
|
||||
memcpy(ptr, &swappable, sizeof(swappable));
|
||||
}
|
||||
|
||||
template <>
|
||||
inline void SwapBytesAndStore(void* ptr, double val) {
|
||||
typedef char VerifySizesAreEqual[sizeof(uint64_t) == sizeof(double) ? 1 : -1];
|
||||
uint64_t swappable;
|
||||
memcpy(&swappable, &val, sizeof(swappable));
|
||||
swappable = SwapBytes(swappable);
|
||||
memcpy(ptr, &swappable, sizeof(swappable));
|
||||
}
|
||||
|
||||
} // namespace v8_typed_array
|
||||
|
||||
#endif // V8_TYPED_ARRAY_BSWAP_H_
|
Loading…
x
Reference in New Issue
Block a user