in the middle putting in event code. broken.
authorRyan <ry@tinyclouds.org>
Thu, 25 Jun 2009 17:13:20 +0000 (19:13 +0200)
committerRyan <ry@tinyclouds.org>
Sun, 28 Jun 2009 17:08:25 +0000 (19:08 +0200)
src/events.cc [new file with mode: 0644]
src/events.h [new file with mode: 0644]
src/events.js [new file with mode: 0644]
src/net.cc
src/net.h
src/node.cc
src/node.js
wscript

diff --git a/src/events.cc b/src/events.cc
new file mode 100644 (file)
index 0000000..b36db7d
--- /dev/null
@@ -0,0 +1,56 @@
+#include "events.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <arpa/inet.h> /* inet_ntop */
+#include <netinet/in.h> /* sockaddr_in, sockaddr_in6 */
+
+using namespace v8;
+using namespace node;
+
+Persistent<FunctionTemplate> EventEmitter::constructor_template;
+
+void 
+EventEmitter::Initialize (v8::Handle<v8::Object> target)
+{
+  HandleScope scope;
+
+  Local<FunctionTemplate> t = FunctionTemplate::New();
+  constructor_template = Persistent<FunctionTemplate>::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<Value> argv[])
+{
+  Local<Value> emit_v = handle_->Get(String::NewSymbol("emit"));
+  assert(emit_v->IsFunction());
+  Local<Function> emit = Local<Function>::Cast(emit_v);
+
+  Local<Array> event_args = Array::New(argc);
+  for (int i = 0; i < argc; i++) {
+    event_args->Set(Integer::New(i), argv[i]);
+  }
+
+  Handle<Value> 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 (file)
index 0000000..1fe47cb
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef node_events_h
+#define node_events_h
+
+#include "node.h"
+#include <v8.h>
+
+namespace node {
+
+class EventEmitter : public ObjectWrap {
+public:
+  static void Initialize (v8::Handle<v8::Object> target);
+  static v8::Persistent<v8::FunctionTemplate> constructor_template;
+
+  bool Emit (const char *type, int argc, v8::Handle<v8::Value> argv[]);
+
+  EventEmitter (v8::Handle<v8::Object> handle)
+    : ObjectWrap(handle) { };
+};
+
+} // namespace node
+#endif
diff --git a/src/events.js b/src/events.js
new file mode 100644 (file)
index 0000000..f665cec
--- /dev/null
@@ -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
index 04a7fa0..2e00351 100644 (file)
@@ -1,4 +1,5 @@
 #include "net.h"
+#include "events.h"
 
 #include <assert.h>
 #include <stdlib.h>
@@ -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<v8::Object> target)
   Local<FunctionTemplate> t = FunctionTemplate::New(New);
 
   constructor_template = Persistent<FunctionTemplate>::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<String> _, const AccessorInfo& info)
 }
 
 Connection::Connection (Handle<Object> handle)
-  : ObjectWrap(handle) 
+  : EventEmitter(handle) 
 {
   encoding_ = RAW;
 
@@ -439,11 +432,6 @@ Connection::OnReceive (const void *buf, size_t len)
 {
   HandleScope scope;
 
-  Handle<Value> callback_v = handle_->Get(ON_RECEIVE_SYMBOL);
-  if (!callback_v->IsFunction()) return; 
-
-  Handle<Function> callback = Handle<Function>::Cast(callback_v);
-
   const int argc = 1;
   Handle<Value> argv[argc];
 
@@ -466,47 +454,31 @@ Connection::OnReceive (const void *buf, size_t len)
     argv[0] = Local<Value>::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<Value> callback_v = handle_->Get(ON_DISCONNECT_SYMBOL);
-  if (!callback_v->IsFunction()) return;
-  Handle<Function> callback = Handle<Function>::Cast(callback_v);
 
   Handle<Value> 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<Value> callback_v = handle_->Get(symbol);                   \
-  if (!callback_v->IsFunction()) return;                            \
-  Handle<Function> callback = Handle<Function>::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<FunctionTemplate> Acceptor::constructor_template;
 
@@ -517,7 +489,7 @@ Acceptor::Initialize (Handle<Object> target)
 
   Local<FunctionTemplate> t = FunctionTemplate::New(New);
   constructor_template = Persistent<FunctionTemplate>::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<Object> target)
 }
 
 Acceptor::Acceptor (Handle<Object> handle, Handle<Function> connection_handler,  Handle<Object> 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<Object> handle, Handle<Function> connection_handler,
   if (backlog_v->IsInt32()) {
     backlog = backlog_v->IntegerValue();
   }
+#endif
 
-  Local<Value> 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<Value> connection_handler_v =
-    handle_->GetHiddenValue(CONNECTION_HANDLER_SYMBOL);
-  if (!connection_handler_v->IsFunction()) {
-    printf("Connection handler was empty!");
-    Close();
-    return NULL;
-  }
-  Local<Function> connection_handler =
-    Local<Function>::Cast(connection_handler_v);
 
   TryCatch try_catch;
 
@@ -617,10 +576,8 @@ Acceptor::OnConnection (struct sockaddr *addr, socklen_t len)
   connection->SetAcceptor(handle_);
 
   Handle<Value> argv[1] = { js_connection };
-  Local<Value> ret = connection_handler->Call(handle_, 1, argv);
 
-  if (ret.IsEmpty())
-    FatalException(try_catch);
+  Emit("Connection", 1, argv);
 
   return connection;
 }
index 5852f3e..6713809 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -2,6 +2,7 @@
 #define node_net_h
 
 #include "node.h"
+#include "events.h"
 #include <v8.h>
 #include <oi_socket.h>
 
@@ -9,7 +10,7 @@ namespace node {
 
 class Acceptor;
 
-class Connection : public ObjectWrap {
+class Connection : public EventEmitter {
 public:
   static void Initialize (v8::Handle<v8::Object> target);
 
@@ -107,7 +108,7 @@ private:
   friend class Acceptor;
 };
 
-class Acceptor : public ObjectWrap {
+class Acceptor : public EventEmitter {
 public:
   static void Initialize (v8::Handle<v8::Object> target);
 
index 930cb81..50b7375 100644 (file)
@@ -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);
index 59395e1..129da24 100644 (file)
@@ -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 3062410..cf3a0fd 100644 (file)
--- 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