@@ -35,9 +35,12 @@

namespace node {

inline AsyncWrap::AsyncWrap(Environment* env, v8::Handle<v8::Object> object)
inline AsyncWrap::AsyncWrap(Environment* env,
v8::Handle<v8::Object> object,
ProviderType provider)
: BaseObject(env, object),
async_flags_(NO_OPTIONS) {
async_flags_(NO_OPTIONS),
provider_type_(provider) {
if (!env->has_async_listener())
return;

@@ -56,14 +59,13 @@ inline AsyncWrap::AsyncWrap(Environment* env, v8::Handle<v8::Object> object)
inline AsyncWrap::~AsyncWrap() {
}


inline uint32_t AsyncWrap::async_flags() const {
return async_flags_;
inline uint32_t AsyncWrap::provider_type() const {
return provider_type_;
}


inline bool AsyncWrap::has_async_listener() {
return async_flags() & HAS_ASYNC_LISTENER;
return async_flags_ & HAS_ASYNC_LISTENER;
}


@@ -35,14 +35,37 @@ class AsyncWrap : public BaseObject {
HAS_ASYNC_LISTENER = 1
};

inline AsyncWrap(Environment* env, v8::Handle<v8::Object> object);
enum ProviderType {
PROVIDER_NONE = 1 << 0,
PROVIDER_CARES = 1 << 1,
PROVIDER_CONNECTWRAP = 1 << 2,
PROVIDER_CRYPTO = 1 << 3,
PROVIDER_FSEVENTWRAP = 1 << 4,
PROVIDER_GETADDRINFOREQWRAP = 1 << 5,
PROVIDER_PIPEWRAP = 1 << 6,
PROVIDER_PROCESSWRAP = 1 << 7,
PROVIDER_REQWRAP = 1 << 8,
PROVIDER_SHUTDOWNWRAP = 1 << 9,
PROVIDER_SIGNALWRAP = 1 << 10,
PROVIDER_STATWATCHER = 1 << 11,
PROVIDER_TCPWRAP = 1 << 12,
PROVIDER_TIMERWRAP = 1 << 13,
PROVIDER_TLSWRAP = 1 << 14,
PROVIDER_TTYWRAP = 1 << 15,
PROVIDER_UDPWRAP = 1 << 16,
PROVIDER_ZLIB = 1 << 17
};

inline ~AsyncWrap();
inline AsyncWrap(Environment* env,
v8::Handle<v8::Object> object,
ProviderType provider);

inline uint32_t async_flags() const;
inline ~AsyncWrap();

inline bool has_async_listener();

inline uint32_t provider_type() const;

// Only call these within a valid HandleScope.
inline v8::Handle<v8::Value> MakeCallback(const v8::Handle<v8::Function> cb,
int argc,
@@ -65,6 +88,7 @@ class AsyncWrap : public BaseObject {
v8::Handle<v8::Value>* argv);

uint32_t async_flags_;
uint32_t provider_type_;
};

} // namespace node
@@ -224,7 +224,7 @@ static Local<Array> HostentToNames(struct hostent* host) {
class QueryWrap : public AsyncWrap {
public:
QueryWrap(Environment* env, Local<Object> req_wrap_obj)
: AsyncWrap(env, req_wrap_obj) {
: AsyncWrap(env, req_wrap_obj, AsyncWrap::PROVIDER_CARES) {
}

virtual ~QueryWrap() {
@@ -997,7 +997,10 @@ static void GetAddrInfo(const FunctionCallbackInfo<Value>& args) {
abort();
}

GetAddrInfoReqWrap* req_wrap = new GetAddrInfoReqWrap(env, req_wrap_obj);
GetAddrInfoReqWrap* req_wrap =
new GetAddrInfoReqWrap(env,
req_wrap_obj,
AsyncWrap::PROVIDER_GETADDRINFOREQWRAP);

struct addrinfo hints;
memset(&hints, 0, sizeof(struct addrinfo));
@@ -126,6 +126,10 @@ inline bool Environment::AsyncListener::has_listener() const {
return fields_[kHasListener] > 0;
}

inline uint32_t Environment::AsyncListener::watched_providers() const {
return fields_[kWatchedProviders];
}

inline Environment::DomainFlag::DomainFlag() {
for (int i = 0; i < kFieldsCount; ++i) fields_[i] = 0;
}
@@ -253,6 +257,11 @@ inline bool Environment::has_async_listener() const {
return const_cast<Environment*>(this)->async_listener()->has_listener();
}

inline uint32_t Environment::watched_providers() const {
// The const_cast is okay, it doesn't violate conceptual const-ness.
return const_cast<Environment*>(this)->async_listener()->watched_providers();
}

inline bool Environment::in_domain() const {
// The const_cast is okay, it doesn't violate conceptual const-ness.
return using_domains() &&
@@ -191,13 +191,15 @@ class Environment {
inline uint32_t* fields();
inline int fields_count() const;
inline bool has_listener() const;
inline uint32_t watched_providers() const;

private:
friend class Environment; // So we can call the constructor.
inline AsyncListener();

enum Fields {
kHasListener,
kWatchedProviders,
kFieldsCount
};

@@ -272,6 +274,7 @@ class Environment {
inline uv_loop_t* event_loop() const;
inline bool has_async_listener() const;
inline bool in_domain() const;
inline uint32_t watched_providers() const;

static inline Environment* from_immediate_check_handle(uv_check_t* handle);
inline uv_check_t* immediate_check_handle();
@@ -65,7 +65,10 @@ class FSEventWrap: public HandleWrap {


FSEventWrap::FSEventWrap(Environment* env, Handle<Object> object)
: HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(&handle_)) {
: HandleWrap(env,
object,
reinterpret_cast<uv_handle_t*>(&handle_),
AsyncWrap::PROVIDER_FSEVENTWRAP) {
initialized_ = false;
}

@@ -90,8 +90,9 @@ void HandleWrap::Close(const FunctionCallbackInfo<Value>& args) {

HandleWrap::HandleWrap(Environment* env,
Handle<Object> object,
uv_handle_t* handle)
: AsyncWrap(env, object),
uv_handle_t* handle,
AsyncWrap::ProviderType provider)
: AsyncWrap(env, object, provider),
flags_(0),
handle__(handle) {
handle__->data = this;
@@ -62,7 +62,8 @@ class HandleWrap : public AsyncWrap {
protected:
HandleWrap(Environment* env,
v8::Handle<v8::Object> object,
uv_handle_t* handle);
uv_handle_t* handle,
AsyncWrap::ProviderType provider);
virtual ~HandleWrap();

private:
@@ -283,6 +283,7 @@

// Needs to be the same as src/env.h
var kHasListener = 0;
var kWatchedProviders = 1;

// Flags to determine what async listeners are available.
var HAS_CREATE_AL = 1 << 0;
@@ -351,7 +352,7 @@
for (i = 0; i < ccQueue.length; i++) {
queueItem = ccQueue[i];
queue[queue.length] = queueItem;
if ((queueItem.flags & HAS_CREATE_AL) === 0) {
if ((queueItem.callback_flags & HAS_CREATE_AL) === 0) {
data[queueItem.uid] = queueItem.data;
continue;
}
@@ -369,8 +370,8 @@
if (data[queueItem.uid] !== undefined)
continue;
queue[queue.length] = queueItem;
context._asyncFlags |= queueItem.flags;
if ((queueItem.flags & HAS_CREATE_AL) === 0) {
context._asyncFlags |= queueItem.callback_flags;
if ((queueItem.callback_flags & HAS_CREATE_AL) === 0) {
data[queueItem.uid] = queueItem.data;
continue;
}
@@ -397,7 +398,7 @@
inAsyncTick = true;
for (i = 0; i < queue.length; i++) {
queueItem = queue[i];
if ((queueItem.flags & HAS_BEFORE_AL) > 0)
if ((queueItem.callback_flags & HAS_BEFORE_AL) > 0)
queueItem.before(context, data[queueItem.uid]);
}
inAsyncTick = false;
@@ -418,7 +419,7 @@
inAsyncTick = true;
for (i = 0; i < queue.length; i++) {
queueItem = queue[i];
if ((queueItem.flags & HAS_AFTER_AL) > 0)
if ((queueItem.callback_flags & HAS_AFTER_AL) > 0)
queueItem.after(context, data[queueItem.uid]);
}
inAsyncTick = false;
@@ -445,7 +446,7 @@
var data = currentContext._asyncData;
for (i = 0; i < queue.length; i++) {
queueItem = queue[i];
if ((queueItem.flags & HAS_ERROR_AL) === 0)
if ((queueItem.callback_flags & HAS_ERROR_AL) === 0)
continue;
try {
threw = true;
@@ -469,7 +470,7 @@
if (asyncQueue) {
for (i = 0; i < asyncQueue.length; i++) {
queueItem = asyncQueue[i];
if ((queueItem.flags & HAS_ERROR_AL) === 0 ||
if ((queueItem.callback_flags & HAS_ERROR_AL) === 0 ||
(data && data[queueItem.uid] !== undefined))
continue;
try {
@@ -501,19 +502,19 @@
function AsyncListenerInst(callbacks, data) {
if (typeof callbacks.create === 'function') {
this.create = callbacks.create;
this.flags |= HAS_CREATE_AL;
this.callback_flags |= HAS_CREATE_AL;
}
if (typeof callbacks.before === 'function') {
this.before = callbacks.before;
this.flags |= HAS_BEFORE_AL;
this.callback_flags |= HAS_BEFORE_AL;
}
if (typeof callbacks.after === 'function') {
this.after = callbacks.after;
this.flags |= HAS_AFTER_AL;
this.callback_flags |= HAS_AFTER_AL;
}
if (typeof callbacks.error === 'function') {
this.error = callbacks.error;
this.flags |= HAS_ERROR_AL;
this.callback_flags |= HAS_ERROR_AL;
}

this.uid = ++alUid;
@@ -525,7 +526,7 @@
AsyncListenerInst.prototype.error = undefined;
AsyncListenerInst.prototype.data = undefined;
AsyncListenerInst.prototype.uid = 0;
AsyncListenerInst.prototype.flags = 0;
AsyncListenerInst.prototype.callback_flags = 0;

// Create new async listener object. Useful when instantiating a new
// object and want the listener instance, but not add it to the stack.
@@ -3498,7 +3498,7 @@ class PBKDF2Request : public AsyncWrap {
char* salt,
ssize_t iter,
ssize_t keylen)
: AsyncWrap(env, object),
: AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO),
digest_(digest),
error_(0),
passlen_(passlen),
@@ -3760,7 +3760,7 @@ void PBKDF2(const FunctionCallbackInfo<Value>& args) {
class RandomBytesRequest : public AsyncWrap {
public:
RandomBytesRequest(Environment* env, Local<Object> object, size_t size)
: AsyncWrap(env, object),
: AsyncWrap(env, object, AsyncWrap::PROVIDER_CRYPTO),
error_(0),
size_(size),
data_(static_cast<char*>(malloc(size))) {
@@ -297,7 +297,7 @@ class Connection : public SSLWrap<Connection>, public AsyncWrap {
SecureContext* sc,
SSLWrap<Connection>::Kind kind)
: SSLWrap<Connection>(env, sc, kind),
AsyncWrap(env, wrap),
AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO),
bio_read_(NULL),
bio_write_(NULL),
hello_offset_(0) {
@@ -583,7 +583,7 @@ class Certificate : public AsyncWrap {
static void ExportChallenge(const v8::FunctionCallbackInfo<v8::Value>& args);

Certificate(Environment* env, v8::Local<v8::Object> wrap)
: AsyncWrap(env, wrap) {
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_CRYPTO) {
MakeWeak<Certificate>(this);
}
};
@@ -66,7 +66,7 @@ static void Delete(uv_handle_t* handle) {


StatWatcher::StatWatcher(Environment* env, Local<Object> wrap)
: AsyncWrap(env, wrap),
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_STATWATCHER),
watcher_(new uv_fs_poll_t) {
MakeWeak<StatWatcher>(this);
uv_fs_poll_init(env->event_loop(), watcher_);
@@ -74,7 +74,7 @@ class ZCtx : public AsyncWrap {
public:

ZCtx(Environment* env, Local<Object> wrap, node_zlib_mode mode)
: AsyncWrap(env, wrap),
: AsyncWrap(env, wrap, AsyncWrap::PROVIDER_ZLIB),
chunk_size_(0),
dictionary_(NULL),
dictionary_len_(0),
@@ -128,7 +128,10 @@ void PipeWrap::New(const FunctionCallbackInfo<Value>& args) {


PipeWrap::PipeWrap(Environment* env, Handle<Object> object, bool ipc)
: StreamWrap(env, object, reinterpret_cast<uv_stream_t*>(&handle_)) {
: StreamWrap(env,
object,
reinterpret_cast<uv_stream_t*>(&handle_),
AsyncWrap::PROVIDER_PIPEWRAP) {
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.
@@ -275,7 +278,9 @@ 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(env, req_wrap_obj);
ConnectWrap* req_wrap = new ConnectWrap(env,
req_wrap_obj,
AsyncWrap::PROVIDER_CONNECTWRAP);
uv_pipe_connect(&req_wrap->req_,
&wrap->handle_,
*name,
@@ -78,7 +78,10 @@ class ProcessWrap : public HandleWrap {
}

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

~ProcessWrap() {
@@ -37,8 +37,10 @@ extern QUEUE req_wrap_queue;
template <typename T>
class ReqWrap : public AsyncWrap {
public:
ReqWrap(Environment* env, v8::Handle<v8::Object> object)
: AsyncWrap(env, object) {
ReqWrap(Environment* env,
v8::Handle<v8::Object> object,
AsyncWrap::ProviderType provider = AsyncWrap::PROVIDER_REQWRAP)
: AsyncWrap(env, object, AsyncWrap::PROVIDER_REQWRAP) {
if (env->in_domain())
object->Set(env->domain_string(), env->domain_array()->Get(0));

@@ -72,7 +72,10 @@ class SignalWrap : public HandleWrap {
}

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