@@ -22,38 +22,39 @@
#ifndef SRC_NODE_WRAP_H_
#define SRC_NODE_WRAP_H_

#include "v8.h"
#include "uv.h"

#include "env.h"
#include "env-inl.h"
#include "pipe_wrap.h"
#include "tty_wrap.h"
#include "tcp_wrap.h"
#include "tty_wrap.h"
#include "udp_wrap.h"
#include "uv.h"
#include "v8.h"

namespace node {

extern v8::Persistent<v8::FunctionTemplate> pipeConstructorTmpl;
extern v8::Persistent<v8::FunctionTemplate> ttyConstructorTmpl;
extern v8::Persistent<v8::FunctionTemplate> tcpConstructorTmpl;

#define WITH_GENERIC_STREAM(obj, BODY) \
do { \
if (HasInstance(tcpConstructorTmpl, obj)) { \
TCPWrap* const wrap = TCPWrap::Unwrap(obj); \
BODY \
} else if (HasInstance(ttyConstructorTmpl, obj)) { \
TTYWrap* const wrap = TTYWrap::Unwrap(obj); \
BODY \
} else if (HasInstance(pipeConstructorTmpl, obj)) { \
PipeWrap* const wrap = PipeWrap::Unwrap(obj); \
BODY \
} \
#define WITH_GENERIC_STREAM(env, obj, BODY) \
do { \
if (env->tcp_constructor_template().IsEmpty() == false && \
env->tcp_constructor_template()->HasInstance(obj)) { \
TCPWrap* const wrap = TCPWrap::Unwrap(obj); \
BODY \
} else if (env->tty_constructor_template().IsEmpty() == false && \
env->tty_constructor_template()->HasInstance(obj)) { \
TTYWrap* const wrap = TTYWrap::Unwrap(obj); \
BODY \
} else if (env->pipe_constructor_template().IsEmpty() == false && \
env->pipe_constructor_template()->HasInstance(obj)) { \
PipeWrap* const wrap = PipeWrap::Unwrap(obj); \
BODY \
} \
} while (0)

inline uv_stream_t* HandleToStream(v8::Local<v8::Object> obj) {
inline uv_stream_t* HandleToStream(Environment* env,
v8::Local<v8::Object> obj) {
v8::HandleScope scope(node_isolate);

WITH_GENERIC_STREAM(obj, {
WITH_GENERIC_STREAM(env, obj, {
return reinterpret_cast<uv_stream_t*>(wrap->UVHandle());
});

@@ -21,6 +21,9 @@

#include "node.h"
#include "node_buffer.h"

#include "env.h"
#include "env-inl.h"
#include "v8.h"
#include "zlib.h"

@@ -31,6 +34,7 @@

namespace node {

using v8::Context;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Handle;
@@ -42,9 +46,6 @@ using v8::Object;
using v8::String;
using v8::Value;

static Cached<String> callback_sym;
static Cached<String> onerror_sym;

enum node_zlib_mode {
NONE,
DEFLATE,
@@ -66,19 +67,21 @@ void InitZlib(v8::Handle<v8::Object> target);
class ZCtx : public ObjectWrap {
public:

explicit ZCtx(node_zlib_mode mode) : ObjectWrap(),
init_done_(false),
level_(0),
windowBits_(0),
memLevel_(0),
strategy_(0),
err_(0),
dictionary_(NULL),
dictionary_len_(0),
flush_(0),
chunk_size_(0),
write_in_progress_(false),
mode_(mode) {
ZCtx(Environment* env, node_zlib_mode mode)
: ObjectWrap()
, chunk_size_(0)
, dictionary_(NULL)
, dictionary_len_(0)
, env_(env)
, err_(0)
, flush_(0)
, init_done_(false)
, level_(0)
, memLevel_(0)
, mode_(mode)
, strategy_(0)
, windowBits_(0)
, write_in_progress_(false) {
}


@@ -87,6 +90,10 @@ class ZCtx : public ObjectWrap {
}


inline Environment* env() const {
return env_;
}

void Close() {
assert(!write_in_progress_ && "write in progress");
assert(init_done_ && "close before init");
@@ -182,7 +189,7 @@ class ZCtx : public ObjectWrap {
// set this so that later on, I can easily tell how much was written.
ctx->chunk_size_ = out_len;

uv_queue_work(uv_default_loop(),
uv_queue_work(ctx->env()->event_loop(),
work_req,
ZCtx::Process,
ZCtx::After);
@@ -245,8 +252,11 @@ class ZCtx : public ObjectWrap {
static void After(uv_work_t* work_req, int status) {
assert(status == 0);

HandleScope scope(node_isolate);
ZCtx *ctx = container_of(work_req, ZCtx, work_req_);
ZCtx* ctx = container_of(work_req, ZCtx, work_req_);
Environment* env = ctx->env();

Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// Acceptable error states depend on the type of zlib stream.
switch (ctx->err_) {
@@ -275,37 +285,39 @@ class ZCtx : public ObjectWrap {

// call the write() cb
Local<Object> handle = ctx->handle(node_isolate);
assert(handle->Get(callback_sym)->IsFunction() && "Invalid callback");
Local<Value> args[2] = { avail_in, avail_out };
MakeCallback(handle, callback_sym, ARRAY_SIZE(args), args);
MakeCallback(env, handle, env->callback_string(), ARRAY_SIZE(args), args);

ctx->Unref();
}

static void Error(ZCtx *ctx, const char *msg_) {
const char *msg;
static void Error(ZCtx* ctx, const char* message) {
Environment* env = ctx->env();

// If you hit this assertion, you forgot to enter the v8::Context first.
assert(env->context() == env->isolate()->GetCurrentContext());

if (ctx->strm_.msg != NULL) {
msg = ctx->strm_.msg;
} else {
msg = msg_;
message = ctx->strm_.msg;
}

Local<Object> handle = ctx->handle(node_isolate);
assert(handle->Get(onerror_sym)->IsFunction() && "Invalid error handler");
HandleScope scope(node_isolate);
Local<Value> args[2] = {
OneByteString(node_isolate, msg),
OneByteString(node_isolate, message),
Number::New(ctx->err_)
};
MakeCallback(handle, onerror_sym, ARRAY_SIZE(args), args);
MakeCallback(env, handle, env->onerror_string(), ARRAY_SIZE(args), args);

// no hope of rescue.
ctx->write_in_progress_ = false;
ctx->Unref();
}

static void New(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

if (args.Length() < 1 || !args[0]->IsInt32()) {
return ThrowTypeError("Bad argument");
}
@@ -315,7 +327,7 @@ class ZCtx : public ObjectWrap {
return ThrowTypeError("Bad argument");
}

ZCtx *ctx = new ZCtx(mode);
ZCtx* ctx = new ZCtx(env, mode);
ctx->Wrap(args.This());
}

@@ -506,33 +518,27 @@ class ZCtx : public ObjectWrap {
static const int kDeflateContextSize = 16384; // approximate
static const int kInflateContextSize = 10240; // approximate

int chunk_size_;
Bytef* dictionary_;
size_t dictionary_len_;
Environment* const env_;
int err_;
int flush_;
bool init_done_;

z_stream strm_;
int level_;
int windowBits_;
int memLevel_;
node_zlib_mode mode_;
int strategy_;

int err_;

Bytef* dictionary_;
size_t dictionary_len_;

int flush_;

int chunk_size_;

bool write_in_progress_;

z_stream strm_;
int windowBits_;
uv_work_t work_req_;
node_zlib_mode mode_;
bool write_in_progress_;
};


void InitZlib(Handle<Object> target) {
HandleScope scope(node_isolate);

void InitZlib(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Local<FunctionTemplate> z = FunctionTemplate::New(ZCtx::New);

z->InstanceTemplate()->SetInternalFieldCount(1);
@@ -546,9 +552,6 @@ void InitZlib(Handle<Object> target) {
z->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Zlib"));
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Zlib"), z->GetFunction());

callback_sym = FIXED_ONE_BYTE_STRING(node_isolate, "callback");
onerror_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onerror");

// valid flush values.
NODE_DEFINE_CONSTANT(target, Z_NO_FLUSH);
NODE_DEFINE_CONSTANT(target, Z_PARTIAL_FLUSH);
@@ -593,4 +596,4 @@ void InitZlib(Handle<Object> target) {

} // namespace node

NODE_MODULE(node_zlib, node::InitZlib)
NODE_MODULE_CONTEXT_AWARE(node_zlib, node::InitZlib)
@@ -20,16 +20,22 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "pipe_wrap.h"

#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
#include "node.h"
#include "node_buffer.h"
#include "handle_wrap.h"
#include "node_wrap.h"
#include "req_wrap.h"
#include "stream_wrap.h"
#include "util-inl.h"
#include "util.h"

namespace node {

using v8::Boolean;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -38,17 +44,11 @@ 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;

static Persistent<Function> pipeConstructor;
static Cached<String> onconnection_sym;
static Cached<String> oncomplete_sym;


// TODO(bnoordhuis) share with TCPWrap?
typedef class ReqWrap<uv_connect_t> ConnectWrap;

@@ -58,10 +58,14 @@ uv_pipe_t* PipeWrap::UVHandle() {
}


Local<Object> PipeWrap::Instantiate() {
HandleScope scope(node_isolate);
assert(!pipeConstructor.IsEmpty());
return scope.Close(NewInstance(pipeConstructor));
Local<Object> PipeWrap::Instantiate(Environment* env) {
HandleScope handle_scope(env->isolate());
assert(!env->pipe_constructor_template().IsEmpty());
Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
assert(!constructor.IsEmpty());
Local<Object> instance = constructor->NewInstance();
assert(!instance.IsEmpty());
return handle_scope.Close(instance);
}


@@ -72,14 +76,13 @@ PipeWrap* PipeWrap::Unwrap(Local<Object> obj) {
}


void PipeWrap::Initialize(Handle<Object> target) {
StreamWrap::Initialize(target);

HandleScope scope(node_isolate);
void PipeWrap::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Pipe"));

t->InstanceTemplate()->SetInternalFieldCount(1);

enum PropertyAttribute attributes =
@@ -115,9 +118,8 @@ void PipeWrap::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "setPendingInstances", SetPendingInstances);
#endif

pipeConstructorTmpl.Reset(node_isolate, t);
pipeConstructor.Reset(node_isolate, t->GetFunction());
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Pipe"), t->GetFunction());
env->set_pipe_constructor_template(t);
}


@@ -126,16 +128,15 @@ void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {
// Therefore we assert that we are not trying to call this as a
// normal function.
assert(args.IsConstructCall());

HandleScope scope(node_isolate);
PipeWrap* wrap = new PipeWrap(args.This(), args[0]->IsTrue());
assert(wrap);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
new PipeWrap(env, args.This(), args[0]->IsTrue());
}


PipeWrap::PipeWrap(Handle<Object> object, bool ipc)
: StreamWrap(object, reinterpret_cast<uv_stream_t*>(&handle_)) {
int r = uv_pipe_init(uv_default_loop(), &handle_, ipc);
PipeWrap::PipeWrap(Environment* env, Handle<Object> object, bool ipc)
: StreamWrap(env, object, reinterpret_cast<uv_stream_t*>(&handle_)) {
int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
assert(r == 0); // How do we proxy this error up to javascript?
// Suggestion: uv_pipe_init() returns void.
UpdateWriteQueueSize();
@@ -184,11 +185,13 @@ void PipeWrap::Listen(const FunctionCallbackInfo<Value>& args) {

// TODO(bnoordhuis) maybe share with TCPWrap?
void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
HandleScope scope(node_isolate);

PipeWrap* pipe_wrap = static_cast<PipeWrap*>(handle->data);
assert(&pipe_wrap->handle_ == reinterpret_cast<uv_pipe_t*>(handle));

Environment* env = pipe_wrap->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// We should not be getting this callback if someone as already called
// uv_close() on the handle.
assert(pipe_wrap->persistent().IsEmpty() == false);
@@ -199,12 +202,17 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {
};

if (status != 0) {
MakeCallback(pipe_wrap->object(), "onconnection", ARRAY_SIZE(argv), argv);
MakeCallback(env,
pipe_wrap->object(),
env->onconnection_string(),
ARRAY_SIZE(argv),
argv);
return;
}

// Instanciate the client javascript object and handle.
Local<Object> client_obj = NewInstance(pipeConstructor);
Local<Object> client_obj =
env->pipe_constructor_template()->GetFunction()->NewInstance();

// Unwrap the client javascript object.
PipeWrap* wrap;
@@ -215,18 +223,22 @@ void PipeWrap::OnConnection(uv_stream_t* handle, int status) {

// Successful accept. Call the onconnection callback in JavaScript land.
argv[1] = client_obj;
if (onconnection_sym.IsEmpty()) {
onconnection_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onconnection");
}
MakeCallback(pipe_wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
pipe_wrap->object(),
env->onconnection_string(),
ARRAY_SIZE(argv),
argv);
}

// TODO(bnoordhuis) Maybe share this with TCPWrap?
void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
ConnectWrap* req_wrap = static_cast<ConnectWrap*>(req->data);
PipeWrap* wrap = static_cast<PipeWrap*>(req->handle->data);
assert(req_wrap->env() == wrap->env());
Environment* env = wrap->env();

HandleScope scope(node_isolate);
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// The wrap and request objects should still be there.
assert(req_wrap->persistent().IsEmpty() == false);
@@ -250,10 +262,11 @@ void PipeWrap::AfterConnect(uv_connect_t* req, int status) {
Boolean::New(writable)
};

if (oncomplete_sym.IsEmpty()) {
oncomplete_sym = FIXED_ONE_BYTE_STRING(node_isolate, "oncomplete");
}
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
req_wrap_obj,
env->oncomplete_string(),
ARRAY_SIZE(argv),
argv);

delete req_wrap;
}
@@ -272,7 +285,8 @@ void PipeWrap::Open(const FunctionCallbackInfo<Value>& args) {


void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope scope(args.GetIsolate());

PipeWrap* wrap;
NODE_UNWRAP(args.This(), PipeWrap, wrap);
@@ -283,7 +297,7 @@ void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {
Local<Object> req_wrap_obj = args[0].As<Object>();
String::AsciiValue name(args[1]);

ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj);
uv_pipe_connect(&req_wrap->req_,
&wrap->handle_,
*name,
@@ -296,4 +310,4 @@ void PipeWrap::Connect(const FunctionCallbackInfo<Value>& args) {

} // namespace node

NODE_MODULE(node_pipe_wrap, node::PipeWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_pipe_wrap, node::PipeWrap::Initialize)
@@ -21,6 +21,8 @@

#ifndef SRC_PIPE_WRAP_H_
#define SRC_PIPE_WRAP_H_

#include "env.h"
#include "stream_wrap.h"

namespace node {
@@ -29,12 +31,14 @@ class PipeWrap : public StreamWrap {
public:
uv_pipe_t* UVHandle();

static v8::Local<v8::Object> Instantiate();
static v8::Local<v8::Object> Instantiate(Environment* env);
static PipeWrap* Unwrap(v8::Local<v8::Object> obj);
static void Initialize(v8::Handle<v8::Object> target);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);

private:
PipeWrap(v8::Handle<v8::Object> object, bool ipc);
PipeWrap(Environment* env, v8::Handle<v8::Object> object, bool ipc);

static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -19,7 +19,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "node.h"
#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
#include "node_wrap.h"

@@ -29,6 +30,7 @@
namespace node {

using v8::Array;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -41,13 +43,11 @@ using v8::Object;
using v8::String;
using v8::Value;

static Cached<String> onexit_sym;

class ProcessWrap : public HandleWrap {
public:
static void Initialize(Handle<Object> target) {
HandleScope scope(node_isolate);

static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Local<FunctionTemplate> constructor = FunctionTemplate::New(New);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Process"));
@@ -70,22 +70,25 @@ class ProcessWrap : public HandleWrap {
// Therefore we assert that we are not trying to call this as a
// normal function.
assert(args.IsConstructCall());
HandleScope scope(node_isolate);
new ProcessWrap(args.This());
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
new ProcessWrap(env, args.This());
}

explicit ProcessWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&process_)) {
ProcessWrap(Environment* env, Handle<Object> object)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&process_)) {
}

~ProcessWrap() {
}

static void ParseStdioOptions(Local<Object> js_options,
static void ParseStdioOptions(Environment* env,
Local<Object> js_options,
uv_process_options_t* options) {
Local<String> stdio_key =
FIXED_ONE_BYTE_STRING(node_isolate, "stdio");
Local<Array> stdios = js_options->Get(stdio_key).As<Array>();

uint32_t len = stdios->Length();
options->stdio = new uv_stdio_container_t[len];
options->stdio_count = len;
@@ -110,23 +113,23 @@ class ProcessWrap : public HandleWrap {
Local<String> handle_key =
FIXED_ONE_BYTE_STRING(node_isolate, "handle");
Local<Object> handle = stdio->Get(handle_key).As<Object>();
uv_stream_t* stream = HandleToStream(handle);
uv_stream_t* stream = HandleToStream(env, handle);
assert(stream != NULL);

options->stdio[i].flags = UV_INHERIT_STREAM;
options->stdio[i].data.stream = stream;
} else {
Local<String> fd_key = FIXED_ONE_BYTE_STRING(node_isolate, "fd");
int fd = static_cast<int>(stdio->Get(fd_key)->IntegerValue());

options->stdio[i].flags = UV_INHERIT_FD;
options->stdio[i].data.fd = fd;
}
}
}

static void Spawn(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

ProcessWrap* wrap;
NODE_UNWRAP(args.This(), ProcessWrap, wrap);
@@ -216,7 +219,7 @@ class ProcessWrap : public HandleWrap {
}

// options.stdio
ParseStdioOptions(js_options, &options);
ParseStdioOptions(env, js_options, &options);

// options.windows_verbatim_arguments
Local<String> windows_verbatim_arguments_key =
@@ -232,7 +235,7 @@ class ProcessWrap : public HandleWrap {
options.flags |= UV_PROCESS_DETACHED;
}

int err = uv_spawn(uv_default_loop(), &wrap->process_, &options);
int err = uv_spawn(env->event_loop(), &wrap->process_, &options);

if (err == 0) {
assert(wrap->process_.data == wrap);
@@ -268,22 +271,24 @@ class ProcessWrap : public HandleWrap {
static void OnExit(uv_process_t* handle,
int64_t exit_status,
int term_signal) {
HandleScope scope(node_isolate);

ProcessWrap* wrap = static_cast<ProcessWrap*>(handle->data);
assert(wrap);
assert(wrap != NULL);
assert(&wrap->process_ == handle);

Environment* env = wrap->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

Local<Value> argv[] = {
Number::New(node_isolate, static_cast<double>(exit_status)),
OneByteString(node_isolate, signo_string(term_signal))
};

if (onexit_sym.IsEmpty()) {
onexit_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onexit");
}

MakeCallback(wrap->object(), onexit_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
wrap->object(),
env->onexit_string(),
ARRAY_SIZE(argv),
argv);
}

uv_process_t process_;
@@ -292,4 +297,4 @@ class ProcessWrap : public HandleWrap {

} // namespace node

NODE_MODULE(node_process_wrap, node::ProcessWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_process_wrap, node::ProcessWrap::Initialize)
@@ -22,29 +22,31 @@
#ifndef SRC_REQ_WRAP_H_
#define SRC_REQ_WRAP_H_

#include "node.h"
#include "node_internals.h"
#include "env.h"
#include "env-inl.h"
#include "queue.h"
#include "util.h"

namespace node {

// defined in node.cc
extern Cached<v8::String> process_symbol;
extern Cached<v8::String> domain_symbol;
extern QUEUE req_wrap_queue;

template <typename T>
class ReqWrap {
public:
ReqWrap(v8::Handle<v8::Object> object = v8::Handle<v8::Object>()) {
v8::HandleScope scope(node_isolate);
if (object.IsEmpty()) object = v8::Object::New();
persistent().Reset(node_isolate, object);

if (InDomain()) {
v8::Local<v8::Value> domain = GetDomain();
if (domain->IsObject())
object->Set(domain_symbol, domain);
ReqWrap(Environment* env,
v8::Handle<v8::Object> object = v8::Handle<v8::Object>())
: env_(env) {
v8::HandleScope handle_scope(env->isolate());

if (object.IsEmpty()) {
object = v8::Object::New();
}
persistent().Reset(env->isolate(), object);

if (env->in_domain()) {
object->Set(env->domain_string(), env->domain_array()->Get(0));
}

QUEUE_INSERT_TAIL(&req_wrap_queue, &req_wrap_queue_);
@@ -64,17 +66,25 @@ class ReqWrap {
req_.data = this;
}

inline Environment* env() const {
return env_;
}

inline v8::Local<v8::Object> object() {
return PersistentToLocal(node_isolate, persistent());
return PersistentToLocal(env()->isolate(), persistent());
}

inline v8::Persistent<v8::Object>& persistent() {
return object_;
}

v8::Persistent<v8::Object> object_;
// TODO(bnoordhuis) Make these private.
QUEUE req_wrap_queue_;
T req_; // *must* be last, GetActiveRequests() in node.cc depends on it

private:
v8::Persistent<v8::Object> object_;
Environment* const env_;
};


@@ -19,12 +19,14 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "node.h"
#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"

#include "v8.h"

namespace node {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -33,17 +35,13 @@ using v8::HandleScope;
using v8::Integer;
using v8::Local;
using v8::Object;
using v8::String;
using v8::Value;

static Cached<String> onsignal_sym;


class SignalWrap : public HandleWrap {
public:
static void Initialize(Handle<Object> target) {
HandleScope scope(node_isolate);

static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Local<FunctionTemplate> constructor = FunctionTemplate::New(New);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Signal"));
@@ -54,8 +52,6 @@ class SignalWrap : public HandleWrap {
NODE_SET_PROTOTYPE_METHOD(constructor, "start", Start);
NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop);

onsignal_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onsignal");

target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "Signal"),
constructor->GetFunction());
}
@@ -66,14 +62,14 @@ class SignalWrap : public HandleWrap {
// Therefore we assert that we are not trying to call this as a
// normal function.
assert(args.IsConstructCall());

HandleScope scope(node_isolate);
new SignalWrap(args.This());
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
new SignalWrap(env, args.This());
}

explicit SignalWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_signal_init(uv_default_loop(), &handle_);
SignalWrap(Environment* env, Handle<Object> object)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_signal_init(env->event_loop(), &handle_);
assert(r == 0);
}

@@ -100,13 +96,12 @@ class SignalWrap : public HandleWrap {
}

static void OnSignal(uv_signal_t* handle, int signum) {
HandleScope scope(node_isolate);

SignalWrap* wrap = container_of(handle, SignalWrap, handle_);
assert(wrap);

Local<Value> argv[1] = { Integer::New(signum, node_isolate) };
MakeCallback(wrap->object(), onsignal_sym, ARRAY_SIZE(argv), argv);
Environment* env = wrap->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());
Local<Value> arg = Integer::New(signum, env->isolate());
MakeCallback(env, wrap->object(), env->onsignal_string(), 1, &arg);
}

uv_signal_t handle_;
@@ -116,4 +111,4 @@ class SignalWrap : public HandleWrap {
} // namespace node


NODE_MODULE(node_signal_wrap, node::SignalWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_signal_wrap, node::SignalWrap::Initialize)
@@ -20,11 +20,12 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "smalloc.h"
#include "node.h"
#include "node_internals.h"

#include "v8.h"
#include "env.h"
#include "env-inl.h"
#include "node_internals.h"
#include "v8-profiler.h"
#include "v8.h"

#include <string.h>
#include <assert.h>
@@ -34,6 +35,7 @@
namespace node {
namespace smalloc {

using v8::Context;
using v8::External;
using v8::ExternalArrayType;
using v8::FunctionCallbackInfo;
@@ -45,7 +47,6 @@ using v8::Local;
using v8::Object;
using v8::Persistent;
using v8::RetainedObjectInfo;
using v8::String;
using v8::Uint32;
using v8::Value;
using v8::kExternalUnsignedByteArray;
@@ -64,9 +65,6 @@ void TargetFreeCallback(Isolate* isolate,
Persistent<Object>* target,
CallbackInfo* arg);

Cached<String> smalloc_sym;
static bool using_alloc_cb;


// return size of external array type, or 0 if unrecognized
size_t ExternalArraySize(enum ExternalArrayType type) {
@@ -299,10 +297,11 @@ void AllocDispose(const FunctionCallbackInfo<Value>& args) {


void AllocDispose(Handle<Object> obj) {
HandleScope handle_scope(node_isolate);
Environment* env = Environment::GetCurrent(node_isolate);
HandleScope handle_scope(env->isolate());

if (using_alloc_cb) {
Local<Value> ext_v = obj->GetHiddenValue(smalloc_sym);
if (env->using_smalloc_alloc_cb()) {
Local<Value> ext_v = obj->GetHiddenValue(env->smalloc_p_string());
if (ext_v->IsExternal()) {
Local<External> ext = ext_v.As<External>();
CallbackInfo* cb_info = static_cast<CallbackInfo*>(ext->Value());
@@ -361,16 +360,14 @@ void Alloc(Handle<Object> obj,
enum ExternalArrayType type) {
assert(!obj->HasIndexedPropertiesInExternalArrayData());

if (smalloc_sym.IsEmpty()) {
smalloc_sym = FIXED_ONE_BYTE_STRING(node_isolate, "_smalloc_p");
using_alloc_cb = true;
}
Environment* env = Environment::GetCurrent(node_isolate);
env->set_using_smalloc_alloc_cb(true);

CallbackInfo* cb_info = new CallbackInfo;
cb_info->cb = fn;
cb_info->hint = hint;
cb_info->p_obj.Reset(node_isolate, obj);
obj->SetHiddenValue(smalloc_sym, External::New(cb_info));
obj->SetHiddenValue(env->smalloc_p_string(), External::New(cb_info));

node_isolate->AdjustAmountOfExternalAllocatedMemory(length +
sizeof(*cb_info));
@@ -462,26 +459,26 @@ RetainedObjectInfo* WrapperInfo(uint16_t class_id, Handle<Value> wrapper) {
}


void Initialize(Handle<Object> exports) {
void Initialize(Handle<Object> exports,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

NODE_SET_METHOD(exports, "copyOnto", CopyOnto);
NODE_SET_METHOD(exports, "sliceOnto", SliceOnto);

NODE_SET_METHOD(exports, "alloc", Alloc);
NODE_SET_METHOD(exports, "dispose", AllocDispose);

exports->Set(FIXED_ONE_BYTE_STRING(node_isolate, "kMaxLength"),
Uint32::NewFromUnsigned(kMaxLength, node_isolate));

// for performance, begin checking if allocation object may contain
// callbacks if at least one has been set.
using_alloc_cb = false;
Uint32::NewFromUnsigned(kMaxLength, env->isolate()));

HeapProfiler* heap_profiler = node_isolate->GetHeapProfiler();
HeapProfiler* heap_profiler = env->isolate()->GetHeapProfiler();
heap_profiler->SetWrapperClassInfoProvider(ALLOC_ID, WrapperInfo);
}


} // namespace smalloc
} // namespace node

NODE_MODULE(node_smalloc, node::smalloc::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_smalloc, node::smalloc::Initialize)
@@ -20,10 +20,11 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "stream_wrap.h"
#include "node.h"
#include "env-inl.h"
#include "env.h"
#include "handle_wrap.h"
#include "node_buffer.h"
#include "node_counters.h"
#include "handle_wrap.h"
#include "pipe_wrap.h"
#include "req_wrap.h"
#include "tcp_wrap.h"
@@ -36,6 +37,7 @@
namespace node {

using v8::Array;
using v8::Context;
using v8::FunctionCallbackInfo;
using v8::Handle;
using v8::HandleScope;
@@ -49,31 +51,13 @@ using v8::Undefined;
using v8::Value;


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;


void StreamWrap::Initialize(Handle<Object> target) {
if (initialized) return;
initialized = true;

HandleScope scope(node_isolate);
bytes_sym = FIXED_ONE_BYTE_STRING(node_isolate, "bytes");
write_queue_size_sym = FIXED_ONE_BYTE_STRING(node_isolate, "writeQueueSize");
onread_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onread");
oncomplete_sym = FIXED_ONE_BYTE_STRING(node_isolate, "oncomplete");
}


StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(stream)),
stream_(stream),
default_callbacks_(this),
callbacks_(&default_callbacks_) {
StreamWrap::StreamWrap(Environment* env,
Local<Object> object,
uv_stream_t* stream)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(stream))
, stream_(stream)
, default_callbacks_(this)
, callbacks_(&default_callbacks_) {
}


@@ -95,7 +79,7 @@ void StreamWrap::UpdateWriteQueueSize() {
HandleScope scope(node_isolate);
Local<Integer> write_queue_size =
Integer::NewFromUnsigned(stream()->write_queue_size, node_isolate);
object()->Set(write_queue_size_sym, write_queue_size);
object()->Set(env()->write_queue_size_string(), write_queue_size);
}


@@ -137,12 +121,12 @@ void StreamWrap::OnAlloc(uv_handle_t* handle,


template <class WrapType, class UVType>
static Local<Object> AcceptHandle(uv_stream_t* pipe) {
static Local<Object> AcceptHandle(Environment* env, uv_stream_t* pipe) {
HandleScope scope(node_isolate);
Local<Object> wrap_obj;
UVType* handle;

wrap_obj = WrapType::Instantiate();
wrap_obj = WrapType::Instantiate(env);
if (wrap_obj.IsEmpty())
return Local<Object>();

@@ -208,7 +192,8 @@ size_t StreamWrap::WriteBuffer(Handle<Value> val, uv_buf_t* buf) {


void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

StreamWrap* wrap;
NODE_UNWRAP(args.This(), StreamWrap, wrap);
@@ -221,7 +206,8 @@ void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {

size_t length = Buffer::Length(buf_obj);
char* storage = new char[sizeof(WriteWrap)];
WriteWrap* req_wrap = new(storage) WriteWrap(req_wrap_obj, wrap);
WriteWrap* req_wrap =
new(storage) WriteWrap(env, req_wrap_obj, wrap);

uv_buf_t buf;
WriteBuffer(buf_obj, &buf);
@@ -232,7 +218,8 @@ void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {
NULL,
StreamWrap::AfterWrite);
req_wrap->Dispatched();
req_wrap_obj->Set(bytes_sym, Integer::NewFromUnsigned(length, node_isolate));
req_wrap_obj->Set(env->bytes_string(),
Integer::NewFromUnsigned(length, node_isolate));

if (err) {
req_wrap->~WriteWrap();
@@ -245,7 +232,8 @@ void StreamWrap::WriteBuffer(const FunctionCallbackInfo<Value>& args) {

template <enum encoding encoding>
void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
int err;

StreamWrap* wrap;
@@ -272,7 +260,8 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
}

char* storage = new char[sizeof(WriteWrap) + storage_size + 15];
WriteWrap* req_wrap = new(storage) WriteWrap(req_wrap_obj, wrap);
WriteWrap* req_wrap =
new(storage) WriteWrap(env, req_wrap_obj, wrap);

char* data = reinterpret_cast<char*>(ROUND_UP(
reinterpret_cast<uintptr_t>(storage) + sizeof(WriteWrap), 16));
@@ -301,14 +290,10 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
HandleWrap* wrap;
NODE_UNWRAP(send_handle_obj, HandleWrap, wrap);
send_handle = wrap->GetHandle();

// Reference StreamWrap instance to prevent it from being garbage
// collected before `AfterWrite` is called.
if (handle_sym.IsEmpty()) {
handle_sym = FIXED_ONE_BYTE_STRING(node_isolate, "handle");
}
assert(!req_wrap->persistent().IsEmpty());
req_wrap->object()->Set(handle_sym, send_handle_obj);
req_wrap->object()->Set(env->handle_string(), send_handle_obj);
}

err = wrap->callbacks()->DoWrite(
@@ -320,7 +305,8 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {
}

req_wrap->Dispatched();
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, data_size));
req_wrap->object()->Set(env->bytes_string(),
Number::New(node_isolate, data_size));

if (err) {
req_wrap->~WriteWrap();
@@ -332,7 +318,8 @@ void StreamWrap::WriteStringImpl(const FunctionCallbackInfo<Value>& args) {


void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
HandleScope scope;
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

StreamWrap* wrap;
NODE_UNWRAP(args.This(), StreamWrap, wrap);
@@ -378,7 +365,8 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {

storage_size += sizeof(WriteWrap);
char* storage = new char[storage_size];
WriteWrap* req_wrap = new(storage) WriteWrap(req_wrap_obj, wrap);
WriteWrap* req_wrap =
new(storage) WriteWrap(env, req_wrap_obj, wrap);

uint32_t bytes = 0;
size_t offset = sizeof(WriteWrap);
@@ -419,7 +407,8 @@ void StreamWrap::Writev(const FunctionCallbackInfo<Value>& args) {
delete[] bufs;

req_wrap->Dispatched();
req_wrap->object()->Set(bytes_sym, Number::New(node_isolate, bytes));
req_wrap->object()->Set(env->bytes_string(),
Number::New(node_isolate, bytes));

if (err) {
req_wrap->~WriteWrap();
@@ -448,44 +437,48 @@ void StreamWrap::WriteUcs2String(const FunctionCallbackInfo<Value>& args) {
void StreamWrap::AfterWrite(uv_write_t* req, int status) {
WriteWrap* req_wrap = container_of(req, WriteWrap, req_);
StreamWrap* wrap = req_wrap->wrap();
Environment* env = wrap->env();

HandleScope scope(node_isolate);
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// The wrap and request objects should still be there.
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_obj->Delete(handle_sym);
}

wrap->callbacks()->AfterWrite(req_wrap);
req_wrap_obj->Delete(env->handle_string());
wrap->callbacks_->AfterWrite(req_wrap);

Local<Value> argv[] = {
Integer::New(status, node_isolate),
wrap->object(),
req_wrap_obj
};

MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
req_wrap_obj,
env->oncomplete_string(),
ARRAY_SIZE(argv),
argv);

req_wrap->~WriteWrap();
delete[] reinterpret_cast<char*>(req_wrap);
}


void StreamWrap::Shutdown(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

StreamWrap* wrap;
NODE_UNWRAP(args.This(), StreamWrap, wrap);

assert(args[0]->IsObject());
Local<Object> req_wrap_obj = args[0].As<Object>();

ShutdownWrap* req_wrap = new ShutdownWrap(req_wrap_obj);
ShutdownWrap* req_wrap = new ShutdownWrap(env, req_wrap_obj);
int err = wrap->callbacks()->DoShutdown(req_wrap, AfterShutdown);
req_wrap->Dispatched();
if (err) delete req_wrap;
@@ -496,12 +489,14 @@ void StreamWrap::Shutdown(const FunctionCallbackInfo<Value>& args) {
void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
ShutdownWrap* req_wrap = static_cast<ShutdownWrap*>(req->data);
StreamWrap* wrap = static_cast<StreamWrap*>(req->handle->data);
Environment* env = wrap->env();

// The wrap and request objects should still be there.
assert(req_wrap->persistent().IsEmpty() == false);
assert(wrap->persistent().IsEmpty() == false);

HandleScope scope(node_isolate);
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> argv[3] = {
@@ -510,7 +505,11 @@ void StreamWrap::AfterShutdown(uv_shutdown_t* req, int status) {
req_wrap_obj
};

MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
req_wrap_obj,
env->oncomplete_string(),
ARRAY_SIZE(argv),
argv);

delete req_wrap;
}
@@ -568,7 +567,9 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
ssize_t nread,
const uv_buf_t* buf,
uv_handle_type pending) {
HandleScope scope(node_isolate);
Environment* env = wrap()->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

Local<Value> argv[] = {
Integer::New(nread, node_isolate),
@@ -579,7 +580,7 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
if (nread < 0) {
if (buf->base != NULL)
free(buf->base);
MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env, Self(), env->onread_string(), ARRAY_SIZE(argv), argv);
return;
}

@@ -591,15 +592,15 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,

char* base = static_cast<char*>(realloc(buf->base, nread));
assert(static_cast<size_t>(nread) <= buf->len);
argv[1] = Buffer::Use(base, nread);
argv[1] = Buffer::Use(env, base, nread);

Local<Object> pending_obj;
if (pending == UV_TCP) {
pending_obj = AcceptHandle<TCPWrap, uv_tcp_t>(handle);
pending_obj = AcceptHandle<TCPWrap, uv_tcp_t>(env, handle);
} else if (pending == UV_NAMED_PIPE) {
pending_obj = AcceptHandle<PipeWrap, uv_pipe_t>(handle);
pending_obj = AcceptHandle<PipeWrap, uv_pipe_t>(env, handle);
} else if (pending == UV_UDP) {
pending_obj = AcceptHandle<UDPWrap, uv_udp_t>(handle);
pending_obj = AcceptHandle<UDPWrap, uv_udp_t>(env, handle);
} else {
assert(pending == UV_UNKNOWN_HANDLE);
}
@@ -608,7 +609,11 @@ void StreamWrapCallbacks::DoRead(uv_stream_t* handle,
argv[2] = pending_obj;
}

MakeCallback(wrap()->object(), onread_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
wrap()->object(),
env->onread_string(),
ARRAY_SIZE(argv),
argv);
}


@@ -22,11 +22,11 @@
#ifndef SRC_STREAM_WRAP_H_
#define SRC_STREAM_WRAP_H_

#include "v8.h"
#include "node.h"
#include "env.h"
#include "handle_wrap.h"
#include "req_wrap.h"
#include "string_bytes.h"
#include "v8.h"

namespace node {

@@ -37,8 +37,8 @@ typedef class ReqWrap<uv_shutdown_t> ShutdownWrap;

class WriteWrap: public ReqWrap<uv_write_t> {
public:
WriteWrap(v8::Local<v8::Object> obj, StreamWrap* wrap)
: ReqWrap<uv_write_t>(obj)
WriteWrap(Environment* env, v8::Local<v8::Object> obj, StreamWrap* wrap)
: ReqWrap<uv_write_t>(env, obj)
, wrap_(wrap) {
}

@@ -108,8 +108,6 @@ class StreamWrap : public HandleWrap {
delete old;
}

static void Initialize(v8::Handle<v8::Object> target);

static void GetFD(v8::Local<v8::String>,
const v8::PropertyCallbackInfo<v8::Value>&);

@@ -148,7 +146,9 @@ class StreamWrap : public HandleWrap {
protected:
static size_t WriteBuffer(v8::Handle<v8::Value> val, uv_buf_t* buf);

StreamWrap(v8::Handle<v8::Object> object, uv_stream_t* stream);
StreamWrap(Environment* env,
v8::Local<v8::Object> object,
uv_stream_t* stream);

~StreamWrap() {
if (callbacks_ != &default_callbacks_) {
@@ -20,10 +20,12 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "tcp_wrap.h"
#include "node.h"

#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
#include "node_buffer.h"
#include "node_wrap.h"
#include "handle_wrap.h"
#include "req_wrap.h"
#include "stream_wrap.h"

@@ -32,6 +34,7 @@

namespace node {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -40,40 +43,32 @@ 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;

static Persistent<Function> tcpConstructor;
static Cached<String> oncomplete_sym;
static Cached<String> onconnection_sym;


typedef class ReqWrap<uv_connect_t> ConnectWrap;


Local<Object> TCPWrap::Instantiate() {
// If this assert fire then process.binding('tcp_wrap') hasn't been
// called yet.
assert(tcpConstructor.IsEmpty() == false);

HandleScope scope(node_isolate);
Local<Object> obj = NewInstance(tcpConstructor);

return scope.Close(obj);
Local<Object> TCPWrap::Instantiate(Environment* env) {
HandleScope handle_scope(env->isolate());
assert(env->tcp_constructor_template().IsEmpty() == false);
Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
assert(constructor.IsEmpty() == false);
Local<Object> instance = constructor->NewInstance();
assert(instance.IsEmpty() == false);
return handle_scope.Close(instance);
}


void TCPWrap::Initialize(Handle<Object> target) {
StreamWrap::Initialize(target);

HandleScope scope(node_isolate);
void TCPWrap::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TCP"));

t->InstanceTemplate()->SetInternalFieldCount(1);

enum PropertyAttribute attributes =
@@ -119,12 +114,8 @@ void TCPWrap::Initialize(Handle<Object> target) {
SetSimultaneousAccepts);
#endif

onconnection_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onconnection");
oncomplete_sym = FIXED_ONE_BYTE_STRING(node_isolate, "oncomplete");

tcpConstructorTmpl.Reset(node_isolate, t);
tcpConstructor.Reset(node_isolate, t->GetFunction());
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "TCP"), t->GetFunction());
env->set_tcp_constructor_template(t);
}


@@ -145,15 +136,16 @@ void TCPWrap::New(const FunctionCallbackInfo<Value>& args) {
// 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());
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
TCPWrap* wrap = new TCPWrap(env, args.This());
assert(wrap);
}


TCPWrap::TCPWrap(Handle<Object> object)
: StreamWrap(object, reinterpret_cast<uv_stream_t*>(&handle_)) {
int r = uv_tcp_init(uv_default_loop(), &handle_);
TCPWrap::TCPWrap(Environment* env, Handle<Object> object)
: StreamWrap(env, object, reinterpret_cast<uv_stream_t*>(&handle_)) {
int r = uv_tcp_init(env->event_loop(), &handle_);
assert(r == 0); // How do we proxy this error up to javascript?
// Suggestion: uv_tcp_init() returns void.
UpdateWriteQueueSize();
@@ -166,7 +158,8 @@ TCPWrap::~TCPWrap() {


void TCPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
struct sockaddr_storage address;

TCPWrap* wrap;
@@ -181,15 +174,16 @@ void TCPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
&addrlen);
if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, out);
AddressToJS(env, addr, out);
}

args.GetReturnValue().Set(err);
}


void TCPWrap::GetPeerName(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
struct sockaddr_storage address;

TCPWrap* wrap;
@@ -204,7 +198,7 @@ void TCPWrap::GetPeerName(const FunctionCallbackInfo<Value>& args) {
&addrlen);
if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, out);
AddressToJS(env, addr, out);
}

args.GetReturnValue().Set(err);
@@ -311,10 +305,12 @@ void TCPWrap::Listen(const FunctionCallbackInfo<Value>& args) {


void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
HandleScope scope(node_isolate);

TCPWrap* tcp_wrap = static_cast<TCPWrap*>(handle->data);
assert(&tcp_wrap->handle_ == reinterpret_cast<uv_tcp_t*>(handle));
Environment* env = tcp_wrap->env();

Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// We should not be getting this callback if someone as already called
// uv_close() on the handle.
@@ -327,7 +323,7 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {

if (status == 0) {
// Instantiate the client javascript object and handle.
Local<Object> client_obj = Instantiate();
Local<Object> client_obj = Instantiate(env);

// Unwrap the client javascript object.
TCPWrap* wrap;
@@ -340,15 +336,22 @@ void TCPWrap::OnConnection(uv_stream_t* handle, int status) {
argv[1] = client_obj;
}

MakeCallback(tcp_wrap->object(), onconnection_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
tcp_wrap->object(),
env->onconnection_string(),
ARRAY_SIZE(argv),
argv);
}


void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
ConnectWrap* req_wrap = static_cast<ConnectWrap*>(req->data);
TCPWrap* wrap = static_cast<TCPWrap*>(req->handle->data);
assert(req_wrap->env() == wrap->env());
Environment* env = wrap->env();

HandleScope scope(node_isolate);
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

// The wrap and request objects should still be there.
assert(req_wrap->persistent().IsEmpty() == false);
@@ -362,14 +365,19 @@ void TCPWrap::AfterConnect(uv_connect_t* req, int status) {
v8::True(node_isolate),
v8::True(node_isolate)
};
MakeCallback(req_wrap_obj, oncomplete_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
req_wrap_obj,
env->oncomplete_string(),
ARRAY_SIZE(argv),
argv);

delete req_wrap;
}


void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

TCPWrap* wrap;
NODE_UNWRAP(args.This(), TCPWrap, wrap);
@@ -386,7 +394,7 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip4_addr(*ip_address, port, &addr);

if (err == 0) {
ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj);
err = uv_tcp_connect(&req_wrap->req_,
&wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
@@ -400,7 +408,8 @@ void TCPWrap::Connect(const FunctionCallbackInfo<Value>& args) {


void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

TCPWrap* wrap;
NODE_UNWRAP(args.This(), TCPWrap, wrap);
@@ -417,7 +426,7 @@ void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {
int err = uv_ip6_addr(*ip_address, port, &addr);

if (err == 0) {
ConnectWrap* req_wrap = new ConnectWrap(req_wrap_obj);
ConnectWrap* req_wrap = new ConnectWrap(env, req_wrap_obj);
err = uv_tcp_connect(&req_wrap->req_,
&wrap->handle_,
reinterpret_cast<const sockaddr*>(&addr),
@@ -431,50 +440,38 @@ void TCPWrap::Connect6(const FunctionCallbackInfo<Value>& args) {


// also used by udp_wrap.cc
Local<Object> AddressToJS(const sockaddr* addr, Handle<Object> info) {
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;

Local<Object> AddressToJS(Environment* env,
const sockaddr* addr,
Local<Object> info) {
HandleScope scope(node_isolate);
char ip[INET6_ADDRSTRLEN];
const sockaddr_in *a4;
const sockaddr_in6 *a6;
int port;

if (address_sym.IsEmpty()) {
address_sym = FIXED_ONE_BYTE_STRING(node_isolate, "address");
family_sym = FIXED_ONE_BYTE_STRING(node_isolate, "family");
port_sym = FIXED_ONE_BYTE_STRING(node_isolate, "port");
ipv4_sym = FIXED_ONE_BYTE_STRING(node_isolate, "IPv4");
ipv6_sym = FIXED_ONE_BYTE_STRING(node_isolate, "IPv6");
}

if (info.IsEmpty()) info = Object::New();

switch (addr->sa_family) {
case AF_INET6:
a6 = reinterpret_cast<const sockaddr_in6*>(addr);
uv_inet_ntop(AF_INET6, &a6->sin6_addr, ip, sizeof ip);
port = ntohs(a6->sin6_port);
info->Set(address_sym, OneByteString(node_isolate, ip));
info->Set(family_sym, ipv6_sym);
info->Set(port_sym, Integer::New(port, node_isolate));
info->Set(env->address_string(), OneByteString(node_isolate, ip));
info->Set(env->family_string(), env->ipv6_string());
info->Set(env->port_string(), Integer::New(port, node_isolate));
break;

case AF_INET:
a4 = reinterpret_cast<const sockaddr_in*>(addr);
uv_inet_ntop(AF_INET, &a4->sin_addr, ip, sizeof ip);
port = ntohs(a4->sin_port);
info->Set(address_sym, OneByteString(node_isolate, ip));
info->Set(family_sym, ipv4_sym);
info->Set(port_sym, Integer::New(port, node_isolate));
info->Set(env->address_string(), OneByteString(node_isolate, ip));
info->Set(env->family_string(), env->ipv4_string());
info->Set(env->port_string(), Integer::New(port, node_isolate));
break;

default:
info->Set(address_sym, String::Empty(node_isolate));
info->Set(env->address_string(), String::Empty(node_isolate));
}

return scope.Close(info);
@@ -483,4 +480,4 @@ Local<Object> AddressToJS(const sockaddr* addr, Handle<Object> info) {

} // namespace node

NODE_MODULE(node_tcp_wrap, node::TCPWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_tcp_wrap, node::TCPWrap::Initialize)
@@ -21,20 +21,24 @@

#ifndef SRC_TCP_WRAP_H_
#define SRC_TCP_WRAP_H_

#include "env.h"
#include "stream_wrap.h"

namespace node {

class TCPWrap : public StreamWrap {
public:
static v8::Local<v8::Object> Instantiate();
static v8::Local<v8::Object> Instantiate(Environment* env);
static TCPWrap* Unwrap(v8::Local<v8::Object> obj);
static void Initialize(v8::Handle<v8::Object> target);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);

uv_tcp_t* UVHandle();

private:
explicit TCPWrap(v8::Handle<v8::Object> object);
TCPWrap(Environment* env, v8::Handle<v8::Object> object);
~TCPWrap();

static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -19,13 +19,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "node.h"
#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"

#include <stdint.h>

namespace node {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -40,9 +42,9 @@ const uint32_t kOnTimeout = 0;

class TimerWrap : public HandleWrap {
public:
static void Initialize(Handle<Object> target) {
HandleScope scope(node_isolate);

static void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Local<FunctionTemplate> constructor = FunctionTemplate::New(New);
constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "Timer"));
@@ -71,13 +73,14 @@ class TimerWrap : public HandleWrap {
// Therefore we assert that we are not trying to call this as a
// normal function.
assert(args.IsConstructCall());
HandleScope scope(node_isolate);
new TimerWrap(args.This());
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
new TimerWrap(env, args.This());
}

explicit TimerWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_timer_init(uv_default_loop(), &handle_);
TimerWrap(Environment* env, Handle<Object> object)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_timer_init(env->event_loop(), &handle_);
assert(r == 0);
}

@@ -133,19 +136,19 @@ class TimerWrap : public HandleWrap {
}

static void OnTimeout(uv_timer_t* handle, int status) {
HandleScope scope(node_isolate);

TimerWrap* wrap = static_cast<TimerWrap*>(handle->data);
assert(wrap);

Environment* env = wrap->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());
Local<Value> argv[1] = { Integer::New(status, node_isolate) };
MakeCallback(wrap->object(), kOnTimeout, ARRAY_SIZE(argv), argv);
MakeCallback(env, wrap->object(), kOnTimeout, ARRAY_SIZE(argv), argv);
}

static void Now(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
uv_update_time(uv_default_loop());
double now = static_cast<double>(uv_now(uv_default_loop()));
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
uv_update_time(env->event_loop());
double now = static_cast<double>(uv_now(env->event_loop()));
args.GetReturnValue().Set(now);
}

@@ -155,4 +158,4 @@ class TimerWrap : public HandleWrap {

} // namespace node

NODE_MODULE(node_timer_wrap, node::TimerWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_timer_wrap, node::TimerWrap::Initialize)
@@ -34,6 +34,7 @@ namespace node {
using crypto::SSLWrap;
using crypto::SecureContext;
using v8::Boolean;
using v8::Context;
using v8::Exception;
using v8::Function;
using v8::FunctionCallbackInfo;
@@ -44,40 +45,20 @@ using v8::Integer;
using v8::Local;
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> onhandshakestart_sym;
static Cached<String> onhandshakedone_sym;
static Cached<String> onclienthello_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> sni_context_sym;

static Persistent<Function> tlsWrap;

static const int X509_NAME_FLAGS = ASN1_STRFLGS_ESC_CTRL
| ASN1_STRFLGS_ESC_MSB
| XN_FLAG_SEP_MULTILINE
| XN_FLAG_FN_SN;


TLSCallbacks::TLSCallbacks(Kind kind,
TLSCallbacks::TLSCallbacks(Environment* env,
Kind kind,
Handle<Object> sc,
StreamWrapCallbacks* old)
: SSLWrap<TLSCallbacks>(ObjectWrap::Unwrap<SecureContext>(sc), kind),
: SSLWrap<TLSCallbacks>(env, ObjectWrap::Unwrap<SecureContext>(sc), kind),
StreamWrapCallbacks(old),
enc_in_(NULL),
enc_out_(NULL),
@@ -92,7 +73,7 @@ TLSCallbacks::TLSCallbacks(Kind kind,
sc_ = ObjectWrap::Unwrap<SecureContext>(sc);
sc_handle_.Reset(node_isolate, sc);

Local<Object> object = NewInstance(tlsWrap);
Local<Object> object = env->tls_wrap_constructor_function()->NewInstance();
NODE_WRAP(object, this);
persistent().Reset(node_isolate, object);

@@ -197,7 +178,8 @@ void TLSCallbacks::InitSSL() {


void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

if (args.Length() < 1 || !args[0]->IsObject())
return ThrowTypeError("First argument should be a StreamWrap instance");
@@ -212,8 +194,8 @@ void TLSCallbacks::Wrap(const FunctionCallbackInfo<Value>& args) {
SSLWrap<TLSCallbacks>::kClient;

TLSCallbacks* callbacks = NULL;
WITH_GENERIC_STREAM(stream, {
callbacks = new TLSCallbacks(kind, sc, wrap->callbacks());
WITH_GENERIC_STREAM(env, stream, {
callbacks = new TLSCallbacks(env, kind, sc, wrap->callbacks());
wrap->OverrideCallbacks(callbacks);
});

@@ -243,23 +225,32 @@ void TLSCallbacks::Start(const FunctionCallbackInfo<Value>& args) {


void TLSCallbacks::SSLInfoCallback(const SSL* ssl_, int where, int ret) {
if (!(where & (SSL_CB_HANDSHAKE_START | SSL_CB_HANDSHAKE_DONE)))
return;

// Be compatible with older versions of OpenSSL. SSL_get_app_data() wants
// a non-const SSL* in OpenSSL <= 0.9.7e.
SSL* ssl = const_cast<SSL*>(ssl_);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
Environment* env = c->env();
// There should be a Context::Scope a few stack frames down.
assert(env->context() == env->isolate()->GetCurrentContext());
HandleScope handle_scope(env->isolate());
Local<Object> object = c->object(env->isolate());

if (where & SSL_CB_HANDSHAKE_START) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
Local<Object> object = c->object(node_isolate);
if (object->Has(onhandshakestart_sym))
MakeCallback(object, onhandshakestart_sym, 0, NULL);
Local<Value> callback = object->Get(env->onhandshakestart_string());
if (callback->IsFunction()) {
MakeCallback(env, object, callback.As<Function>());
}
}

if (where & SSL_CB_HANDSHAKE_DONE) {
HandleScope scope(node_isolate);
TLSCallbacks* c = static_cast<TLSCallbacks*>(SSL_get_app_data(ssl));
c->established_ = true;
Local<Object> object = c->object(node_isolate);
if (object->Has(onhandshakedone_sym))
MakeCallback(object, onhandshakedone_sym, 0, NULL);
Local<Value> callback = object->Get(env->onhandshakedone_string());
if (callback->IsFunction()) {
MakeCallback(env, object, callback.As<Function>());
}
}
}

@@ -306,9 +297,8 @@ void TLSCallbacks::EncOut() {


void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
HandleScope scope(node_isolate);

TLSCallbacks* callbacks = static_cast<TLSCallbacks*>(req->data);
Environment* env = callbacks->env();

// Handle error
if (status) {
@@ -317,10 +307,16 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
return;

// Notify about error
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());
Local<Value> arg = String::Concat(
FIXED_ONE_BYTE_STRING(node_isolate, "write cb error, status: "),
Integer::New(status, node_isolate)->ToString());
MakeCallback(callbacks->object(node_isolate), onerror_sym, 1, &arg);
MakeCallback(env,
callbacks->object(node_isolate),
env->onerror_string(),
1,
&arg);
callbacks->InvokeQueued(status);
return;
}
@@ -334,7 +330,7 @@ void TLSCallbacks::EncOutCb(uv_write_t* req, int status) {
}


Handle<Value> TLSCallbacks::GetSSLError(int status, int* err) {
Local<Value> TLSCallbacks::GetSSLError(int status, int* err) {
HandleScope scope(node_isolate);

*err = SSL_get_error(ssl_, status);
@@ -365,7 +361,7 @@ Handle<Value> TLSCallbacks::GetSSLError(int status, int* err) {
return scope.Close(exception);
}
}
return Handle<Value>();
return Local<Value>();
}


@@ -374,7 +370,8 @@ void TLSCallbacks::ClearOut() {
if (!hello_parser_.IsEnded())
return;

HandleScope scope(node_isolate);
Context::Scope context_scope(env()->context());
HandleScope handle_scope(env()->isolate());

assert(ssl_ != NULL);

@@ -385,18 +382,27 @@ void TLSCallbacks::ClearOut() {
if (read > 0) {
Local<Value> argv[] = {
Integer::New(read, node_isolate),
Buffer::New(out, read)
Buffer::New(env(), out, read)
};
MakeCallback(Self(), onread_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env(),
Self(),
env()->onread_string(),
ARRAY_SIZE(argv),
argv);
}
} while (read > 0);

if (read == -1) {
int err;
Handle<Value> argv = GetSSLError(read, &err);

if (!argv.IsEmpty())
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
if (!argv.IsEmpty()) {
MakeCallback(env(),
object(node_isolate),
env()->onerror_string(),
1,
&argv);
}
}
}

@@ -406,8 +412,6 @@ bool TLSCallbacks::ClearIn() {
if (!hello_parser_.IsEnded())
return false;

HandleScope scope(node_isolate);

int written = 0;
while (clear_in_->Length() > 0) {
size_t avail = 0;
@@ -425,11 +429,19 @@ bool TLSCallbacks::ClearIn() {
return true;
}

Context::Scope context_scope(env()->context());
HandleScope handle_scope(env()->isolate());

// Error or partial write
int err;
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty())
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
if (!argv.IsEmpty()) {
MakeCallback(env(),
object(node_isolate),
env()->onerror_string(),
1,
&argv);
}

return false;
}
@@ -440,8 +452,6 @@ int TLSCallbacks::DoWrite(WriteWrap* w,
size_t count,
uv_stream_t* send_handle,
uv_write_cb cb) {
HandleScope scope(node_isolate);

assert(send_handle == NULL);

// Queue callback to execute it on next tick
@@ -489,9 +499,15 @@ int TLSCallbacks::DoWrite(WriteWrap* w,

if (i != count) {
int err;
Context::Scope context_scope(env()->context());
HandleScope handle_scope(env()->isolate());
Handle<Value> argv = GetSSLError(written, &err);
if (!argv.IsEmpty()) {
MakeCallback(object(node_isolate), onerror_sym, 1, &argv);
MakeCallback(env(),
object(node_isolate),
env()->onerror_string(),
1,
&argv);
return -1;
}

@@ -527,8 +543,10 @@ void TLSCallbacks::DoRead(uv_stream_t* handle,
if (nread < 0) {
// Error should be emitted only after all data was read
ClearOut();
Context::Scope context_scope(env()->context());
HandleScope handle_scope(env()->isolate());
Local<Value> arg = Integer::New(nread, node_isolate);
MakeCallback(Self(), onread_sym, 1, &arg);
MakeCallback(env(), Self(), env()->onread_string(), 1, &arg);
return;
}

@@ -664,18 +682,16 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
HandleScope scope(node_isolate);

TLSCallbacks* p = static_cast<TLSCallbacks*>(arg);
Environment* env = p->env();

const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);

if (servername != NULL) {
// Call the SNI callback and use its return value as context
Local<Object> object = p->object(node_isolate);
Local<Value> ctx;
if (object->Has(sni_context_sym)) {
ctx = object->Get(sni_context_sym);
}
Local<Value> ctx = object->Get(env->sni_context_string());

if (ctx.IsEmpty() || ctx->IsUndefined())
if (!ctx->IsObject())
return SSL_TLSEXT_ERR_NOACK;

p->sni_context_.Dispose();
@@ -690,8 +706,10 @@ int TLSCallbacks::SelectSNIContextCallback(SSL* s, int* ad, void* arg) {
#endif // SSL_CTRL_SET_TLSEXT_SERVERNAME_CB


void TLSCallbacks::Initialize(Handle<Object> target) {
HandleScope scope(node_isolate);
void TLSCallbacks::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

NODE_SET_METHOD(target, "wrap", TLSCallbacks::Wrap);

@@ -715,29 +733,9 @@ void TLSCallbacks::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "setServername", SetServername);
#endif // SSL_CRT_SET_TLSEXT_SERVERNAME_CB

tlsWrap.Reset(node_isolate, t->GetFunction());

onread_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onread");
onerror_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onerror");
onhandshakestart_sym =
FIXED_ONE_BYTE_STRING(node_isolate, "onhandshakestart");
onhandshakedone_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onhandshakedone");
onclienthello_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onclienthello");

subject_sym = FIXED_ONE_BYTE_STRING(node_isolate, "subject");
issuer_sym = FIXED_ONE_BYTE_STRING(node_isolate, "issuer");
valid_from_sym = FIXED_ONE_BYTE_STRING(node_isolate, "valid_from");
valid_to_sym = FIXED_ONE_BYTE_STRING(node_isolate, "valid_to");
subjectaltname_sym = FIXED_ONE_BYTE_STRING(node_isolate, "subjectaltname");
modulus_sym = FIXED_ONE_BYTE_STRING(node_isolate, "modulus");
exponent_sym = FIXED_ONE_BYTE_STRING(node_isolate, "exponent");
fingerprint_sym = FIXED_ONE_BYTE_STRING(node_isolate, "fingerprint");
name_sym = FIXED_ONE_BYTE_STRING(node_isolate, "name");
version_sym = FIXED_ONE_BYTE_STRING(node_isolate, "version");
ext_key_usage_sym = FIXED_ONE_BYTE_STRING(node_isolate, "ext_key_usage");
sni_context_sym = FIXED_ONE_BYTE_STRING(node_isolate, "sni_context");
env->set_tls_wrap_constructor_function(t->GetFunction());
}

} // namespace node

NODE_MODULE(node_tls_wrap, node::TLSCallbacks::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_tls_wrap, node::TLSCallbacks::Initialize)
@@ -24,6 +24,8 @@

#include "node.h"
#include "node_crypto.h" // SSLWrap

#include "env.h"
#include "queue.h"
#include "stream_wrap.h"
#include "v8.h"
@@ -42,7 +44,9 @@ namespace crypto {
class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
public StreamWrapCallbacks {
public:
static void Initialize(v8::Handle<v8::Object> target);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);

int DoWrite(WriteWrap* w,
uv_buf_t* bufs,
@@ -82,7 +86,10 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
QUEUE member_;
};

TLSCallbacks(Kind kind, v8::Handle<v8::Object> sc, StreamWrapCallbacks* old);
TLSCallbacks(Environment* env,
Kind kind,
v8::Handle<v8::Object> sc,
StreamWrapCallbacks* old);
~TLSCallbacks();

static void SSLInfoCallback(const SSL* ssl_, int where, int ret);
@@ -99,7 +106,7 @@ class TLSCallbacks : public crypto::SSLWrap<TLSCallbacks>,
EncOut();
}

v8::Handle<v8::Value> GetSSLError(int status, int* err);
v8::Local<v8::Value> GetSSLError(int status, int* err);
static void OnClientHelloParseEnd(void* arg);

static void Wrap(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -20,16 +20,19 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "tty_wrap.h"
#include "node.h"
#include "node_buffer.h"

#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
#include "node_buffer.h"
#include "node_wrap.h"
#include "req_wrap.h"
#include "stream_wrap.h"

namespace node {

using v8::Array;
using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -43,14 +46,13 @@ using v8::String;
using v8::Value;


void TTYWrap::Initialize(Handle<Object> target) {
StreamWrap::Initialize(target);

HandleScope scope(node_isolate);
void TTYWrap::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->SetClassName(FIXED_ONE_BYTE_STRING(node_isolate, "TTY"));

t->InstanceTemplate()->SetInternalFieldCount(1);

enum PropertyAttribute attributes =
@@ -81,8 +83,8 @@ void TTYWrap::Initialize(Handle<Object> target) {
NODE_SET_METHOD(target, "isTTY", IsTTY);
NODE_SET_METHOD(target, "guessHandleType", GuessHandleType);

ttyConstructorTmpl.Reset(node_isolate, t);
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "TTY"), t->GetFunction());
env->set_tty_constructor_template(t);
}


@@ -162,7 +164,8 @@ void TTYWrap::SetRawMode(const FunctionCallbackInfo<Value>& args) {


void TTYWrap::New(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

// This constructor should not be exposed to public javascript.
// Therefore we assert that we are not trying to call this as a
@@ -172,16 +175,16 @@ void TTYWrap::New(const FunctionCallbackInfo<Value>& args) {
int fd = args[0]->Int32Value();
assert(fd >= 0);

TTYWrap* wrap = new TTYWrap(args.This(), fd, args[1]->IsTrue());
TTYWrap* wrap = new TTYWrap(env, args.This(), fd, args[1]->IsTrue());
wrap->UpdateWriteQueueSize();
}


TTYWrap::TTYWrap(Handle<Object> object, int fd, bool readable)
: StreamWrap(object, reinterpret_cast<uv_stream_t*>(&handle_)) {
uv_tty_init(uv_default_loop(), &handle_, fd, readable);
TTYWrap::TTYWrap(Environment* env, Handle<Object> object, int fd, bool readable)
: StreamWrap(env, object, reinterpret_cast<uv_stream_t*>(&handle_)) {
uv_tty_init(env->event_loop(), &handle_, fd, readable);
}

} // namespace node

NODE_MODULE(node_tty_wrap, node::TTYWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_tty_wrap, node::TTYWrap::Initialize)
@@ -22,20 +22,26 @@
#ifndef SRC_TTY_WRAP_H_
#define SRC_TTY_WRAP_H_

#include "env.h"
#include "handle_wrap.h"
#include "stream_wrap.h"

namespace node {

class TTYWrap : public StreamWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
static TTYWrap* Unwrap(v8::Local<v8::Object> obj);

uv_tty_t* UVHandle();

private:
TTYWrap(v8::Handle<v8::Object> object, int fd, bool readable);
TTYWrap(Environment* env,
v8::Handle<v8::Object> object,
int fd,
bool readable);

static void GuessHandleType(const v8::FunctionCallbackInfo<v8::Value>& args);
static void IsTTY(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -20,7 +20,8 @@
// USE OR OTHER DEALINGS IN THE SOFTWARE.

#include "udp_wrap.h"
#include "node.h"
#include "env.h"
#include "env-inl.h"
#include "node_buffer.h"
#include "handle_wrap.h"
#include "req_wrap.h"
@@ -30,6 +31,7 @@

namespace node {

using v8::Context;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
@@ -38,7 +40,6 @@ using v8::HandleScope;
using v8::Integer;
using v8::Local;
using v8::Object;
using v8::Persistent;
using v8::PropertyAttribute;
using v8::PropertyCallbackInfo;
using v8::String;
@@ -49,20 +50,17 @@ using v8::Value;

class SendWrap : public ReqWrap<uv_udp_send_t> {
public:
SendWrap(Local<Object> req_wrap_obj, bool have_callback);
SendWrap(Environment* env, Local<Object> req_wrap_obj, bool have_callback);
inline bool have_callback() const;
private:
const bool have_callback_;
};


static Persistent<Function> constructor;
static Cached<String> oncomplete_sym;
static Cached<String> onmessage_sym;


SendWrap::SendWrap(Local<Object> req_wrap_obj, bool have_callback)
: ReqWrap<uv_udp_send_t>(req_wrap_obj)
SendWrap::SendWrap(Environment* env,
Local<Object> req_wrap_obj,
bool have_callback)
: ReqWrap<uv_udp_send_t>(env, req_wrap_obj)
, have_callback_(have_callback) {
}

@@ -72,9 +70,9 @@ inline bool SendWrap::have_callback() const {
}


UDPWrap::UDPWrap(Handle<Object> object)
: HandleWrap(object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_udp_init(uv_default_loop(), &handle_);
UDPWrap::UDPWrap(Environment* env, Handle<Object> object)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&handle_)) {
int r = uv_udp_init(env->event_loop(), &handle_);
assert(r == 0); // can't fail anyway
}

@@ -83,11 +81,10 @@ UDPWrap::~UDPWrap() {
}


void UDPWrap::Initialize(Handle<Object> target) {
HandleScope scope(node_isolate);

oncomplete_sym = FIXED_ONE_BYTE_STRING(node_isolate, "oncomplete");
onmessage_sym = FIXED_ONE_BYTE_STRING(node_isolate, "onmessage");
void UDPWrap::Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
Environment* env = Environment::GetCurrent(context);

Local<FunctionTemplate> t = FunctionTemplate::New(New);
t->InstanceTemplate()->SetInternalFieldCount(1);
@@ -120,15 +117,16 @@ void UDPWrap::Initialize(Handle<Object> target) {
NODE_SET_PROTOTYPE_METHOD(t, "ref", HandleWrap::Ref);
NODE_SET_PROTOTYPE_METHOD(t, "unref", HandleWrap::Unref);

constructor.Reset(node_isolate, t->GetFunction());
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "UDP"), t->GetFunction());
env->set_udp_constructor_function(t->GetFunction());
}


void UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
assert(args.IsConstructCall());
new UDPWrap(args.This());
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());
new UDPWrap(env, args.This());
}


@@ -244,7 +242,8 @@ void UDPWrap::DropMembership(const FunctionCallbackInfo<Value>& args) {


void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

UDPWrap* wrap;
NODE_UNWRAP(args.This(), UDPWrap, wrap);
@@ -269,7 +268,7 @@ void UDPWrap::DoSend(const FunctionCallbackInfo<Value>& args, int family) {
assert(offset < Buffer::Length(buffer_obj));
assert(length <= Buffer::Length(buffer_obj) - offset);

SendWrap* req_wrap = new SendWrap(req_wrap_obj, have_callback);
SendWrap* req_wrap = new SendWrap(env, req_wrap_obj, have_callback);

uv_buf_t buf = uv_buf_init(Buffer::Data(buffer_obj) + offset,
length);
@@ -337,7 +336,9 @@ void UDPWrap::RecvStop(const FunctionCallbackInfo<Value>& args) {


void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
HandleScope scope(node_isolate);
Environment* env = Environment::GetCurrent(args.GetIsolate());
HandleScope handle_scope(args.GetIsolate());

struct sockaddr_storage address;
UDPWrap* wrap;
NODE_UNWRAP(args.This(), UDPWrap, wrap);
@@ -352,7 +353,7 @@ void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {

if (err == 0) {
const sockaddr* addr = reinterpret_cast<const sockaddr*>(&address);
AddressToJS(addr, obj);
AddressToJS(env, addr, obj);
}

args.GetReturnValue().Set(err);
@@ -363,10 +364,12 @@ void UDPWrap::GetSockName(const FunctionCallbackInfo<Value>& args) {
void UDPWrap::OnSend(uv_udp_send_t* req, int status) {
SendWrap* req_wrap = static_cast<SendWrap*>(req->data);
if (req_wrap->have_callback()) {
HandleScope scope(node_isolate);
Environment* env = req_wrap->env();
Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());
Local<Object> req_wrap_obj = req_wrap->object();
Local<Value> arg = Integer::New(status, node_isolate);
MakeCallback(req_wrap_obj, oncomplete_sym, 1, &arg);
MakeCallback(env, req_wrap_obj, env->oncomplete_string(), 1, &arg);
}
delete req_wrap;
}
@@ -397,8 +400,11 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
}

UDPWrap* wrap = static_cast<UDPWrap*>(handle->data);
Environment* env = wrap->env();

Context::Scope context_scope(env->context());
HandleScope handle_scope(env->isolate());

HandleScope scope(node_isolate);
Local<Object> wrap_obj = wrap->object();
Local<Value> argv[] = {
Integer::New(nread, node_isolate),
@@ -410,14 +416,18 @@ void UDPWrap::OnRecv(uv_udp_t* handle,
if (nread < 0) {
if (buf->base != NULL)
free(buf->base);
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
MakeCallback(env,
wrap_obj,
env->onmessage_string(),
ARRAY_SIZE(argv),
argv);
return;
}

char* base = static_cast<char*>(realloc(buf->base, nread));
argv[2] = Buffer::Use(base, nread);
argv[3] = AddressToJS(addr);
MakeCallback(wrap_obj, onmessage_sym, ARRAY_SIZE(argv), argv);
argv[2] = Buffer::Use(env, base, nread);
argv[3] = AddressToJS(env, addr);
MakeCallback(env, wrap_obj, env->onmessage_string(), ARRAY_SIZE(argv), argv);
}


@@ -428,10 +438,10 @@ UDPWrap* UDPWrap::Unwrap(Local<Object> obj) {
}


Local<Object> UDPWrap::Instantiate() {
Local<Object> UDPWrap::Instantiate(Environment* env) {
// If this assert fires then Initialize hasn't been called yet.
assert(constructor.IsEmpty() == false);
return NewInstance(constructor);
assert(env->udp_constructor_function().IsEmpty() == false);
return env->udp_constructor_function()->NewInstance();
}


@@ -442,4 +452,4 @@ uv_udp_t* UDPWrap::UVHandle() {

} // namespace node

NODE_MODULE(node_udp_wrap, node::UDPWrap::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_udp_wrap, node::UDPWrap::Initialize)
@@ -22,15 +22,19 @@
#ifndef SRC_UDP_WRAP_H_
#define SRC_UDP_WRAP_H_

#include "node.h"
#include "req_wrap.h"
#include "env.h"
#include "handle_wrap.h"
#include "req_wrap.h"
#include "uv.h"
#include "v8.h"

namespace node {

class UDPWrap: public HandleWrap {
public:
static void Initialize(v8::Handle<v8::Object> target);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
static void GetFD(v8::Local<v8::String>,
const v8::PropertyCallbackInfo<v8::Value>&);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
@@ -50,11 +54,11 @@ class UDPWrap: public HandleWrap {
static void SetTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
static UDPWrap* Unwrap(v8::Local<v8::Object> obj);

static v8::Local<v8::Object> Instantiate();
static v8::Local<v8::Object> Instantiate(Environment* env);
uv_udp_t* UVHandle();

private:
explicit UDPWrap(v8::Handle<v8::Object> object);
UDPWrap(Environment* env, v8::Handle<v8::Object> object);
virtual ~UDPWrap();

static void DoBind(const v8::FunctionCallbackInfo<v8::Value>& args,
@@ -0,0 +1,83 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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 SRC_UTIL_INL_H_
#define SRC_UTIL_INL_H_

#include "util.h"

namespace node {

template <class TypeName>
inline v8::Local<TypeName> PersistentToLocal(
v8::Isolate* isolate,
const v8::Persistent<TypeName>& persistent) {
if (persistent.IsWeak()) {
return WeakPersistentToLocal(isolate, persistent);
} else {
return StrongPersistentToLocal(persistent);
}
}

template <class TypeName>
inline v8::Local<TypeName> StrongPersistentToLocal(
const v8::Persistent<TypeName>& persistent) {
return *reinterpret_cast<v8::Local<TypeName>*>(
const_cast<v8::Persistent<TypeName>*>(&persistent));
}

template <class TypeName>
inline v8::Local<TypeName> WeakPersistentToLocal(
v8::Isolate* isolate,
const v8::Persistent<TypeName>& persistent) {
return v8::Local<TypeName>::New(isolate, persistent);
}

inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const char* data,
int length) {
return v8::String::NewFromOneByte(isolate,
reinterpret_cast<const uint8_t*>(data),
v8::String::kNormalString,
length);
}

inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const signed char* data,
int length) {
return v8::String::NewFromOneByte(isolate,
reinterpret_cast<const uint8_t*>(data),
v8::String::kNormalString,
length);
}

inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const unsigned char* data,
int length) {
return v8::String::NewFromOneByte(isolate,
reinterpret_cast<const uint8_t*>(data),
v8::String::kNormalString,
length);
}

} // namespace node

#endif // SRC_UTIL_INL_H_
@@ -0,0 +1,82 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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 SRC_UTIL_H_
#define SRC_UTIL_H_

#include "v8.h"
#include <stddef.h>

namespace node {

#define OFFSET_OF(TypeName, Field) \
(reinterpret_cast<uintptr_t>(&(reinterpret_cast<TypeName*>(8)->Field)) - 8)

#define CONTAINER_OF(Pointer, TypeName, Field) \
reinterpret_cast<TypeName*>( \
reinterpret_cast<uintptr_t>(Pointer) - OFFSET_OF(TypeName, Field))

#define FIXED_ONE_BYTE_STRING(isolate, string) \
(node::OneByteString((isolate), (string), sizeof(string) - 1))

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
void operator=(const TypeName&); \
TypeName(const TypeName&)

// If persistent.IsWeak() == false, then do not call persistent.Dispose()
// while the returned Local<T> is still in scope, it will destroy the
// reference to the object.
template <class TypeName>
inline v8::Local<TypeName> PersistentToLocal(
v8::Isolate* isolate,
const v8::Persistent<TypeName>& persistent);

// Unchecked conversion from a non-weak Persistent<T> to Local<TLocal<T>,
// use with care!
//
// Do not call persistent.Dispose() while the returned Local<T> is still in
// scope, it will destroy the reference to the object.
template <class TypeName>
inline v8::Local<TypeName> StrongPersistentToLocal(
const v8::Persistent<TypeName>& persistent);

template <class TypeName>
inline v8::Local<TypeName> WeakPersistentToLocal(
v8::Isolate* isolate,
const v8::Persistent<TypeName>& persistent);

// Convenience wrapper around v8::String::NewFromOneByte().
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const char* data,
int length = -1);

// For the people that compile with -funsigned-char.
inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const signed char* data,
int length = -1);

inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
const unsigned char* data,
int length = -1);

} // namespace node

#endif // SRC_UTIL_H_
@@ -25,6 +25,7 @@
namespace node {
namespace uv {

using v8::Context;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Handle;
@@ -44,8 +45,9 @@ void ErrName(const FunctionCallbackInfo<Value>& args) {
}


void Initialize(Handle<Object> target) {
v8::HandleScope handle_scope(node_isolate);
void Initialize(Handle<Object> target,
Handle<Value> unused,
Handle<Context> context) {
target->Set(FIXED_ONE_BYTE_STRING(node_isolate, "errname"),
FunctionTemplate::New(ErrName)->GetFunction());
#define V(name, _) \
@@ -59,4 +61,4 @@ void Initialize(Handle<Object> target) {
} // namespace uv
} // namespace node

NODE_MODULE(node_uv, node::uv::Initialize)
NODE_MODULE_CONTEXT_AWARE(node_uv, node::uv::Initialize)