Browse Source

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.)
v0.7.4-release
Ryan 16 years ago
parent
commit
1fc4dce08b
  1. 4
      src/events.cc
  2. 7
      src/events.h
  3. 26
      src/http.cc
  4. 21
      src/http.h
  5. 40
      src/net.cc
  6. 23
      src/net.h
  7. 77
      src/node.cc
  8. 39
      src/node.h
  9. 80
      src/object_wrap.h
  10. 8
      src/process.cc
  11. 3
      src/process.h
  12. 4
      src/timer.cc
  13. 4
      src/timer.h

4
src/events.cc

@ -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);

7
src/events.h

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

8
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<Object> handle)
: EventEmitter(handle)
Process::Process ()
: EventEmitter()
{
ev_init(&stdout_watcher_, Process::OnOutput);
stdout_watcher_.data = this;

3
src/process.h

@ -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);

4
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();
}

4
src/timer.h

@ -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);

Loading…
Cancel
Save