Bug 1137935 - add support for wildcard event type in devtools event emitter;r=ochameau
This API is only implemented as a temporary measure to ease the migration out of
sdk APIs.
MozReview-Commit-ID: BBlhxclpWqJ
--- a/devtools/shared/event-emitter.js
+++ b/devtools/shared/event-emitter.js
@@ -145,50 +145,61 @@ class EventEmitter {
newListener[onceOriginalListener] = listener;
EventEmitter.on(target, type, newListener);
});
}
static emit(target, type, ...rest) {
logEvent(type, rest);
- if (!(eventListeners in target) || !target[eventListeners].has(type)) {
+ if (!(eventListeners in target)) {
return;
}
- // Creating a temporary Set with the original listeners, to avoiding side effects
- // in emit.
- let listenersForType = new Set(target[eventListeners].get(type));
+ if (target[eventListeners].has(type)) {
+ // Creating a temporary Set with the original listeners, to avoiding side effects
+ // in emit.
+ let listenersForType = new Set(target[eventListeners].get(type));
- for (let listener of listenersForType) {
- // If the object was destroyed during event emission, stop emitting.
- if (!(eventListeners in target)) {
- break;
- }
+ for (let listener of listenersForType) {
+ // If the object was destroyed during event emission, stop emitting.
+ if (!(eventListeners in target)) {
+ break;
+ }
- let events = target[eventListeners];
- let listeners = events.get(type);
+ let events = target[eventListeners];
+ let listeners = events.get(type);
- // If listeners were removed during emission, make sure the
- // event handler we're going to fire wasn't removed.
- if (listeners && listeners.has(listener)) {
- try {
- if (isEventHandler(listener)) {
- listener[handler](type, ...rest);
- } else {
- listener.call(target, ...rest);
+ // If listeners were removed during emission, make sure the
+ // event handler we're going to fire wasn't removed.
+ if (listeners && listeners.has(listener)) {
+ try {
+ if (isEventHandler(listener)) {
+ listener[handler](type, ...rest);
+ } else {
+ listener.call(target, ...rest);
+ }
+ } catch (ex) {
+ // Prevent a bad listener from interfering with the others.
+ let msg = ex + ": " + ex.stack;
+ console.error(msg);
+ dump(msg + "\n");
}
- } catch (ex) {
- // Prevent a bad listener from interfering with the others.
- let msg = ex + ": " + ex.stack;
- console.error(msg);
- dump(msg + "\n");
}
}
}
+
+ // Backward compatibility with the SDK event-emitter: support wildcard listeners that
+ // will be called for any event. The arguments passed to the listener are the event
+ // type followed by the actual arguments.
+ // !!! This API will be removed by Bug 1391261.
+ let hasWildcardListeners = target[eventListeners].has("*");
+ if (type !== "*" && hasWildcardListeners) {
+ EventEmitter.emit(target, "*", type, ...rest);
+ }
}
/**
* Returns a number of event listeners registered for the given event `type`
* on the given event `target`.
*
* @param {Object} target
* Event target object.
--- a/devtools/shared/tests/unit/test_eventemitter_basic.js
+++ b/devtools/shared/tests/unit/test_eventemitter_basic.js
@@ -175,16 +175,54 @@ const TESTS = {
equal(secondCallbackCalled, false, "second callback not called yet");
return Promise.all([ check1, check2, check3 ]).then(args => {
equal(args[0], "rval from c1", "callback 1 done good");
equal(args[1], "rval from c2", "callback 2 done good");
equal(args[2], "rval from c3", "callback 3 done good");
});
+ },
+
+ // This API is only provided for backward compatibility reasons with the old SDK
+ // event-emitter.
+ // !!! This API will be removed by Bug 1391261.
+ testWildcard() {
+ let emitter = getEventEmitter();
+
+ let received = [];
+ let listener = (...args) => received.push(args);
+
+ emitter.on("*", listener);
+
+ emitter.emit("a", 1);
+
+ equal(received.length, 1, "the listener was triggered once");
+ equal(received[0].length, 2, "the listener was called with 2 arguments");
+ equal(received[0][0], "a", "first argument is the event name");
+ equal(received[0][1], 1, "additional arguments are forwarded");
+
+ emitter.emit("*", "wildcard");
+
+ equal(received.length, 2, "the listener was only triggered once");
+ equal(received[1].length, 1, "the listener was called with only 1 argument");
+ equal(received[1][0], "wildcard", "first argument is the actual argument");
+
+ emitter.emit("other", "arg1", "arg2");
+
+ equal(received.length, 3, "the listener was triggered once");
+ equal(received[2].length, 3, "the listener was called with only 1 argument");
+ equal(received[2][0], "other", "first argument is the event name");
+ equal(received[2][1], "arg1", "additional arguments are forwarded");
+ equal(received[2][2], "arg2", "additional arguments are forwarded");
+
+ emitter.off("*", listener);
+ emitter.emit("a");
+ emitter.emit("*");
+ equal(received.length, 3, "the listener was not called anymore");
}
};
/**
* Create a runnable tests based on the tests descriptor given.
*
* @param {Object} tests
* The tests descriptor object, contains the tests to run.