Permalink
Browse files

[events] EventEmitter emits wildcard event. Supports .onAny(cb) and .…

…on('*', cb).
  • Loading branch information...
pgte committed Jun 6, 2012
1 parent dc8b488 commit c8b9b18e72926d4f18e1d871fa2129bdc56511c8
Showing with 165 additions and 1 deletion.
  1. +39 −1 lib/events.js
  2. +56 −0 test/simple/test-event-emitter-on-any.js
  3. +70 −0 test/simple/test-event-emitter-remove-any-listener.js
View
@@ -21,6 +21,8 @@
var isArray = Array.isArray;
+var eventTypeAny = '*';
+
function EventEmitter() {
if (exports.usingDomains) {
// if there is an active domain, then attach to it.
@@ -45,7 +47,7 @@ EventEmitter.prototype.setMaxListeners = function(n) {
};
-EventEmitter.prototype.emit = function() {
+function emit() {
var type = arguments[0];
// If there is no 'error' event listener then throw.
if (type === 'error') {
@@ -123,13 +125,29 @@ EventEmitter.prototype.emit = function() {
}
};
+EventEmitter.prototype.emit = emit;
+
+function emitAll() {
+ var hasHandlers = emit.apply(this, arguments);
+ var args = Array.prototype.slice.call(arguments);
+ var eventType = args.shift();
+
+ emit.call(this, eventTypeAny, eventType, args);
+
+ return hasHandlers;
+}
+
EventEmitter.prototype.addListener = function(type, listener) {
if ('function' !== typeof listener) {
throw new Error('addListener only takes instances of Function');
}
if (!this._events) this._events = {};
+ if (type === eventTypeAny && this.emit !== emitAll) {
+ this.emit = emitAll;
+ }
+
// To avoid recursion in the case that type == "newListeners"! Before
// adding it to the listeners, first emit "newListeners".
this.emit('newListener', type, typeof listener.listener === 'function' ?
@@ -219,6 +237,10 @@ EventEmitter.prototype.removeListener = function(type, listener) {
delete this._events[type];
}
+ if (type === eventTypeAny) {
+ delete this.emit;
+ }
+
return this;
};
@@ -237,9 +259,25 @@ EventEmitter.prototype.removeAllListeners = function(type) {
this._events[type] = null;
}
+ if (type === eventTypeAny) {
+ delete this.emit;
+ }
+
+ return this;
+};
+
+EventEmitter.prototype.onAny = function(callback) {
+ this.on(eventTypeAny, callback);
+
return this;
};
+EventEmitter.prototype.removeAnyListener = function(callback) {
+ this.removeListener(eventTypeAny, callback);
+
+ return this;
+}
+
EventEmitter.prototype.listeners = function(type) {
if (!this._events) this._events = {};
if (!this._events[type]) this._events[type] = [];
@@ -0,0 +1,56 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var events = require('events');
+
+var e = new events.EventEmitter();
+
+var events_new_listener_emited = [];
+var listeners_new_listener_emited = [];
+var times_hello_emited = 0;
+
+e.on('newListener', function(event, listener) {
+ events_new_listener_emited.push(event);
+ listeners_new_listener_emited.push(listener);
+});
+
+function hello(eventType, args) {
+ console.log('hello');
+ times_hello_emited += 1;
+ assert.equal('hello', eventType);
+ assert.deepEqual(['a', 'b'], args);
+}
+e.onAny(hello);
+
+console.log('start');
+
+e.emit('hello', 'a', 'b');
+
+
+process.on('exit', function() {
+ assert.deepEqual(['*'], events_new_listener_emited);
+ assert.deepEqual([hello], listeners_new_listener_emited);
+ assert.equal(1, times_hello_emited);
+});
+
+
@@ -0,0 +1,70 @@
+// Copyright Joyent, Inc. and other Node contributors.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a
+// copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to permit
+// persons to whom the Software is furnished to do so, subject to the
+// following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
+// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
+// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+// USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+var common = require('../common');
+var assert = require('assert');
+var events = require('events');
+
+
+var count = 0;
+
+function listener1() {
+ console.log('listener1');
+ count++;
+}
+
+function listener2() {
+ console.log('listener2');
+ count++;
+}
+
+function listener3() {
+ console.log('listener3');
+ count++;
+}
+
+var e1 = new events.EventEmitter();
+var e1listeners = e1.listeners('*');
+e1.onAny(listener1);
+assert.equal(e1listeners.length, 1);
+e1.removeAnyListener(listener1);
+assert.deepEqual([], e1.listeners('*'));
+
+// identity check, listeners array should be the same
+assert.equal(e1listeners, e1.listeners('*'));
+
+var e2 = new events.EventEmitter();
+e2.onAny(listener1);
+e2.removeAnyListener(listener2);
+assert.deepEqual([listener1], e2.listeners('*'));
+
+var e3 = new events.EventEmitter();
+e3.onAny(listener1);
+e3.onAny(listener2);
+var e3listeners = e3.listeners('*');
+assert.equal(e3listeners.length, 2)
+e3.removeAnyListener(listener1);
+assert.equal(e3listeners.length, 1)
+assert.deepEqual([listener2], e3.listeners('*'));
+
+assert.equal(e3listeners, e3.listeners('*'));
+
+

0 comments on commit c8b9b18

Please sign in to comment.