diff --git a/eventemitter3/eventemitter3-tests.ts b/eventemitter3/eventemitter3-tests.ts
index da13434135..4fa378bc20 100644
--- a/eventemitter3/eventemitter3-tests.ts
+++ b/eventemitter3/eventemitter3-tests.ts
@@ -1,16 +1,41 @@
-///
+///
+///
+///
'use strict';
import EventEmitter = require('eventemitter3');
+import util = require('util');
+import * as EventEmitter3ImportedAsES6Module from 'eventemitter3';
+
+declare namespace Assume {
+ interface Class {
+ new(...args: any[]): T;
+ }
+
+ interface Assume {
+ equals(compare: T): Assume;
+ equal(compare: T): Assume;
+ eqls(compare: T): Assume;
+ is: Assume;
+ deep: Assume;
+ to: Assume;
+ either(arr: T[]): Assume;
+ instanceOf(clazz: Class): Assume;
+ a(typeofString: string): Assume;
+ }
+
+ export function assume(input: T): Assume;
+}
+
+let assume = Assume.assume;
class EventEmitterTest {
- v: EventEmitter;
+ v: EventEmitter3.EventEmitter;
constructor() {
this.v = new EventEmitter();
- this.v = new EventEmitter.EventEmitter();
- this.v = new EventEmitter.EventEmitter2();
- this.v = new EventEmitter.EventEmitter3();
+ this.v = new EventEmitter3ImportedAsES6Module();
+ var n: NodeJS.EventEmitter = this.v;
}
listeners() {
@@ -27,39 +52,528 @@ class EventEmitterTest {
on() {
var fn = () => console.log(1);
- var v1: EventEmitter = this.v.on('click', fn);
- var v2: EventEmitter = this.v.on('click', fn, this);
+ var v1: EventEmitter3.EventEmitter = this.v.on('click', fn);
+ var v2: EventEmitter3.EventEmitter = this.v.on('click', fn, this);
}
once() {
var fn = () => console.log(1);
- var v1: EventEmitter = this.v.once('click', fn);
- var v2: EventEmitter = this.v.once('click', fn, this);
+ var v1: EventEmitter3.EventEmitter = this.v.once('click', fn);
+ var v2: EventEmitter3.EventEmitter = this.v.once('click', fn, this);
}
removeListener() {
var fn = () => console.log(1);
- var v1: EventEmitter = this.v.removeListener('click', fn);
- var v2: EventEmitter = this.v.removeListener('click', fn, true);
+ var v1: EventEmitter3.EventEmitter = this.v.removeListener('click', fn);
+ var v2: EventEmitter3.EventEmitter = this.v.removeListener('click', fn, true);
}
removeAllListeners() {
- var v1: EventEmitter = this.v.removeAllListeners('click');
+ var v1: EventEmitter3.EventEmitter = this.v.removeAllListeners('click');
}
off() {
var fn = () => console.log(1);
- var v1: EventEmitter = this.v.off('click', fn);
- var v2: EventEmitter = this.v.off('click', fn, true);
+ var v1: EventEmitter3.EventEmitter = this.v.off('click', fn);
+ var v2: EventEmitter3.EventEmitter = this.v.off('click', fn, true);
}
addListener() {
var fn = () => console.log(1);
- var v1: EventEmitter = this.v.addListener('click', fn);
- var v2: EventEmitter = this.v.addListener('click', fn, this);
+ var v1: EventEmitter3.EventEmitter = this.v.addListener('click', fn);
+ var v2: EventEmitter3.EventEmitter = this.v.addListener('click', fn, this);
}
setMaxListeners() {
- var v1: EventEmitter = this.v.setMaxListeners();
+ var v1: EventEmitter3.EventEmitter = this.v.setMaxListeners();
}
}
+
+
+describe('EventEmitter', function tests() {
+ 'use strict';
+
+ it('exposes a `prefixed` property', function () {
+ assume(EventEmitter.prefixed).is.either([false, '~']);
+ });
+
+ it('inherits when used with require(util).inherits', function () {
+ class Beast extends EventEmitter {
+ /* rawr, i'm a beast */
+ }
+
+ util.inherits(Beast, EventEmitter);
+
+ var moop = new Beast()
+ , meap = new Beast();
+
+ assume(moop).is.instanceOf(Beast);
+ assume(moop).is.instanceOf(EventEmitter);
+
+ moop.listeners();
+ meap.listeners();
+
+ moop.on('data', function () {
+ throw new Error('I should not emit');
+ });
+
+ meap.emit('data', 'rawr');
+ meap.removeListener('foo');
+ meap.removeAllListeners();
+ });
+
+ describe('EventEmitter#emit', function () {
+ it('should return false when there are not events to emit', function () {
+ var e = new EventEmitter();
+
+ assume(e.emit('foo')).equals(false);
+ assume(e.emit('bar')).equals(false);
+ });
+
+ it('emits with context', function (done) {
+ var context = { bar: 'baz' }
+ , e = new EventEmitter();
+
+ e.on('foo', function (bar: string) {
+ assume(bar).equals('bar');
+ assume(this).equals(context);
+
+ done();
+ }, context).emit('foo', 'bar');
+ });
+
+ it('emits with context, multiple arguments (force apply)', function (done) {
+ var context = { bar: 'baz' }
+ , e = new EventEmitter();
+
+ e.on('foo', function (bar: string) {
+ assume(bar).equals('bar');
+ assume(this).equals(context);
+
+ done();
+ }, context).emit('foo', 'bar', 1,2,3,4,5,6,7,8,9,0);
+ });
+
+ it('can emit the function with multiple arguments', function () {
+ var e = new EventEmitter();
+
+ for(var i = 0; i < 100; i++) {
+ (function (j: number) {
+ for (var i = 0, args: number[] = []; i < j; i++) {
+ args.push(j);
+ }
+
+ e.once('args', function () {
+ assume(arguments.length).equals(args.length);
+ });
+
+ e.emit.apply(e, (['args'] as any[]).concat(args));
+ })(i);
+ }
+ });
+
+ it('can emit the function with multiple arguments, multiple listeners', function () {
+ var e = new EventEmitter();
+
+ for(var i = 0; i < 100; i++) {
+ (function (j: number) {
+ for (var i = 0, args: number[] = []; i < j; i++) {
+ args.push(j);
+ }
+
+ e.once('args', function () {
+ assume(arguments.length).equals(args.length);
+ });
+
+ e.once('args', function () {
+ assume(arguments.length).equals(args.length);
+ });
+
+ e.once('args', function () {
+ assume(arguments.length).equals(args.length);
+ });
+
+ e.once('args', function () {
+ assume(arguments.length).equals(args.length);
+ });
+
+ e.emit.apply(e, (['args'] as any[]).concat(args));
+ })(i);
+ }
+ });
+
+ it('emits with context, multiple listeners (force loop)', function () {
+ var e = new EventEmitter();
+
+ e.on('foo', function (bar: string) {
+ assume(this).eqls({ foo: 'bar' });
+ assume(bar).equals('bar');
+ }, { foo: 'bar' });
+
+ e.on('foo', function (bar: string) {
+ assume(this).eqls({ bar: 'baz' });
+ assume(bar).equals('bar');
+ }, { bar: 'baz' });
+
+ e.emit('foo', 'bar');
+ });
+
+ it('emits with different contexts', function () {
+ var e = new EventEmitter()
+ , pattern = '';
+
+ function writer() {
+ pattern += this;
+ }
+
+ e.on('write', writer, 'foo');
+ e.on('write', writer, 'baz');
+ e.once('write', writer, 'bar');
+ e.once('write', writer, 'banana');
+
+ e.emit('write');
+ assume(pattern).equals('foobazbarbanana');
+ });
+
+ it('should return true when there are events to emit', function (done) {
+ var e = new EventEmitter();
+
+ e.on('foo', function () {
+ process.nextTick(done);
+ });
+
+ assume(e.emit('foo')).equals(true);
+ assume(e.emit('foob')).equals(false);
+ });
+
+ it('receives the emitted events', function (done) {
+ var e = new EventEmitter();
+
+ e.on('data', function (a: string, b: EventEmitter3.EventEmitter, c: Date, d: void, undef: void) {
+ assume(a).equals('foo');
+ assume(b).equals(e);
+ assume(c).is.instanceOf(Date);
+ assume(undef).equals(undefined);
+ assume(arguments.length).equals(3);
+
+ done();
+ });
+
+ e.emit('data', 'foo', e, new Date());
+ });
+
+ it('emits to all event listeners', function () {
+ var e = new EventEmitter()
+ , pattern: string[] = [];
+
+ e.on('foo', function () {
+ pattern.push('foo1');
+ });
+
+ e.on('foo', function () {
+ pattern.push('foo2');
+ });
+
+ e.emit('foo');
+
+ assume(pattern.join(';')).equals('foo1;foo2');
+ });
+
+ (function each(keys: string[]) {
+ var key = keys.shift();
+
+ if (!key) return;
+
+ it('can store event which is a known property: '+ key, function (next) {
+ var e = new EventEmitter();
+
+ e.on(key, function (key: string) {
+ assume(key).equals(key);
+ next();
+ }).emit(key, key);
+ });
+
+ each(keys);
+ })([
+ 'hasOwnProperty',
+ 'constructor',
+ '__proto__',
+ 'toString',
+ 'toValue',
+ 'unwatch',
+ 'watch'
+ ]);
+ });
+
+ describe('EventEmitter#listeners', function () {
+ it('returns an empty array if no listeners are specified', function () {
+ var e = new EventEmitter();
+
+ assume(e.listeners('foo')).is.a('array');
+ assume(e.listeners('foo').length).equals(0);
+ });
+
+ it('returns an array of function', function () {
+ var e = new EventEmitter();
+
+ function foo() {}
+
+ e.on('foo', foo);
+ assume(e.listeners('foo')).is.a('array');
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.listeners('foo')).deep.equals([foo]);
+ });
+
+ it('is not vulnerable to modifications', function () {
+ var e = new EventEmitter();
+
+ function foo() {}
+
+ e.on('foo', foo);
+
+ assume(e.listeners('foo')).deep.equals([foo]);
+
+ e.listeners('foo').length = 0;
+ assume(e.listeners('foo')).deep.equals([foo]);
+ });
+
+ it('can return a boolean as indication if listeners exist', function () {
+ var e = new EventEmitter();
+
+ function foo() {}
+
+ e.once('once', foo);
+ e.once('multiple', foo);
+ e.once('multiple', foo);
+ e.on('on', foo);
+ e.on('multi', foo);
+ e.on('multi', foo);
+
+ assume(e.listeners('foo', true)).equals(false);
+ assume(e.listeners('multiple', true)).equals(true);
+ assume(e.listeners('on', true)).equals(true);
+ assume(e.listeners('multi', true)).equals(true);
+
+ e.removeAllListeners();
+
+ assume(e.listeners('multiple', true)).equals(false);
+ assume(e.listeners('on', true)).equals(false);
+ assume(e.listeners('multi', true)).equals(false);
+ });
+ });
+
+ describe('EventEmitter#once', function () {
+ it('only emits it once', function () {
+ var e = new EventEmitter()
+ , calls = 0;
+
+ e.once('foo', function () {
+ calls++;
+ });
+
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+
+ assume(e.listeners('foo').length).equals(0);
+ assume(calls).equals(1);
+ });
+
+ it('only emits once if emits are nested inside the listener', function () {
+ var e = new EventEmitter()
+ , calls = 0;
+
+ e.once('foo', function () {
+ calls++;
+ e.emit('foo');
+ });
+
+ e.emit('foo');
+ assume(e.listeners('foo').length).equals(0);
+ assume(calls).equals(1);
+ });
+
+ it('only emits once for multiple events', function () {
+ var e = new EventEmitter()
+ , multi = 0
+ , foo = 0
+ , bar = 0;
+
+ e.once('foo', function () {
+ foo++;
+ });
+
+ e.once('foo', function () {
+ bar++;
+ });
+
+ e.on('foo', function () {
+ multi++;
+ });
+
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+ e.emit('foo');
+
+ assume(e.listeners('foo').length).equals(1);
+ assume(multi).equals(5);
+ assume(foo).equals(1);
+ assume(bar).equals(1);
+ });
+
+ it('only emits once with context', function (done) {
+ var context = { foo: 'bar' }
+ , e = new EventEmitter();
+
+ e.once('foo', function (bar: string) {
+ assume(this).equals(context);
+ assume(bar).equals('bar');
+
+ done();
+ }, context).emit('foo', 'bar');
+ });
+ });
+
+ describe('EventEmitter#removeListener', function () {
+ it('should only remove the event with the specified function', function () {
+ var e = new EventEmitter();
+
+ function bar() {}
+ e.on('foo', function () {});
+ e.on('bar', function () {});
+ e.on('bar', bar);
+
+ assume(e.removeListener('foo', bar)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.listeners('bar').length).equals(2);
+
+ assume(e.removeListener('foo')).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+ assume(e.listeners('bar').length).equals(2);
+
+ assume(e.removeListener('bar', bar)).equals(e);
+ assume(e.listeners('bar').length).equals(1);
+ assume(e.removeListener('bar')).equals(e);
+ assume(e.listeners('bar').length).equals(0);
+ });
+
+ it('should only remove once events when using the once flag', function () {
+ var e = new EventEmitter();
+
+ function foo() {}
+ e.on('foo', foo);
+
+ assume(e.removeListener('foo', function () {}, undefined, true)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.removeListener('foo', foo, undefined, true)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.removeListener('foo', foo)).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+
+ e.on('foo', foo);
+ e.once('foo', foo);
+
+ assume(e.removeListener('foo', function () {}, undefined, true)).equals(e);
+ assume(e.listeners('foo').length).equals(2);
+ assume(e.removeListener('foo', foo, undefined, true)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+
+ e.once('foo', foo);
+
+ assume(e.removeListener('foo', foo)).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+ });
+
+ it('should only remove listeners matching the correct context', function () {
+ var e = new EventEmitter()
+ , context = { foo: 'bar' };
+
+ function foo() {}
+ function bar() {}
+ e.on('foo', foo, context);
+
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.removeListener('foo', function () {}, context)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.removeListener('foo', foo, { baz: 'quux' })).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.removeListener('foo', foo, context)).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+
+ e.on('foo', foo, context);
+ e.on('foo', bar);
+
+ assume(e.listeners('foo').length).equals(2);
+ assume(e.removeListener('foo', foo, { baz: 'quux' })).equals(e);
+ assume(e.listeners('foo').length).equals(2);
+ assume(e.removeListener('foo', foo, context)).equals(e);
+ assume(e.listeners('foo').length).equals(1);
+ assume(e.listeners('foo')[0]).equals(bar);
+
+ e.on('foo', foo, context);
+
+ assume(e.listeners('foo').length).equals(2);
+ assume(e.removeAllListeners('foo')).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+ });
+ });
+
+ describe('EventEmitter#removeAllListeners', function () {
+ it('removes all events for the specified events', function () {
+ var e = new EventEmitter();
+
+ e.on('foo', function () { throw new Error('oops'); });
+ e.on('foo', function () { throw new Error('oops'); });
+ e.on('bar', function () { throw new Error('oops'); });
+ e.on('aaa', function () { throw new Error('oops'); });
+
+ assume(e.removeAllListeners('foo')).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+ assume(e.listeners('bar').length).equals(1);
+ assume(e.listeners('aaa').length).equals(1);
+
+ assume(e.removeAllListeners('bar')).equals(e);
+ assume(e.removeAllListeners('aaa')).equals(e);
+
+ assume(e.emit('foo')).equals(false);
+ assume(e.emit('bar')).equals(false);
+ assume(e.emit('aaa')).equals(false);
+ });
+
+ it('just nukes the fuck out of everything', function () {
+ var e = new EventEmitter();
+
+ e.on('foo', function () { throw new Error('oops'); });
+ e.on('foo', function () { throw new Error('oops'); });
+ e.on('bar', function () { throw new Error('oops'); });
+ e.on('aaa', function () { throw new Error('oops'); });
+
+ assume(e.removeAllListeners()).equals(e);
+ assume(e.listeners('foo').length).equals(0);
+ assume(e.listeners('bar').length).equals(0);
+ assume(e.listeners('aaa').length).equals(0);
+
+ assume(e.emit('foo')).equals(false);
+ assume(e.emit('bar')).equals(false);
+ assume(e.emit('aaa')).equals(false);
+ });
+ });
+
+ describe('#setMaxListeners', function () {
+ it('is a function', function () {
+ var e = new EventEmitter();
+
+ assume(e.setMaxListeners).is.a('function');
+ });
+
+ it('returns self when called', function () {
+ var e = new EventEmitter();
+
+ assume(e.setMaxListeners()).to.equal(e);
+ });
+ });
+});
diff --git a/eventemitter3/eventemitter3.d.ts b/eventemitter3/eventemitter3.d.ts
index f5cf9bcb2d..0d692b8247 100644
--- a/eventemitter3/eventemitter3.d.ts
+++ b/eventemitter3/eventemitter3.d.ts
@@ -1,11 +1,14 @@
-// Type definitions for EventEmitter3 0.1.6
+// Type definitions for EventEmitter3 1.1.1
// Project: https://github.com/primus/eventemitter3
-// Definitions by: Yuichi Murata
-// Definitions: https://github.com/borisyankov/DefinitelyTyped
+// Definitions by: Yuichi Murata , Leon Yu
+// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
-declare module EventEmitter3 {
- // __Base is hack for https://github.com/Microsoft/TypeScript/issues/3602
- class __Base {
+declare namespace EventEmitter3 {
+ interface EventEmitter3Static {
+ new (): EventEmitter;
+ prefixed: string | boolean;
+ }
+ class EventEmitter {
/**
* Minimal EventEmitter interface that is molded against the Node.js
* EventEmitter interface.
@@ -22,7 +25,17 @@ declare module EventEmitter3 {
* @returns {Array}
* @api public
*/
- listeners(event: string): Function[];
+ listeners(event?: string): Function[];
+
+ /**
+ * Return a list of assigned event listeners.
+ *
+ * @param {String} event The events that should be listed.
+ * @param {Boolean} exists We only need to know if there are listeners.
+ * @returns {Boolean}
+ * @api public
+ */
+ listeners(event: string, param: boolean): boolean;
/**
* Emit an event to all registered event listeners.
@@ -37,8 +50,8 @@ declare module EventEmitter3 {
* Register a new EventListener for the given event.
*
* @param {String} event Name of the event.
- * @param {Functon} fn Callback function.
- * @param {Mixed} context The context of the function.
+ * @param {Function} fn Callback function.
+ * @param {Mixed} [context=this] The context of the function.
* @api public
*/
on(event: string, fn: Function, context?: any): EventEmitter;
@@ -48,7 +61,7 @@ declare module EventEmitter3 {
*
* @param {String} event Name of the event.
* @param {Function} fn Callback function.
- * @param {Mixed} context The context of the function.
+ * @param {Mixed} [context=this] The context of the function.
* @api public
*/
once(event: string, fn: Function, context?: any): EventEmitter;
@@ -58,10 +71,11 @@ declare module EventEmitter3 {
*
* @param {String} event The event we want to remove.
* @param {Function} fn The listener that we need to find.
+ * @param {Mixed} context Only remove listeners matching this context.
* @param {Boolean} once Only remove once listeners.
* @api public
*/
- removeListener(event: string, fn: Function, once?: boolean): EventEmitter;
+ removeListener(event: string, fn?: Function, context?: any, once?: boolean): EventEmitter;
/**
* Remove all listeners or only the listeners for the specified event.
@@ -69,34 +83,41 @@ declare module EventEmitter3 {
* @param {String} event The event want to remove all listeners for.
* @api public
*/
- removeAllListeners(event: string): EventEmitter;
+ removeAllListeners(event?: string): EventEmitter;
- //
- // Alias methods names because people roll like that.
- //
- off(event: string, fn: Function, once?: boolean): EventEmitter;
+ /**
+ * Remove event listeners.
+ *
+ * @param {String} event The event we want to remove.
+ * @param {Function} fn The listener that we need to find.
+ * @param {Mixed} context Only remove listeners matching this context.
+ * @param {Boolean} once Only remove once listeners.
+ * @api public
+ */
+ off(event: string, fn?: Function, context?: any, once?: boolean): EventEmitter;
+
+ /**
+ * Register a new EventListener for the given event.
+ *
+ * @param {String} event Name of the event.
+ * @param {Function} fn Callback function.
+ * @param {Mixed} [context=this] The context of the function.
+ * @api public
+ */
addListener(event: string, fn: Function, context?: any): EventEmitter;
- //
- // This function doesn't apply anymore.
- //
+ /**
+ * This function doesn't apply anymore.
+ * @deprecated
+ */
setMaxListeners(): EventEmitter;
}
- export class EventEmitter extends __Base { }
- export module EventEmitter {
- //
- // Expose the module.
- //
- export class EventEmitter extends __Base {}
- export class EventEmitter2 extends __Base {}
- export class EventEmitter3 extends __Base {}
- }
}
declare module 'eventemitter3' {
//
// Expose the module.
//
- class EventEmitter extends EventEmitter3.EventEmitter {}
- export = EventEmitter;
+ var EventEmitter3: EventEmitter3.EventEmitter3Static;
+ export = EventEmitter3;
}