Bug 1497457 - Allow to remove one time listeners on event-source;r=ochameau

Differential Revision: https://phabricator.services.mozilla.com/D11992

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Julian Descottes 2018-11-27 10:13:47 +00:00
Родитель 93fd1e4504
Коммит ff4d366afa
3 изменённых файлов: 79 добавлений и 7 удалений

Просмотреть файл

@ -27,8 +27,12 @@ function eventSource(proto) {
* Called when the event is fired. If the same listener
* is added more than once, it will be called once per
* addListener call.
* @param key function (optional)
* Key to use for removeListener, defaults to the listener. Used by helper method
* addOneTimeListener, which creates a custom listener. Use the original listener
* as key to allow to remove oneTimeListeners.
*/
proto.addListener = function(name, listener) {
proto.addListener = function(name, listener, key = listener) {
if (typeof listener != "function") {
throw TypeError("Listeners must be functions.");
}
@ -37,7 +41,7 @@ function eventSource(proto) {
this._listeners = {};
}
this._getListeners(name).push(listener);
this._getListeners(name).push({ key, callback: listener });
};
/**
@ -53,14 +57,14 @@ function eventSource(proto) {
*/
proto.addOneTimeListener = function(name, listener) {
return new Promise(resolve => {
const l = (eventName, ...rest) => {
this.removeListener(name, l);
const oneTimeListener = (eventName, ...rest) => {
this.removeListener(name, listener);
if (listener) {
listener(eventName, ...rest);
}
resolve(rest[0]);
};
this.addListener(name, l);
this.addListener(name, oneTimeListener, listener);
});
};
@ -83,7 +87,7 @@ function eventSource(proto) {
this._listeners[name] = [];
} else {
this._listeners[name] =
this._listeners[name].filter(l => l != listener);
this._listeners[name].filter(l => l.key != listener);
}
};
@ -121,7 +125,7 @@ function eventSource(proto) {
for (const listener of listeners) {
try {
listener.apply(null, arguments);
listener.callback.apply(null, arguments);
} catch (e) {
// Prevent a bad listener from interfering with the others.
DevToolsUtils.reportException("notify event '" + name + "'", e);

Просмотреть файл

@ -0,0 +1,67 @@
/* -*- js-indent-level: 2; indent-tabs-mode: nil -*- */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const eventSource = require("devtools/shared/client/event-source");
// Test basic event-source APIs:
// - addListener
// - removeListener
// - addOneTimeListener
add_task(function() {
// Create a basic test object that can emit events using event-source.js
class TestClass {}
eventSource(TestClass.prototype);
const testObject = new TestClass();
testBasicAddRemoveListener(testObject);
info("Check that one time listeners are only triggered once");
testOneTimeListener(testObject);
info("Check that one time listeners can be removed");
testRemoveOneTimeListener(testObject);
});
function testBasicAddRemoveListener(testObject) {
let eventsReceived = 0;
const onTestEvent = () => eventsReceived++;
testObject.addListener("event-testBasicAddRemoveListener", onTestEvent);
testObject.emit("event-testBasicAddRemoveListener");
ok(eventsReceived === 1, "Event listener was triggered");
testObject.emit("event-testBasicAddRemoveListener");
ok(eventsReceived === 2, "Event listener was triggered again");
testObject.removeListener("event-testBasicAddRemoveListener", onTestEvent);
testObject.emit("event-testBasicAddRemoveListener");
ok(eventsReceived === 2, "Event listener was not triggered anymore");
}
function testOneTimeListener(testObject) {
let eventsReceived = 0;
const onTestEvent = () => eventsReceived++;
testObject.addOneTimeListener("event-testOneTimeListener", onTestEvent);
testObject.emit("event-testOneTimeListener");
ok(eventsReceived === 1, "Event listener was triggered");
testObject.emit("event-testOneTimeListener");
ok(eventsReceived === 1, "Event listener was not triggered again");
testObject.removeListener("event-testOneTimeListener", onTestEvent);
}
function testRemoveOneTimeListener(testObject) {
let eventsReceived = 0;
const onTestEvent = () => eventsReceived++;
testObject.addOneTimeListener("event-testRemoveOneTimeListener", onTestEvent);
testObject.removeListener("event-testRemoveOneTimeListener", onTestEvent);
testObject.emit("event-testRemoveOneTimeListener");
ok(eventsReceived === 0, "Event listener was already removed");
}

Просмотреть файл

@ -16,6 +16,7 @@ support-files =
run-if = nightly_build
[test_eventemitter_basic.js]
[test_eventemitter_static.js]
[test_eventsource.js]
[test_fetch-bom.js]
[test_fetch-chrome.js]
[test_fetch-file.js]