inline AsyncWrap::AsyncWrap(Environment* env,
v8::Handle<v8::Object> object,
- ProviderType provider)
+ ProviderType provider,
+ AsyncWrap* parent)
: BaseObject(env, object),
provider_type_(provider) {
}
inline AsyncWrap(Environment* env,
v8::Handle<v8::Object> object,
- ProviderType provider);
+ ProviderType provider,
+ AsyncWrap* parent = nullptr);
inline virtual ~AsyncWrap() override = default;
HandleWrap::HandleWrap(Environment* env,
Handle<Object> object,
uv_handle_t* handle,
- AsyncWrap::ProviderType provider)
- : AsyncWrap(env, object, provider),
+ AsyncWrap::ProviderType provider,
+ AsyncWrap* parent)
+ : AsyncWrap(env, object, provider, parent),
flags_(0),
handle__(handle) {
handle__->data = this;
HandleWrap(Environment* env,
v8::Handle<v8::Object> object,
uv_handle_t* handle,
- AsyncWrap::ProviderType provider);
+ AsyncWrap::ProviderType provider,
+ AsyncWrap* parent = nullptr);
virtual ~HandleWrap() override;
private:
#include "pipe_wrap.h"
+#include "async-wrap.h"
#include "env.h"
#include "env-inl.h"
#include "handle_wrap.h"
using v8::Boolean;
using v8::Context;
using v8::EscapableHandleScope;
+using v8::External;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
}
-Local<Object> PipeWrap::Instantiate(Environment* env) {
+Local<Object> PipeWrap::Instantiate(Environment* env, AsyncWrap* parent) {
EscapableHandleScope handle_scope(env->isolate());
CHECK_EQ(false, env->pipe_constructor_template().IsEmpty());
Local<Function> constructor = env->pipe_constructor_template()->GetFunction();
CHECK_EQ(false, constructor.IsEmpty());
- Local<Object> instance = constructor->NewInstance();
+ Local<Value> ptr = External::New(env->isolate(), parent);
+ Local<Object> instance = constructor->NewInstance(1, &ptr);
CHECK_EQ(false, instance.IsEmpty());
return handle_scope.Escape(instance);
}
// normal function.
CHECK(args.IsConstructCall());
Environment* env = Environment::GetCurrent(args);
- new PipeWrap(env, args.This(), args[0]->IsTrue());
+ if (args[0]->IsExternal()) {
+ void* ptr = args[0].As<External>()->Value();
+ new PipeWrap(env, args.This(), false, static_cast<AsyncWrap*>(ptr));
+ } else {
+ new PipeWrap(env, args.This(), args[0]->IsTrue(), nullptr);
+ }
}
-PipeWrap::PipeWrap(Environment* env, Handle<Object> object, bool ipc)
+PipeWrap::PipeWrap(Environment* env,
+ Handle<Object> object,
+ bool ipc,
+ AsyncWrap* parent)
: StreamWrap(env,
object,
reinterpret_cast<uv_stream_t*>(&handle_),
- AsyncWrap::PROVIDER_PIPEWRAP) {
+ AsyncWrap::PROVIDER_PIPEWRAP,
+ parent) {
int r = uv_pipe_init(env->event_loop(), &handle_, ipc);
CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
// Suggestion: uv_pipe_init() returns void.
}
// Instanciate the client javascript object and handle.
- Local<Object> client_obj = Instantiate(env);
+ Local<Object> client_obj = Instantiate(env, pipe_wrap);
// Unwrap the client javascript object.
PipeWrap* wrap = Unwrap<PipeWrap>(client_obj);
#ifndef SRC_PIPE_WRAP_H_
#define SRC_PIPE_WRAP_H_
+#include "async-wrap.h"
#include "env.h"
#include "stream_wrap.h"
public:
uv_pipe_t* UVHandle();
- static v8::Local<v8::Object> Instantiate(Environment* env);
+ static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
private:
- PipeWrap(Environment* env, v8::Handle<v8::Object> object, bool ipc);
+ PipeWrap(Environment* env,
+ v8::Handle<v8::Object> object,
+ bool ipc,
+ AsyncWrap* parent);
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
static void Bind(const v8::FunctionCallbackInfo<v8::Value>& args);
StreamWrap::StreamWrap(Environment* env,
Local<Object> object,
uv_stream_t* stream,
- AsyncWrap::ProviderType provider)
- : HandleWrap(env, object, reinterpret_cast<uv_handle_t*>(stream), provider),
+ AsyncWrap::ProviderType provider,
+ AsyncWrap* parent)
+ : HandleWrap(env,
+ object,
+ reinterpret_cast<uv_handle_t*>(stream),
+ provider,
+ parent),
stream_(stream),
default_callbacks_(this),
callbacks_(&default_callbacks_),
template <class WrapType, class UVType>
-static Local<Object> AcceptHandle(Environment* env, uv_stream_t* pipe) {
+static Local<Object> AcceptHandle(Environment* env,
+ uv_stream_t* pipe,
+ AsyncWrap* parent) {
EscapableHandleScope scope(env->isolate());
Local<Object> wrap_obj;
UVType* handle;
- wrap_obj = WrapType::Instantiate(env);
+ wrap_obj = WrapType::Instantiate(env, parent);
if (wrap_obj.IsEmpty())
return Local<Object>();
Local<Object> pending_obj;
if (pending == UV_TCP) {
- pending_obj = AcceptHandle<TCPWrap, uv_tcp_t>(env, handle);
+ pending_obj = AcceptHandle<TCPWrap, uv_tcp_t>(env, handle, wrap());
} else if (pending == UV_NAMED_PIPE) {
- pending_obj = AcceptHandle<PipeWrap, uv_pipe_t>(env, handle);
+ pending_obj = AcceptHandle<PipeWrap, uv_pipe_t>(env, handle, wrap());
} else if (pending == UV_UDP) {
- pending_obj = AcceptHandle<UDPWrap, uv_udp_t>(env, handle);
+ pending_obj = AcceptHandle<UDPWrap, uv_udp_t>(env, handle, wrap());
} else {
CHECK_EQ(pending, UV_UNKNOWN_HANDLE);
}
StreamWrap(Environment* env,
v8::Local<v8::Object> object,
uv_stream_t* stream,
- AsyncWrap::ProviderType provider);
+ AsyncWrap::ProviderType provider,
+ AsyncWrap* parent = nullptr);
~StreamWrap() {
if (!callbacks_gc_ && callbacks_ != &default_callbacks_) {
using v8::Boolean;
using v8::Context;
using v8::EscapableHandleScope;
+using v8::External;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
}
-Local<Object> TCPWrap::Instantiate(Environment* env) {
+Local<Object> TCPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
EscapableHandleScope handle_scope(env->isolate());
CHECK_EQ(env->tcp_constructor_template().IsEmpty(), false);
Local<Function> constructor = env->tcp_constructor_template()->GetFunction();
CHECK_EQ(constructor.IsEmpty(), false);
- Local<Object> instance = constructor->NewInstance();
+ Local<Value> ptr = External::New(env->isolate(), parent);
+ Local<Object> instance = constructor->NewInstance(1, &ptr);
CHECK_EQ(instance.IsEmpty(), false);
return handle_scope.Escape(instance);
}
// normal function.
CHECK(args.IsConstructCall());
Environment* env = Environment::GetCurrent(args);
- TCPWrap* wrap = new TCPWrap(env, args.This());
+ TCPWrap* wrap;
+ if (args.Length() == 0) {
+ wrap = new TCPWrap(env, args.This(), nullptr);
+ } else if (args[0]->IsExternal()) {
+ void* ptr = args[0].As<External>()->Value();
+ wrap = new TCPWrap(env, args.This(), static_cast<AsyncWrap*>(ptr));
+ } else {
+ UNREACHABLE();
+ }
CHECK(wrap);
}
-TCPWrap::TCPWrap(Environment* env, Handle<Object> object)
+TCPWrap::TCPWrap(Environment* env, Handle<Object> object, AsyncWrap* parent)
: StreamWrap(env,
object,
reinterpret_cast<uv_stream_t*>(&handle_),
- AsyncWrap::PROVIDER_TCPWRAP) {
+ AsyncWrap::PROVIDER_TCPWRAP,
+ parent) {
int r = uv_tcp_init(env->event_loop(), &handle_);
CHECK_EQ(r, 0); // How do we proxy this error up to javascript?
// Suggestion: uv_tcp_init() returns void.
if (status == 0) {
// Instantiate the client javascript object and handle.
- Local<Object> client_obj = Instantiate(env);
+ Local<Object> client_obj =
+ Instantiate(env, static_cast<AsyncWrap*>(tcp_wrap));
// Unwrap the client javascript object.
TCPWrap* wrap = Unwrap<TCPWrap>(client_obj);
#ifndef SRC_TCP_WRAP_H_
#define SRC_TCP_WRAP_H_
+#include "async-wrap.h"
#include "env.h"
#include "stream_wrap.h"
class TCPWrap : public StreamWrap {
public:
- static v8::Local<v8::Object> Instantiate(Environment* env);
+ static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
static void Initialize(v8::Handle<v8::Object> target,
v8::Handle<v8::Value> unused,
v8::Handle<v8::Context> context);
uv_tcp_t* UVHandle();
private:
- TCPWrap(Environment* env, v8::Handle<v8::Object> object);
+ TCPWrap(Environment* env, v8::Handle<v8::Object> object, AsyncWrap* parent);
~TCPWrap();
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
namespace node {
using v8::Context;
+using v8::EscapableHandleScope;
+using v8::External;
using v8::Function;
using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
}
-UDPWrap::UDPWrap(Environment* env, Handle<Object> object)
+UDPWrap::UDPWrap(Environment* env, Handle<Object> object, AsyncWrap* parent)
: HandleWrap(env,
object,
reinterpret_cast<uv_handle_t*>(&handle_),
void UDPWrap::New(const FunctionCallbackInfo<Value>& args) {
CHECK(args.IsConstructCall());
Environment* env = Environment::GetCurrent(args);
- new UDPWrap(env, args.This());
+ if (args.Length() == 0) {
+ new UDPWrap(env, args.This(), nullptr);
+ } else if (args[0]->IsExternal()) {
+ new UDPWrap(env,
+ args.This(),
+ static_cast<AsyncWrap*>(args[0].As<External>()->Value()));
+ } else {
+ UNREACHABLE();
+ }
}
}
-Local<Object> UDPWrap::Instantiate(Environment* env) {
+Local<Object> UDPWrap::Instantiate(Environment* env, AsyncWrap* parent) {
// If this assert fires then Initialize hasn't been called yet.
CHECK_EQ(env->udp_constructor_function().IsEmpty(), false);
- return env->udp_constructor_function()->NewInstance();
+ EscapableHandleScope scope(env->isolate());
+ Local<Value> ptr = External::New(env->isolate(), parent);
+ return scope.Escape(env->udp_constructor_function()->NewInstance(1, &ptr));
}
#ifndef SRC_UDP_WRAP_H_
#define SRC_UDP_WRAP_H_
+#include "async-wrap.h"
#include "env.h"
#include "handle_wrap.h"
#include "req_wrap.h"
static void SetBroadcast(const v8::FunctionCallbackInfo<v8::Value>& args);
static void SetTTL(const v8::FunctionCallbackInfo<v8::Value>& args);
- static v8::Local<v8::Object> Instantiate(Environment* env);
+ static v8::Local<v8::Object> Instantiate(Environment* env, AsyncWrap* parent);
uv_udp_t* UVHandle();
private:
- UDPWrap(Environment* env, v8::Handle<v8::Object> object);
+ UDPWrap(Environment* env, v8::Handle<v8::Object> object, AsyncWrap* parent);
static void DoBind(const v8::FunctionCallbackInfo<v8::Value>& args,
int family);