mirror of
https://github.com/nodejs/node-v0.x-archive.git
synced 2026-04-28 03:01:10 -04:00
Simplify and cleanup ObjectWrap.
Simplify and inline ObjectWrap::Wrap
Inline and clean up ObjectWrap::Unwrap
Move ObjectWrap into its own file.
Remove handle from ObjectWrap constructor. add obj->Wrap(handle)
Simplify Attach/Detach in ObjectWrap
Remove ObjectWrap::InformV8ofAllocation. (Too messy/complex.)
This commit is contained in:
@@ -82,8 +82,8 @@ Promise::Create (void)
|
||||
Local<Object> 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);
|
||||
|
||||
@@ -10,20 +10,17 @@ class EventEmitter : public ObjectWrap {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
virtual size_t size (void) { return sizeof(EventEmitter); };
|
||||
|
||||
bool Emit (const char *type, int argc, v8::Handle<v8::Value> argv[]);
|
||||
|
||||
protected:
|
||||
EventEmitter (v8::Handle<v8::Object> handle)
|
||||
: ObjectWrap(handle) { }
|
||||
EventEmitter () : ObjectWrap() { }
|
||||
};
|
||||
|
||||
class Promise : public EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
virtual size_t size (void) { return sizeof(Promise); };
|
||||
|
||||
bool EmitSuccess (int argc, v8::Handle<v8::Value> argv[]);
|
||||
bool EmitError (int argc, v8::Handle<v8::Value> argv[]);
|
||||
@@ -34,7 +31,7 @@ class Promise : public EventEmitter {
|
||||
|
||||
protected:
|
||||
|
||||
Promise (v8::Handle<v8::Object> handle) : EventEmitter(handle) { }
|
||||
Promise () : EventEmitter() { }
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
|
||||
26
src/http.cc
26
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<Object> 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<FunctionTemplate> 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();
|
||||
}
|
||||
|
||||
21
src/http.h
21
src/http.h
@@ -14,14 +14,23 @@ public:
|
||||
static v8::Persistent<v8::FunctionTemplate> client_constructor_template;
|
||||
static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
|
||||
|
||||
virtual size_t size (void) { return sizeof(HTTPConnection); };
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> NewClient (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> NewServer (const v8::Arguments& args);
|
||||
|
||||
HTTPConnection (v8::Handle<v8::Object> 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<v8::Object> target);
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
|
||||
virtual size_t size (void) { return sizeof(HTTPServer); };
|
||||
|
||||
protected:
|
||||
static v8::Handle<v8::Value> New (const v8::Arguments& args);
|
||||
|
||||
HTTPServer (v8::Handle<v8::Object> handle) : Server(handle) {}
|
||||
HTTPServer (void) : Server() {}
|
||||
|
||||
v8::Handle<v8::FunctionTemplate> GetConnectionTemplate (void);
|
||||
Connection* UnwrapConnection (v8::Local<v8::Object> connection);
|
||||
|
||||
40
src/net.cc
40
src/net.cc
@@ -96,17 +96,6 @@ Connection::ReadyStateGetter (Local<String> property, const AccessorInfo& info)
|
||||
return ThrowException(String::New("This shouldn't happen."));
|
||||
}
|
||||
|
||||
Connection::Connection (Handle<Object> 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<Object> target)
|
||||
target->Set(String::NewSymbol("Server"), constructor_template->GetFunction());
|
||||
}
|
||||
|
||||
Server::Server (Handle<Object> handle)
|
||||
: EventEmitter(handle)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
#if 0
|
||||
// TODO SetOptions
|
||||
handle_->SetHiddenValue(CONNECTION_HANDLER_SYMBOL, connection_handler);
|
||||
|
||||
int backlog = 1024; // default value
|
||||
Local<Value> 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<String>
|
||||
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();
|
||||
}
|
||||
|
||||
23
src/net.h
23
src/net.h
@@ -14,8 +14,6 @@ class Connection : public EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
virtual size_t size (void) { return sizeof(Connection); };
|
||||
|
||||
protected:
|
||||
/* v8 interface */
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
@@ -31,8 +29,16 @@ protected:
|
||||
static v8::Handle<v8::Value> ReadyStateGetter (v8::Local<v8::String> _,
|
||||
const v8::AccessorInfo& info);
|
||||
|
||||
Connection (v8::Handle<v8::Object> 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<v8::Object> target);
|
||||
|
||||
virtual size_t size (void) { return sizeof(Server); };
|
||||
|
||||
protected:
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
static v8::Handle<v8::Value> New (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Listen (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Close (const v8::Arguments& args);
|
||||
|
||||
Server (v8::Handle<v8::Object> 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) {
|
||||
|
||||
77
src/node.cc
77
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<Object> handle)
|
||||
{
|
||||
// TODO throw exception if it's already set
|
||||
HandleScope scope;
|
||||
handle_ = Persistent<Object>::New(handle);
|
||||
|
||||
Handle<External> 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<Object> 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> value = handle->GetInternalField(0);
|
||||
if (value.IsEmpty()) {
|
||||
fprintf(stderr, "Tried to unwrap object with empty internal field.\n");
|
||||
return NULL;
|
||||
}
|
||||
Handle<External> field = Handle<External>::Cast(value);
|
||||
return field->Value();
|
||||
}
|
||||
|
||||
void
|
||||
ObjectWrap::MakeWeak (Persistent<Value> value, void *data)
|
||||
{
|
||||
ObjectWrap *obj = static_cast<ObjectWrap*> (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)
|
||||
{
|
||||
|
||||
39
src/node.h
39
src/node.h
@@ -6,9 +6,9 @@
|
||||
#include <v8.h>
|
||||
#include <oi_socket.h>
|
||||
|
||||
namespace node {
|
||||
#include "object_wrap.h"
|
||||
|
||||
#define NODE_UNWRAP(type, value) static_cast<type*>(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<v8::Value> encoding_v);
|
||||
void FatalException (v8::TryCatch &try_catch);
|
||||
oi_buf * buf_new (size_t size);
|
||||
|
||||
class ObjectWrap {
|
||||
public:
|
||||
ObjectWrap (v8::Handle<v8::Object> 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<v8::Object> 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<v8::Object> handle_;
|
||||
|
||||
private:
|
||||
static void MakeWeak (v8::Persistent<v8::Value> _, void *data);
|
||||
int attach_count_;
|
||||
bool weak_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
#endif // node_h
|
||||
|
||||
80
src/object_wrap.h
Normal file
80
src/object_wrap.h
Normal file
@@ -0,0 +1,80 @@
|
||||
#ifndef object_wrap_h
|
||||
#define object_wrap_h
|
||||
|
||||
#include <v8.h>
|
||||
#include <assert.h>
|
||||
|
||||
namespace node {
|
||||
|
||||
#define NODE_UNWRAP(type, value) static_cast<type*>(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<v8::Object> handle)
|
||||
{
|
||||
assert(!handle.IsEmpty());
|
||||
assert(handle->InternalFieldCount() == 1);
|
||||
return v8::Handle<v8::External>::Cast(
|
||||
handle->GetInternalField(0))->Value();
|
||||
}
|
||||
|
||||
inline void Wrap(v8::Handle<v8::Object> handle)
|
||||
{
|
||||
assert(handle_.IsEmpty());
|
||||
assert(handle->InternalFieldCount() > 0);
|
||||
handle_ = v8::Persistent<v8::Object>::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<v8::Object> handle_;
|
||||
|
||||
private:
|
||||
static void MakeWeak (v8::Persistent<v8::Value> value, void *data) {
|
||||
ObjectWrap *obj = static_cast<ObjectWrap*>(data);
|
||||
assert(value == obj->handle_);
|
||||
obj->weak_ = true;
|
||||
if (!obj->attached_) delete obj;
|
||||
}
|
||||
bool attached_;
|
||||
bool weak_;
|
||||
};
|
||||
|
||||
} // namespace node
|
||||
#endif // object_wrap_h
|
||||
@@ -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<Object> handle)
|
||||
: EventEmitter(handle)
|
||||
Process::Process ()
|
||||
: EventEmitter()
|
||||
{
|
||||
ev_init(&stdout_watcher_, Process::OnOutput);
|
||||
stdout_watcher_.data = this;
|
||||
|
||||
@@ -12,7 +12,6 @@ namespace node {
|
||||
class Process : EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
virtual size_t size (void) { return sizeof(Process); }
|
||||
|
||||
protected:
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
@@ -23,7 +22,7 @@ class Process : EventEmitter {
|
||||
static v8::Handle<v8::Value> Kill (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> PIDGetter (v8::Local<v8::String> _, const v8::AccessorInfo& info);
|
||||
|
||||
Process(v8::Handle<v8::Object> handle);
|
||||
Process();
|
||||
~Process();
|
||||
|
||||
int Spawn (const char *command);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -12,12 +12,10 @@ class Timer : EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
virtual size_t size (void) { return sizeof(Timer); }
|
||||
|
||||
protected:
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
|
||||
Timer (v8::Handle<v8::Object> handle) : EventEmitter (handle) { }
|
||||
Timer () : EventEmitter () { }
|
||||
~Timer();
|
||||
|
||||
static v8::Handle<v8::Value> New (const v8::Arguments& args);
|
||||
|
||||
Reference in New Issue
Block a user