Bug 918588 - Properly support off after once with EventEmitter. r=mratcliffe
authorJ. Ryan Stinnett <jryans@gmail.com>
Thu, 19 Sep 2013 19:36:13 -0500
changeset 148085 42d54d6f6d1c109287dec399733ea75be6ecb858
parent 148084 59d5404eadf50aedd55b81df28643390445780c4
child 148086 c36f479a97554f80f147deb77a8e93e18acd70a9
push id25324
push userryanvm@gmail.com
push dateFri, 20 Sep 2013 18:10:24 +0000
treeherdermozilla-central@8ef53ff515b8 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmratcliffe
bugs918588
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 918588 - Properly support off after once with EventEmitter. r=mratcliffe
browser/devtools/shared/event-emitter.js
browser/devtools/shared/test/browser_eventemitter_basic.js
--- a/browser/devtools/shared/event-emitter.js
+++ b/browser/devtools/shared/event-emitter.js
@@ -57,16 +57,17 @@ EventEmitter.prototype = {
    * @param function aListener
    *        Called when the event is fired.  Will be called at most one time.
    */
   once: function EventEmitter_once(aEvent, aListener) {
     let handler = function() {
       this.off(aEvent, handler);
       aListener.apply(null, arguments);
     }.bind(this);
+    handler._originalListener = aListener;
     this.on(aEvent, handler);
   },
 
   /**
    * Remove a previously-registered event listener.  Works for events
    * registered with either on or once.
    *
    * @param string aEvent
@@ -74,17 +75,19 @@ EventEmitter.prototype = {
    * @param function aListener
    *        The listener to remove.
    */
   off: function EventEmitter_off(aEvent, aListener) {
     if (!this._eventEmitterListeners)
       return;
     let listeners = this._eventEmitterListeners.get(aEvent);
     if (listeners) {
-      this._eventEmitterListeners.set(aEvent, listeners.filter(function(l) aListener != l));
+      this._eventEmitterListeners.set(aEvent, listeners.filter(l => {
+        return l !== aListener && l._originalListener !== aListener;
+      }));
     }
   },
 
   /**
    * Emit an event.  All arguments to this method will
    * be sent to listner functions.
    */
   emit: function EventEmitter_emit(aEvent) {
--- a/browser/devtools/shared/test/browser_eventemitter_basic.js
+++ b/browser/devtools/shared/test/browser_eventemitter_basic.js
@@ -69,12 +69,29 @@ function testEmitter(aObject) {
 
     emitter.on("tick", c1);
     emitter.on("tick", c2);
     emitter.on("tick", c3);
     emitter.on("tick", c4);
 
     emitter.emit("tick");
 
+    offAfterOnce();
+  }
+
+  function offAfterOnce() {
+    let enteredC1 = false;
+
+    function c1() {
+      enteredC1 = true;
+    }
+
+    emitter.once("oao", c1);
+    emitter.off("oao", c1);
+
+    emitter.emit("oao");
+
+    ok(!enteredC1, "c1 should not be called");
+
     delete emitter;
     finish();
   }
 }