Fix memory leak. It was only a missing HandleScope in Emit()!
authorRyan <ry@tinyclouds.org>
Fri, 24 Jul 2009 10:53:46 +0000 (12:53 +0200)
committerRyan <ry@tinyclouds.org>
Fri, 24 Jul 2009 13:11:18 +0000 (15:11 +0200)
This change also tries to optimize Emit by looping through the listeners in
C++. The javascript version of this function is still there and being used,
but only by javascript code. Not an ideal solution - there should only be
one implementation - however for now it seems to help.

This doesn't solve all of the memory leaks that we're experiencing, there
seems to be another subtle problem.

src/events.cc
src/events.js

index 9967c1c..0116087 100644 (file)
@@ -33,24 +33,33 @@ EventEmitter::Initialize (v8::Handle<v8::Object> target)
 bool
 EventEmitter::Emit (const char *type, int argc, Handle<Value> argv[])
 {
+  HandleScope scope; 
+
   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]);
-  }
+  Local<Value> events_v = handle_->Get(String::NewSymbol("_events"));
+  if (!events_v->IsObject()) return false;
+  Local<Object> events = events_v->ToObject();
 
-  Handle<Value> emit_argv[2] = { String::NewSymbol(type), event_args };
+  Local<Value> listeners_v = events->Get(String::NewSymbol(type));
+  if (!listeners_v->IsArray()) return false;
+  Local<Array> listeners = Local<Array>::Cast(listeners_v);
 
   TryCatch try_catch;
 
-  emit->Call(handle_, 2, emit_argv);
+  for (int i = 0; i < listeners->Length(); i++) {
+    Local<Value> listener_v = listeners->Get(Integer::New(i));
+    if (!listener_v->IsFunction()) continue;
+    Local<Function> listener = Local<Function>::Cast(listener_v);
+
+    listener->Call(handle_, argc, argv);
 
-  if (try_catch.HasCaught()) {
-    FatalException(try_catch);
-    return false;
+    if (try_catch.HasCaught()) {
+      FatalException(try_catch);
+      return false;
+    }
   }
 
   return true;
index a43a603..0430533 100644 (file)
@@ -18,13 +18,14 @@ emitter.listeners = function (type) {
 };
 
 // This function is called often from C++. 
+// FIXME there is a counterpart for this function in C++
+// both must have the same behavior.
 // See events.cc 
 emitter.emit = function (type, args) {
   if (!this._events) return;
   if (!this._events.hasOwnProperty(type)) return;
 
   var listeners = this._events[type];
-  var length = listeners.length;
 
   for (var i = 0; i < listeners.length; i++) {
     listeners[i].apply(this, args);