From 2ecd7ffe54160b81a42b2c053126fa3bbaa2d72f Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 25 Jun 2009 19:13:20 +0200 Subject: [PATCH] in the middle putting in event code. broken. --- src/events.cc | 56 +++++++++++++++++++++++++++++++++++++ src/events.h | 21 ++++++++++++++ src/events.js | 33 ++++++++++++++++++++++ src/net.cc | 77 ++++++++++++--------------------------------------- src/net.h | 5 ++-- src/node.cc | 3 ++ src/node.js | 6 ++++ wscript | 8 +++++- 8 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 src/events.cc create mode 100644 src/events.h create mode 100644 src/events.js diff --git a/src/events.cc b/src/events.cc new file mode 100644 index 00000000000..b36db7d46bc --- /dev/null +++ b/src/events.cc @@ -0,0 +1,56 @@ +#include "events.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include /* inet_ntop */ +#include /* sockaddr_in, sockaddr_in6 */ + +using namespace v8; +using namespace node; + +Persistent EventEmitter::constructor_template; + +void +EventEmitter::Initialize (v8::Handle target) +{ + HandleScope scope; + + Local t = FunctionTemplate::New(); + constructor_template = Persistent::New(t); + + // All prototype methods are defined in events.js + + target->Set(String::NewSymbol("EventEmitter"), constructor_template->GetFunction()); +} + +bool +EventEmitter::Emit (const char *type, int argc, Handle argv[]) +{ + Local emit_v = handle_->Get(String::NewSymbol("emit")); + assert(emit_v->IsFunction()); + Local emit = Local::Cast(emit_v); + + Local event_args = Array::New(argc); + for (int i = 0; i < argc; i++) { + event_args->Set(Integer::New(i), argv[i]); + } + + Handle emit_argv[2] = { String::NewSymbol(type), event_args }; + + TryCatch try_catch; + + emit->Call(handle_, 2, emit_argv); + + if (try_catch.HasCaught()) { + FatalException(try_catch); + return false; + } + + return true; +} diff --git a/src/events.h b/src/events.h new file mode 100644 index 00000000000..1fe47cb0ec7 --- /dev/null +++ b/src/events.h @@ -0,0 +1,21 @@ +#ifndef node_events_h +#define node_events_h + +#include "node.h" +#include + +namespace node { + +class EventEmitter : public ObjectWrap { +public: + static void Initialize (v8::Handle target); + static v8::Persistent constructor_template; + + bool Emit (const char *type, int argc, v8::Handle argv[]); + + EventEmitter (v8::Handle handle) + : ObjectWrap(handle) { }; +}; + +} // namespace node +#endif diff --git a/src/events.js b/src/events.js new file mode 100644 index 00000000000..f665cec977a --- /dev/null +++ b/src/events.js @@ -0,0 +1,33 @@ +(function () { + +// node.EventEmitter is defined in src/events.cc +var emitter = node.EventEmitter.prototype; + +emitter.addListener = function (type, listener) { + if (!this._events) this._events = {}; + if (!this._events.hasOwnProperty(type)) this._events[type] = []; + this._events[type].push(listener); +}; + +emitter.listeners = function (type, listener) { + if (!this._events) this._events = {}; + if (!this._events.hasOwnProperty(type)) this._events[type] = []; + return this._events[type]; +}; + +/* This function is called often from C++. + * See events.cc + */ +emitter.emit = function (type, args) { + if (this["on" + type] instanceof Function) { + this["on" + type].apply(this, args); + } + if (!this._events) return; + if (!this._events.hasOwnProperty(type)) return; + for (var i = 0; i < this._events[type].length; i++) { + var listener = this._events[type][i]; + listener.apply(this, args); + } +}; + +})(); // end annonymous namespace diff --git a/src/net.cc b/src/net.cc index 04a7fa0176f..2e00351bc71 100644 --- a/src/net.cc +++ b/src/net.cc @@ -1,4 +1,5 @@ #include "net.h" +#include "events.h" #include #include @@ -18,21 +19,12 @@ using namespace node; #define RAW_SYMBOL String::NewSymbol("raw") #define ASCII_SYMBOL String::NewSymbol("ascii") -#define ON_RECEIVE_SYMBOL String::NewSymbol("onReceive") -#define ON_DISCONNECT_SYMBOL String::NewSymbol("onDisconnect") -#define ON_CONNECT_SYMBOL String::NewSymbol("onConnect") -#define ON_DRAIN_SYMBOL String::NewSymbol("onDrain") -#define ON_TIMEOUT_SYMBOL String::NewSymbol("onTimeout") -#define ON_ERROR_SYMBOL String::NewSymbol("onError") -#define ON_EOF_SYMBOL String::NewSymbol("onEOF") - #define ENCODING_SYMBOL String::NewSymbol("encoding") #define TIMEOUT_SYMBOL String::NewSymbol("timeout") #define SERVER_SYMBOL String::NewSymbol("server") #define REMOTE_ADDRESS_SYMBOL String::NewSymbol("remoteAddress") #define PROTOCOL_SYMBOL String::NewSymbol("protocol") -#define CONNECTION_HANDLER_SYMBOL String::NewSymbol("connectionHandler") #define READY_STATE_SYMBOL String::NewSymbol("readyState") #define OPEN_SYMBOL String::NewSymbol("open") @@ -65,6 +57,7 @@ Connection::Initialize (v8::Handle target) Local t = FunctionTemplate::New(New); constructor_template = Persistent::New(t); + constructor_template->Inherit(EventEmitter::constructor_template); constructor_template->InstanceTemplate()->SetInternalFieldCount(1); NODE_SET_PROTOTYPE_METHOD(constructor_template, "connect", Connect); @@ -102,7 +95,7 @@ Connection::ReadyStateGetter (Local _, const AccessorInfo& info) } Connection::Connection (Handle handle) - : ObjectWrap(handle) + : EventEmitter(handle) { encoding_ = RAW; @@ -439,11 +432,6 @@ Connection::OnReceive (const void *buf, size_t len) { HandleScope scope; - Handle callback_v = handle_->Get(ON_RECEIVE_SYMBOL); - if (!callback_v->IsFunction()) return; - - Handle callback = Handle::Cast(callback_v); - const int argc = 1; Handle argv[argc]; @@ -466,47 +454,31 @@ Connection::OnReceive (const void *buf, size_t len) argv[0] = Local::New(Null()); } - TryCatch try_catch; - callback->Call(handle_, argc, argv); - - if (try_catch.HasCaught()) - FatalException(try_catch); + Emit("Receive", argc, argv); } void Connection::OnDisconnect () { HandleScope scope; - Local callback_v = handle_->Get(ON_DISCONNECT_SYMBOL); - if (!callback_v->IsFunction()) return; - Handle callback = Handle::Cast(callback_v); Handle argv[1]; argv[0] = socket_.errorno == 0 ? False() : True(); - TryCatch try_catch; - callback->Call(handle_, 1, argv); - if (try_catch.HasCaught()) - node::FatalException(try_catch); + Emit("Disconnect", 1, argv); } -#define DEFINE_SIMPLE_CALLBACK(name, symbol) \ +#define DEFINE_SIMPLE_CALLBACK(name, type) \ void name () \ { \ HandleScope scope; \ - Local callback_v = handle_->Get(symbol); \ - if (!callback_v->IsFunction()) return; \ - Handle callback = Handle::Cast(callback_v); \ - TryCatch try_catch; \ - callback->Call(handle_, 0, NULL); \ - if (try_catch.HasCaught()) \ - node::FatalException(try_catch); \ + Emit (type, 0, NULL); \ } -DEFINE_SIMPLE_CALLBACK(Connection::OnConnect, ON_CONNECT_SYMBOL) -DEFINE_SIMPLE_CALLBACK(Connection::OnDrain, ON_DRAIN_SYMBOL) -DEFINE_SIMPLE_CALLBACK(Connection::OnTimeout, ON_TIMEOUT_SYMBOL) -DEFINE_SIMPLE_CALLBACK(Connection::OnEOF, ON_EOF_SYMBOL) +DEFINE_SIMPLE_CALLBACK(Connection::OnConnect, "Connect") +DEFINE_SIMPLE_CALLBACK(Connection::OnDrain, "Drain") +DEFINE_SIMPLE_CALLBACK(Connection::OnTimeout, "Timeout") +DEFINE_SIMPLE_CALLBACK(Connection::OnEOF, "EOF") Persistent Acceptor::constructor_template; @@ -517,7 +489,7 @@ Acceptor::Initialize (Handle target) Local t = FunctionTemplate::New(New); constructor_template = Persistent::New(t); - + constructor_template->Inherit(EventEmitter::constructor_template); constructor_template->InstanceTemplate()->SetInternalFieldCount(1); NODE_SET_PROTOTYPE_METHOD(constructor_template, "listen", Listen); @@ -527,10 +499,11 @@ Acceptor::Initialize (Handle target) } Acceptor::Acceptor (Handle handle, Handle connection_handler, Handle options) - : ObjectWrap(handle) + : EventEmitter(handle) { HandleScope scope; +#if 0 handle_->SetHiddenValue(CONNECTION_HANDLER_SYMBOL, connection_handler); int backlog = 1024; // default value @@ -538,13 +511,9 @@ Acceptor::Acceptor (Handle handle, Handle connection_handler, if (backlog_v->IsInt32()) { backlog = backlog_v->IntegerValue(); } +#endif - Local on_error_v = options->Get(ON_ERROR_SYMBOL); - if (on_error_v->IsFunction()) { - handle_->Set(ON_ERROR_SYMBOL, on_error_v); - } - - oi_server_init(&server_, backlog); + oi_server_init(&server_, 1024); server_.on_connection = Acceptor::on_connection; server_.data = this; } @@ -588,16 +557,6 @@ Connection* Acceptor::OnConnection (struct sockaddr *addr, socklen_t len) { HandleScope scope; - - Local connection_handler_v = - handle_->GetHiddenValue(CONNECTION_HANDLER_SYMBOL); - if (!connection_handler_v->IsFunction()) { - printf("Connection handler was empty!"); - Close(); - return NULL; - } - Local connection_handler = - Local::Cast(connection_handler_v); TryCatch try_catch; @@ -617,10 +576,8 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len) connection->SetAcceptor(handle_); Handle argv[1] = { js_connection }; - Local ret = connection_handler->Call(handle_, 1, argv); - if (ret.IsEmpty()) - FatalException(try_catch); + Emit("Connection", 1, argv); return connection; } diff --git a/src/net.h b/src/net.h index 5852f3e7ffc..6713809d23a 100644 --- a/src/net.h +++ b/src/net.h @@ -2,6 +2,7 @@ #define node_net_h #include "node.h" +#include "events.h" #include #include @@ -9,7 +10,7 @@ namespace node { class Acceptor; -class Connection : public ObjectWrap { +class Connection : public EventEmitter { public: static void Initialize (v8::Handle target); @@ -107,7 +108,7 @@ class Connection : public ObjectWrap { friend class Acceptor; }; -class Acceptor : public ObjectWrap { +class Acceptor : public EventEmitter { public: static void Initialize (v8::Handle target); diff --git a/src/node.cc b/src/node.cc index 930cb81f722..50b737585d0 100644 --- a/src/node.cc +++ b/src/node.cc @@ -1,5 +1,6 @@ #include "node.h" +#include "events.h" #include "net.h" #include "file.h" #include "http.h" @@ -312,6 +313,7 @@ Load (int argc, char *argv[]) NODE_SET_METHOD(node_obj, "debug", debug); NODE_SET_METHOD(node_obj, "reallyExit", node_exit); + EventEmitter::Initialize(node_obj); Timer::Initialize(node_obj); Process::Initialize(node_obj); @@ -331,6 +333,7 @@ Load (int argc, char *argv[]) HTTPServer::Initialize(http); HTTPConnection::Initialize(http); + ExecuteNativeJS("events.js", native_events); ExecuteNativeJS("http.js", native_http); ExecuteNativeJS("file.js", native_file); ExecuteNativeJS("node.js", native_node); diff --git a/src/node.js b/src/node.js index 59395e155f0..129da2443fd 100644 --- a/src/node.js +++ b/src/node.js @@ -1,3 +1,9 @@ +node.tcp.Server = function (on_connection, options) { + this.__proto__ = node.tcp.LowLevelServer (); + node.debug("hello world"); + if (on_connection) this.addListener("Connection", on_connection); +}; + // Timers function setTimeout (callback, delay) { diff --git a/wscript b/wscript index 306241092af..cf3a0fdd4c9 100644 --- a/wscript +++ b/wscript @@ -141,7 +141,12 @@ def build(bld): js2c.JS2C(source, targets) native_cc = bld.new_task_gen( - source="src/http.js src/file.js src/node.js", + source = """ + src/events.js + src/http.js + src/file.js + src/node.js + """, target="src/natives.h", rule=javascript_in_c, before="cxx" @@ -155,6 +160,7 @@ def build(bld): node.target = 'node' node.source = """ src/node.cc + src/events.cc src/http.cc src/net.cc src/file.cc