diff --git a/src/events.cc b/src/events.cc index f39d8e796f..9967c1cb36 100644 --- a/src/events.cc +++ b/src/events.cc @@ -82,8 +82,8 @@ Promise::Create (void) Local handle = Promise::constructor_template->GetFunction()->NewInstance(); - Promise *promise = new Promise(handle); - ObjectWrap::InformV8ofAllocation(promise); + Promise *promise = new Promise(); + promise->Wrap(handle); promise->Attach(); ev_ref(EV_DEFAULT_UC); diff --git a/src/events.h b/src/events.h index abd1eda97e..ca3d5fdeab 100644 --- a/src/events.h +++ b/src/events.h @@ -10,20 +10,17 @@ class EventEmitter : public ObjectWrap { public: static void Initialize (v8::Handle target); static v8::Persistent constructor_template; - virtual size_t size (void) { return sizeof(EventEmitter); }; bool Emit (const char *type, int argc, v8::Handle argv[]); protected: - EventEmitter (v8::Handle handle) - : ObjectWrap(handle) { } + EventEmitter () : ObjectWrap() { } }; class Promise : public EventEmitter { public: static void Initialize (v8::Handle target); static v8::Persistent constructor_template; - virtual size_t size (void) { return sizeof(Promise); }; bool EmitSuccess (int argc, v8::Handle argv[]); bool EmitError (int argc, v8::Handle argv[]); @@ -34,7 +31,7 @@ class Promise : public EventEmitter { protected: - Promise (v8::Handle handle) : EventEmitter(handle) { } + Promise () : EventEmitter() { } }; } // namespace node diff --git a/src/http.cc b/src/http.cc index 42fafb636c..6261a90a6a 100644 --- a/src/http.cc +++ b/src/http.cc @@ -59,8 +59,8 @@ HTTPConnection::NewClient (const Arguments& args) { HandleScope scope; - HTTPConnection *connection = new HTTPConnection(args.This(), HTTP_RESPONSE); - ObjectWrap::InformV8ofAllocation(connection); + HTTPConnection *connection = new HTTPConnection(HTTP_RESPONSE); + connection->Wrap(args.This()); return args.This(); } @@ -70,8 +70,8 @@ HTTPConnection::NewServer (const Arguments& args) { HandleScope scope; - HTTPConnection *connection = new HTTPConnection(args.This(), HTTP_REQUEST); - ObjectWrap::InformV8ofAllocation(connection); + HTTPConnection *connection = new HTTPConnection(HTTP_REQUEST); + connection->Wrap(args.This()); return args.This(); } @@ -221,20 +221,6 @@ HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len) return 0; } -HTTPConnection::HTTPConnection (Handle handle, enum http_parser_type type) - : Connection(handle) -{ - http_parser_init (&parser_, type); - parser_.on_message_begin = on_message_begin; - parser_.on_uri = on_uri; - parser_.on_header_field = on_header_field; - parser_.on_header_value = on_header_value; - parser_.on_headers_complete = on_headers_complete; - parser_.on_body = on_body; - parser_.on_message_complete = on_message_complete; - parser_.data = this; -} - Persistent HTTPServer::constructor_template; void @@ -254,8 +240,8 @@ HTTPServer::New (const Arguments& args) { HandleScope scope; - HTTPServer *s = new HTTPServer(args.This()); - ObjectWrap::InformV8ofAllocation(s); + HTTPServer *server = new HTTPServer(); + server->Wrap(args.This()); return args.This(); } diff --git a/src/http.h b/src/http.h index ee1e81012f..02392d73ed 100644 --- a/src/http.h +++ b/src/http.h @@ -14,14 +14,23 @@ public: static v8::Persistent client_constructor_template; static v8::Persistent server_constructor_template; - virtual size_t size (void) { return sizeof(HTTPConnection); }; - protected: static v8::Handle NewClient (const v8::Arguments& args); static v8::Handle NewServer (const v8::Arguments& args); - HTTPConnection (v8::Handle handle, - enum http_parser_type type); + HTTPConnection (enum http_parser_type type) + : Connection() + { + http_parser_init (&parser_, type); + parser_.on_message_begin = on_message_begin; + parser_.on_uri = on_uri; + parser_.on_header_field = on_header_field; + parser_.on_header_value = on_header_value; + parser_.on_headers_complete = on_headers_complete; + parser_.on_body = on_body; + parser_.on_message_complete = on_message_complete; + parser_.data = this; + } void OnReceive (const void *buf, size_t len); @@ -43,12 +52,10 @@ public: static void Initialize (v8::Handle target); static v8::Persistent constructor_template; - virtual size_t size (void) { return sizeof(HTTPServer); }; - protected: static v8::Handle New (const v8::Arguments& args); - HTTPServer (v8::Handle handle) : Server(handle) {} + HTTPServer (void) : Server() {} v8::Handle GetConnectionTemplate (void); Connection* UnwrapConnection (v8::Local connection); diff --git a/src/net.cc b/src/net.cc index 20e62083a7..61bcbb4abe 100644 --- a/src/net.cc +++ b/src/net.cc @@ -96,17 +96,6 @@ Connection::ReadyStateGetter (Local property, const AccessorInfo& info) return ThrowException(String::New("This shouldn't happen.")); } -Connection::Connection (Handle handle) - : EventEmitter(handle) -{ - encoding_ = RAW; - - host_ = NULL; - port_ = NULL; - - Init(); -} - void Connection::Init (void) { @@ -121,7 +110,6 @@ Connection::Init (void) socket_.data = this; } - Connection::~Connection () { static int i = 0; @@ -138,8 +126,8 @@ Connection::New (const Arguments& args) { HandleScope scope; - Connection *c = new Connection(args.This()); - ObjectWrap::InformV8ofAllocation(c); + Connection *connection = new Connection(); + connection->Wrap(args.This()); return args.This(); } @@ -492,26 +480,6 @@ Server::Initialize (Handle target) target->Set(String::NewSymbol("Server"), constructor_template->GetFunction()); } -Server::Server (Handle handle) - : EventEmitter(handle) -{ - HandleScope scope; - -#if 0 - // TODO SetOptions - handle_->SetHiddenValue(CONNECTION_HANDLER_SYMBOL, connection_handler); - - int backlog = 1024; // default value - Local backlog_v = options->Get(String::NewSymbol("backlog")); - if (backlog_v->IsInt32()) { - backlog = backlog_v->IntegerValue(); - } -#endif - - oi_server_init(&server_, 1024); - server_.on_connection = Server::on_connection; - server_.data = this; -} static Local GetAddressString (struct sockaddr *addr) @@ -589,8 +557,8 @@ Server::New (const Arguments& args) { HandleScope scope; - Server *a = new Server(args.This()); - ObjectWrap::InformV8ofAllocation(a); + Server *server = new Server(); + server->Wrap(args.This()); return args.This(); } diff --git a/src/net.h b/src/net.h index e597ee9e6b..1449eb6fb4 100644 --- a/src/net.h +++ b/src/net.h @@ -14,8 +14,6 @@ class Connection : public EventEmitter { public: static void Initialize (v8::Handle target); - virtual size_t size (void) { return sizeof(Connection); }; - protected: /* v8 interface */ static v8::Persistent constructor_template; @@ -31,8 +29,16 @@ protected: static v8::Handle ReadyStateGetter (v8::Local _, const v8::AccessorInfo& info); - Connection (v8::Handle handle); - virtual ~Connection (); + Connection (void) : EventEmitter() + { + encoding_ = RAW; + + host_ = NULL; + port_ = NULL; + + Init(); + } + virtual ~Connection (void); int Connect (struct addrinfo *address) { return oi_socket_connect (&socket_, address); @@ -110,15 +116,18 @@ class Server : public EventEmitter { public: static void Initialize (v8::Handle target); - virtual size_t size (void) { return sizeof(Server); }; - protected: static v8::Persistent constructor_template; static v8::Handle New (const v8::Arguments& args); static v8::Handle Listen (const v8::Arguments& args); static v8::Handle Close (const v8::Arguments& args); - Server (v8::Handle handle); + Server (void) : EventEmitter() + { + oi_server_init(&server_, 1024); + server_.on_connection = Server::on_connection; + server_.data = this; + } virtual ~Server () { Close(); } int Listen (struct addrinfo *address) { diff --git a/src/node.cc b/src/node.cc index 988eb082ae..a60aa784b4 100644 --- a/src/node.cc +++ b/src/node.cc @@ -23,83 +23,6 @@ using namespace v8; using namespace node; using namespace std; -ObjectWrap::~ObjectWrap ( ) -{ - handle_->SetInternalField(0, Undefined()); - handle_.Dispose(); - handle_.Clear(); -} - -ObjectWrap::ObjectWrap (Handle handle) -{ - // TODO throw exception if it's already set - HandleScope scope; - handle_ = Persistent::New(handle); - - Handle external = External::New(this); - handle_->SetInternalField(0, external); - handle_.MakeWeak(this, ObjectWrap::MakeWeak); - - attach_count_ = 0; - weak_ = false; -} - -void -ObjectWrap::Attach () -{ - attach_count_ += 1; -} - -void -ObjectWrap::Detach () -{ - if (attach_count_ > 0) attach_count_ -= 1; - - if (weak_ && attach_count_ == 0) { - V8::AdjustAmountOfExternalAllocatedMemory(-size()); - delete this; - } -} - -void* -ObjectWrap::Unwrap (Handle handle) -{ - HandleScope scope; - if (handle.IsEmpty()) { - fprintf(stderr, "Node: Tried to unwrap empty object.\n"); - return NULL; - } - if ( handle->InternalFieldCount() == 0) { - fprintf(stderr, "Node: Tried to unwrap object without internal fields.\n"); - return NULL; - } - Local value = handle->GetInternalField(0); - if (value.IsEmpty()) { - fprintf(stderr, "Tried to unwrap object with empty internal field.\n"); - return NULL; - } - Handle field = Handle::Cast(value); - return field->Value(); -} - -void -ObjectWrap::MakeWeak (Persistent value, void *data) -{ - ObjectWrap *obj = static_cast (data); - - assert(value == obj->handle_); - - obj->weak_ = true; - if (obj->attach_count_ == 0) - delete obj; -} - -void -ObjectWrap::InformV8ofAllocation (ObjectWrap *obj) -{ - v8::V8::AdjustAmountOfExternalAllocatedMemory(obj->size()); -} - static void buf_free (oi_buf *b) { diff --git a/src/node.h b/src/node.h index 00dbd2ff91..e172d3f764 100644 --- a/src/node.h +++ b/src/node.h @@ -6,9 +6,9 @@ #include #include -namespace node { +#include "object_wrap.h" -#define NODE_UNWRAP(type, value) static_cast(node::ObjectWrap::Unwrap(value)) +namespace node { #define NODE_DEFINE_CONSTANT(target, constant) \ (target)->Set(v8::String::NewSymbol(#constant), \ @@ -32,40 +32,5 @@ enum encoding ParseEncoding (v8::Handle encoding_v); void FatalException (v8::TryCatch &try_catch); oi_buf * buf_new (size_t size); -class ObjectWrap { -public: - ObjectWrap (v8::Handle handle); - virtual ~ObjectWrap ( ); - - virtual size_t size (void) = 0; - - /* This must be called after each new ObjectWrap creation! */ - static void InformV8ofAllocation (node::ObjectWrap *obj); - -protected: - static void* Unwrap (v8::Handle handle); - - /* Attach() marks the object as being attached to an event loop. - * Attached objects will not be garbage collected, even if - * all references are lost. - */ - void Attach(); - - /* Detach() marks an object as detached from the event loop. This is its - * default state. When an object with a "weak" reference changes from - * attached to detached state it will be freed. Be careful not to access - * the object after making this call as it might be gone! - * (A "weak reference" is v8 terminology for an object that only has a - * persistant handle.) - */ - void Detach(); - v8::Persistent handle_; - -private: - static void MakeWeak (v8::Persistent _, void *data); - int attach_count_; - bool weak_; -}; - } // namespace node #endif // node_h diff --git a/src/object_wrap.h b/src/object_wrap.h new file mode 100644 index 0000000000..619cda151b --- /dev/null +++ b/src/object_wrap.h @@ -0,0 +1,80 @@ +#ifndef object_wrap_h +#define object_wrap_h + +#include +#include + +namespace node { + +#define NODE_UNWRAP(type, value) static_cast(node::ObjectWrap::Unwrap(value)) + +class ObjectWrap { +public: + ObjectWrap ( ) { + weak_ = false; + attached_ = false; + } + + virtual ~ObjectWrap ( ) { + if (!handle_.IsEmpty()) { + handle_->SetInternalField(0, v8::Undefined()); + handle_.Dispose(); + handle_.Clear(); + } + } + + protected: + static inline void* Unwrap (v8::Handle handle) + { + assert(!handle.IsEmpty()); + assert(handle->InternalFieldCount() == 1); + return v8::Handle::Cast( + handle->GetInternalField(0))->Value(); + } + + inline void Wrap(v8::Handle handle) + { + assert(handle_.IsEmpty()); + assert(handle->InternalFieldCount() > 0); + handle_ = v8::Persistent::New(handle); + handle_->SetInternalField(0, v8::External::New(this)); + handle_.MakeWeak(this, MakeWeak); + } + + /* Attach() marks the object as being attached to an event loop. + * Attached objects will not be garbage collected, even if + * all references are lost. + */ + void Attach() { + assert(!handle_.IsEmpty()); + attached_ = true; + } + + /* Detach() marks an object as detached from the event loop. This is its + * default state. When an object with a "weak" reference changes from + * attached to detached state it will be freed. Be careful not to access + * the object after making this call as it might be gone! + * (A "weak reference" is v8 terminology for an object that only has a + * persistant handle.) + */ + void Detach() { + assert(!handle_.IsEmpty()); + attached_ = false; + if (weak_) delete this; + } + + v8::Persistent handle_; + + private: + static void MakeWeak (v8::Persistent value, void *data) { + ObjectWrap *obj = static_cast(data); + assert(value == obj->handle_); + obj->weak_ = true; + if (!obj->attached_) delete obj; + } + bool attached_; + bool weak_; +}; + +} // namespace node +#endif // object_wrap_h diff --git a/src/process.cc b/src/process.cc index 85f2db7eb3..de930813cf 100644 --- a/src/process.cc +++ b/src/process.cc @@ -50,8 +50,8 @@ Process::New (const Arguments& args) { HandleScope scope; - Process *p = new Process(args.Holder()); - ObjectWrap::InformV8ofAllocation(p); + Process *p = new Process(); + p->Wrap(args.Holder()); return args.This(); } @@ -168,8 +168,8 @@ Process::Close (const Arguments& args) return process->Close() == 0 ? True() : False(); } -Process::Process (Handle handle) - : EventEmitter(handle) +Process::Process () + : EventEmitter() { ev_init(&stdout_watcher_, Process::OnOutput); stdout_watcher_.data = this; diff --git a/src/process.h b/src/process.h index 932d439fb4..a169ccce6b 100644 --- a/src/process.h +++ b/src/process.h @@ -12,7 +12,6 @@ namespace node { class Process : EventEmitter { public: static void Initialize (v8::Handle target); - virtual size_t size (void) { return sizeof(Process); } protected: static v8::Persistent constructor_template; @@ -23,7 +22,7 @@ class Process : EventEmitter { static v8::Handle Kill (const v8::Arguments& args); static v8::Handle PIDGetter (v8::Local _, const v8::AccessorInfo& info); - Process(v8::Handle handle); + Process(); ~Process(); int Spawn (const char *command); diff --git a/src/timer.cc b/src/timer.cc index 672732ef66..0f60fb6c14 100644 --- a/src/timer.cc +++ b/src/timer.cc @@ -81,8 +81,8 @@ Timer::New (const Arguments& args) { HandleScope scope; - Timer *t = new Timer(args.Holder()); - ObjectWrap::InformV8ofAllocation(t); + Timer *t = new Timer(); + t->Wrap(args.Holder()); return args.This(); } diff --git a/src/timer.h b/src/timer.h index f135e7e5f6..ddbf48bb2a 100644 --- a/src/timer.h +++ b/src/timer.h @@ -12,12 +12,10 @@ class Timer : EventEmitter { public: static void Initialize (v8::Handle target); - virtual size_t size (void) { return sizeof(Timer); } - protected: static v8::Persistent constructor_template; - Timer (v8::Handle handle) : EventEmitter (handle) { } + Timer () : EventEmitter () { } ~Timer(); static v8::Handle New (const v8::Arguments& args);