Added support for removing .once listeners
authorArnout Kazemier <info@3rd-Eden.com>
Fri, 18 Mar 2011 20:02:14 +0000 (21:02 +0100)
committerRyan Dahl <ry@tinyclouds.org>
Fri, 25 Mar 2011 18:51:29 +0000 (11:51 -0700)
Closes GH-806.

lib/events.js
test/simple/test-event-emitter-once.js

index 2d2d5d1..6fe55bb 100644 (file)
@@ -138,10 +138,13 @@ EventEmitter.prototype.on = EventEmitter.prototype.addListener;
 
 EventEmitter.prototype.once = function(type, listener) {
   var self = this;
-  self.on(type, function g() {
+  function g() {
     self.removeListener(type, g);
     listener.apply(this, arguments);
-  });
+  };
+
+  g.listener = listener;
+  self.on(type, g);
 
   return this;
 };
@@ -157,12 +160,23 @@ EventEmitter.prototype.removeListener = function(type, listener) {
   var list = this._events[type];
 
   if (isArray(list)) {
-    var i = list.indexOf(listener);
-    if (i < 0) return this;
-    list.splice(i, 1);
+    var position = -1;
+    for (var i = 0, length = list.length; i < length; i++) {
+      if (list[i] === listener ||
+          (list[i].listener && list[i].listener === listener))
+      {
+        position = i;
+        break;
+      }
+    }
+
+    if (position < 0) return this;
+    list.splice(position, 1);
     if (list.length == 0)
       delete this._events[type];
-  } else if (this._events[type] === listener) {
+  } else if (list === listener ||
+             (list.listener && list.listener === listener))
+  {
     delete this._events[type];
   }
 
index fb17237..55f0f16 100644 (file)
@@ -35,6 +35,14 @@ e.emit('hello', 'a', 'b');
 e.emit('hello', 'a', 'b');
 e.emit('hello', 'a', 'b');
 
+var remove = function() {
+  assert.fail(1,0, 'once->foo should not be emitted', '!');
+};
+
+e.once('foo', remove);
+e.removeListener('foo', remove);
+e.emit('foo');
+
 process.addListener('exit', function() {
   assert.equal(1, times_hello_emited);
 });