Browse Source

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.)
v0.11.4-release
Ben Noordhuis 12 years ago
parent
commit
110a9cd8db
  1. 7
      lib/net.js
  2. 2
      node.gyp
  3. 102
      src/cares_wrap.cc
  4. 63
      src/fs_event_wrap.cc
  5. 52
      src/handle_wrap.cc
  6. 57
      src/handle_wrap.h
  7. 502
      src/node.cc
  8. 57
      src/node.h
  9. 160
      src/node_buffer.cc
  10. 57
      src/node_counters.cc
  11. 910
      src/node_crypto.cc
  12. 193
      src/node_crypto.h
  13. 146
      src/node_dtrace.cc
  14. 214
      src/node_file.cc
  15. 156
      src/node_http_parser.cc
  16. 206
      src/node_internals.h
  17. 75
      src/node_object_wrap.h
  18. 121
      src/node_os.cc
  19. 239
      src/node_script.cc
  20. 47
      src/node_stat_watcher.cc
  21. 6
      src/node_stat_watcher.h
  22. 6
      src/node_wrap.h
  23. 62
      src/node_zlib.cc
  24. 64
      src/pipe_wrap.cc
  25. 13
      src/pipe_wrap.h
  26. 49
      src/process_wrap.cc
  27. 24
      src/req_wrap.h
  28. 28
      src/signal_wrap.cc
  29. 68
      src/smalloc.cc
  30. 130
      src/stream_wrap.cc
  31. 22
      src/stream_wrap.h
  32. 130
      src/tcp_wrap.cc
  33. 25
      src/tcp_wrap.h
  34. 58
      src/timer_wrap.cc
  35. 353
      src/tls_wrap.cc
  36. 43
      src/tls_wrap.h
  37. 77
      src/tty_wrap.cc
  38. 23
      src/tty_wrap.h
  39. 150
      src/udp_wrap.cc
  40. 43
      src/udp_wrap.h
  41. 874
      src/v8_typed_array.cc
  42. 35
      src/v8_typed_array.h
  43. 201
      src/v8_typed_array_bswap.h

7
lib/net.js

@ -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

@ -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

102
src/cares_wrap.cc

@ -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));
}
if (uv_inet_pton(AF_INET6, *ip, &address_buffer).code == UV_OK) {
return scope.Close(v8::Integer::New(6, 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;
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");
}

63
src/fs_event_wrap.cc

@ -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);
}

52
src/handle_wrap.cc

@ -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;
}

57
src/handle_wrap.h

@ -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);
inline uv_handle_t* GetHandle() { return handle__; };
protected:
HandleWrap(v8::Handle<v8::Object> object, uv_handle_t* handle);
virtual ~HandleWrap();
v8::Persistent<v8::Object> object_;
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_;
static const unsigned int kUnref = 1;
static const unsigned int kCloseCallback = 2;
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__; };
protected:
HandleWrap(v8::Handle<v8::Object> object, uv_handle_t* handle);
virtual ~HandleWrap();
inline v8::Local<v8::Object> object() {
return v8::Local<v8::Object>::New(node_isolate, persistent());
}
inline v8::Persistent<v8::Object>& persistent() {
return object_;
}
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

File diff suppressed because it is too large

57
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());
}
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);
#define NODE_SET_METHOD node::NODE_SET_METHOD
// 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 = "",

160
src/node_buffer.cc

@ -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);
}

57
src/node_counters.cc

@ -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

910
src/node_crypto.cc

File diff suppressed because it is too large

193
src/node_crypto.h

@ -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) {
}

146
src/node_dtrace.cc

@ -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

214
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");
}
Local<Object> stats =
stats_constructor_template->GetFunction()->NewInstance();
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<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);
}

156
src/node_http_parser.cc

@ -47,26 +47,37 @@
namespace node {
using namespace v8;
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 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 Persistent<String> unknown_method_sym;
#define X(num, name, string) static Persistent<String> name##_sym;
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 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 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 Cached<String> unknown_method_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");
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");
unknown_method_sym = String::New("UNKNOWN_METHOD");
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;

206
src/node_internals.h

@ -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_

75
src/node_object_wrap.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());
}
inline v8::Local<v8::Object> handle(v8::Isolate* isolate) {
return v8::Local<v8::Object>::New(isolate, persistent());
}
protected:
inline void Wrap (v8::Handle<v8::Object> handle) {
assert(handle_.IsEmpty());
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

121
src/node_os.cc

@ -46,81 +46,95 @@
namespace node {
using namespace v8;
static Handle<Value> GetEndianness(const Arguments& args) {
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 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);
}

239
src/node_script.cc

@ -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};
// 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_);
}
cloneObjectMethod->Call(recv, 2, args);
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";
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"));
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)

47
src/node_stat_watcher.cc

@ -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);
}

6
src/node_stat_watcher.h

@ -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,

6
src/node_wrap.h

@ -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 \
} \

62
src/node_zlib.cc

@ -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);

64
src/pipe_wrap.cc

@ -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());
}

13
src/pipe_wrap.h

@ -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);

49
src/process_wrap.cc

@ -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_;

24
src/req_wrap.h

@ -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_;

28
src/signal_wrap.cc

@ -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_;

68
src/smalloc.cc

@ -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);
}

130
src/stream_wrap.cc

@ -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();
}
}

22
src/stream_wrap.h

@ -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

@ -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();

25
src/tcp_wrap.h

@ -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);

58
src/timer_wrap.cc

@ -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_;

353
src/tls_wrap.cc

@ -28,28 +28,39 @@
namespace node {
using namespace v8;
using crypto::SecureContext;
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;
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 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);
// Get callback init args
Local<Value> argv[1] = {*p->servername_};
Local<Object> object = p->object();
if (object->Has(onsniselect_sym)) {
p->sni_context_.Dispose();
// 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());
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");
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");
tlsWrap.Reset(node_isolate, t->GetFunction());
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 = 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

43
src/tls_wrap.h

@ -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_;

77
src/tty_wrap.cc

@ -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());
}

23
src/tty_wrap.h

@ -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

@ -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);
}

43
src/udp_wrap.h

@ -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);

874
src/v8_typed_array.cc

@ -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

35
src/v8_typed_array.h

@ -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_

201
src/v8_typed_array_bswap.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…
Cancel
Save