Merge pull request #10857 from Stubb0rn/eventemitter3-1.2.0

Added type definition for eventemitter3-1.2.0
This commit is contained in:
jramsay
2016-11-03 15:25:46 -07:00
committed by GitHub
3 changed files with 160 additions and 642 deletions
+101 -570
View File
@@ -1,586 +1,117 @@
///<reference path="eventemitter3.d.ts" />
///<reference path="../node/node.d.ts" />
///<reference path="../mocha/mocha.d.ts" />
'use strict';
import EventEmitter = require('eventemitter3');
import util = require('util');
import * as EventEmitter3ImportedAsES6Module from 'eventemitter3';
declare namespace Assume {
interface Class<T> {
new(...args: any[]): T;
}
interface Assume<T> {
equals(compare: T): Assume<T>;
equal(compare: T): Assume<T>;
eqls(compare: T): Assume<T>;
is: Assume<T>;
deep: Assume<T>;
to: Assume<T>;
either(arr: T[]): Assume<T>;
instanceOf(clazz: Class<T>): Assume<T>;
a(typeofString: string): Assume<T>;
}
export function assume<T>(input: T): Assume<T>;
}
let assume = Assume.assume;
class EventEmitterTest {
v: EventEmitter3.EventEmitter;
const eventName = 'test';
const eventSymbol = Symbol('test');
const fn = () => console.log(1);
// Extending EventEmitter
class TestEmitter extends EventEmitter {
constructor() {
this.v = new EventEmitter();
this.v = new EventEmitter3ImportedAsES6Module();
// Some methods are missing or incompatible with current implementation (v4.2.x) of NodeJS.EventEmitter
// (e.g. getMaxListenters or listeners)
// var n: NodeJS.EventEmitter = this.v;
super();
}
listeners() {
var v1: Function[] = this.v.listeners('click');
}
emit() {
var v1: boolean = this.v.emit('click');
var v2: boolean = this.v.emit('click', 1);
var v3: boolean = this.v.emit('click', 1, '1');
var v4: boolean = this.v.emit('click', 1, '1', true);
var v5: boolean = this.v.emit('click', 1, '1', true, new Date());
}
on() {
var fn = () => console.log(1);
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: 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: EventEmitter3.EventEmitter = this.v.removeListener('click', fn);
var v2: EventEmitter3.EventEmitter = this.v.removeListener('click', fn, true);
}
removeAllListeners() {
var v1: EventEmitter3.EventEmitter = this.v.removeAllListeners('click');
}
off() {
var fn = () => console.log(1);
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: EventEmitter3.EventEmitter = this.v.addListener('click', fn);
var v2: EventEmitter3.EventEmitter = this.v.addListener('click', fn, this);
}
setMaxListeners() {
var v1: EventEmitter3.EventEmitter = this.v.setMaxListeners();
test() {
return this;
}
}
const ee: TestEmitter = new TestEmitter();
describe('EventEmitter', function tests() {
'use strict';
// EventEmitter.prefixed
// should be boolean or string static property
const prefix = EventEmitter.prefixed;
if (typeof prefix === 'boolean') {
console.log(prefix.valueOf());
} else {
console.log(prefix.length);
}
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 */
// EventEmitter.eventNames()
// should return array of strings or symbols
ee.eventNames().every((event) => {
if (typeof event === 'symbol') {
return false;
} else {
return event.length > 0;
}
class BeastES6 extends EventEmitter3ImportedAsES6Module {
/* 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);
});
});
});
// EventEmitter.listeners()
// should return array of functions
ee.listeners(eventName).map((listener) => {
return listener.bind(this);
});
// should accept symbol as event name
ee.listeners(eventSymbol).map((listener) => {
return listener.bind(this);
});
// should return boolean with 'exists' flag
const hasListeners: boolean = ee.listeners(eventName, true);
// EventEmitter.emit()
// should support any number of arguments
ee.emit(eventName, 1, true, {}, [], 'test', Symbol(), null);
// should accept symbol as event name
ee.emit(eventSymbol);
// EventEmitter.addListener() and EventEmitter.on()
// should accept function
ee.on(eventName, fn);
ee.addListener(eventName, fn);
// should accept optional context argument
ee.on(eventName, fn, this);
ee.addListener(eventName, fn, this);
// should accept symbol as event name
ee.on(eventSymbol, fn);
ee.addListener(eventSymbol, fn);
// should support fluent interface
ee.on(eventSymbol, fn).test();
ee.addListener(eventSymbol, fn).test();
// EventEmitter.once()
// should accept event name and function
ee.once(eventName, fn);
// should accept optional context argument
ee.once(eventName, fn, this);
ee.once(eventName, fn, {});
// should accept symbol as event name
ee.once(eventSymbol, fn);
// should support fluent interface
ee.once(eventSymbol, fn).test();
// EventEmitter.removeListener() and EventEmitter.off()
// should accept event name
ee.removeListener(eventName);
ee.off(eventName);
// should accept optional function
ee.removeListener(eventName, fn);
ee.off(eventName, fn);
// should accept optional context argument
ee.removeListener(eventName, fn, {});
ee.off(eventName, fn, {});
// should accept optional boolean flag for removing listeners added with `EventEmitter.once()`
ee.removeListener(eventName, fn, null, true);
ee.off(eventName, fn, null, true);
// should accept symbol as event name
ee.removeListener(eventSymbol);
ee.off(eventSymbol);
// should support fluent interface
ee.removeListener(eventName).test();
ee.off(eventName).test();
// EventEmitter.removeAllListeners()
// should not require any arguments
ee.removeAllListeners();
// should accept optional event name
ee.removeAllListeners(eventName);
// should accept symbol as event name
ee.removeAllListeners(eventSymbol);
// should support fluent interface
ee.removeAllListeners(eventName).test();
// EventEmitter.setMaxListeners()
// should support fluent interface
ee.setMaxListeners().test();
@@ -0,0 +1 @@
-m commonjs
+58 -72
View File
@@ -1,123 +1,109 @@
// Type definitions for EventEmitter3 1.1.1
// Type definitions for EventEmitter3 1.2.0
// Project: https://github.com/primus/eventemitter3
// Definitions by: Yuichi Murata <https://github.com/mrk21>, Leon Yu <https://github.com/leonyu>
// Definitions by: Yuichi Murata <https://github.com/mrk21>, Leon Yu <https://github.com/leonyu>, Boriss Nazarovs <https://github.com/Stubb0rn>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
declare namespace EventEmitter3 {
interface EventEmitter3Static {
new (): EventEmitter;
prefixed: string | boolean;
}
/**
* Minimal EventEmitter interface that is molded against the Node.js
* EventEmitter interface.
*/
class EventEmitter {
/**
* Minimal EventEmitter interface that is molded against the Node.js
* EventEmitter interface.
*
* @constructor
* @api public
*/
constructor();
/**
* Return a list of assigned event listeners.
* Return an array listing the events for which the emitter has registered listeners.
*
* @param {String} event The events that should be listed.
* @returns {Array}
* @api public
* @returns {(string|symbol)[]}
*/
listeners(event?: string): Function[];
eventNames(): (string|symbol)[];
/**
* Return a list of assigned event listeners.
* Return the listeners registered for a given event.
*
* @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
* @param {(string|symbol)} event The event name.
* @returns {Function[]}
*/
listeners(event: string, param: boolean): boolean;
listeners(event: string|symbol): Function[];
/**
* Emit an event to all registered event listeners.
* Check if there listeners for a given event.
* If `exists` argument is not `true` lists listeners.
*
* @param {String} event The name of the event.
* @returns {Boolean} Indication if we've emitted an event.
* @api public
* @param {(string|symbol)} event The event name.
* @param {boolean} exists Only check if there are listeners.
* @returns {boolean}
*/
emit(event: string, ...args: any[]): boolean;
listeners(event: string|symbol, exists: boolean): boolean;
/**
* Register a new EventListener for the given event.
* Calls each of the listeners registered for a 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
* @param {(string|symbol)} event The event name.
* @param {...*} args Arguments that are passed to registered listeners
* @returns {boolean} `true` if the event had listeners, else `false`.
*/
on(event: string, fn: Function, context?: any): EventEmitter;
emit(event: string|symbol, ...args: any[]): boolean;
/**
* Add an EventListener that's only called once.
* Add a listener for a 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
* @param {(string|symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
*/
once(event: string, fn: Function, context?: any): EventEmitter;
on(event: string|symbol, fn: Function, context?: any): this;
/**
* Remove event listeners.
* Add a one-time listener for a given event.
*
* @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
* @param {(string|symbol)} event The event name.
* @param {Function} fn The listener function.
* @param {*} [context=this] The context to invoke the listener with.
* @returns {EventEmitter} `this`.
*/
removeListener(event: string, fn?: Function, context?: any, once?: boolean): EventEmitter;
once(event: string|symbol, fn: Function, context?: any): this;
/**
* Remove all listeners or only the listeners for the specified event.
* Remove the listeners of a given event.
*
* @param {String} event The event want to remove all listeners for.
* @api public
* @param {(string|symbol)} event The event name.
* @param {Function} fn Only remove the listeners that match this function.
* @param {*} context Only remove the listeners that have this context.
* @param {boolean} once Only remove one-time listeners.
* @returns {EventEmitter} `this`.
*/
removeAllListeners(event?: string): EventEmitter;
removeListener(event: string|symbol, fn?: Function, context?: any, once?: boolean): this;
/**
* Remove event listeners.
* Remove all listeners, or those of the specified event.
*
* @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
* @param {(string|symbol)} event The event name.
* @returns {EventEmitter} `this`.
*/
off(event: string, fn?: Function, context?: any, once?: boolean): EventEmitter;
removeAllListeners(event?: string|symbol): this;
/**
* 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
* Alias method for `removeListener`
*/
addListener(event: string, fn: Function, context?: any): EventEmitter;
off(event: string|symbol, fn?: Function, context?: any, once?: boolean): this;
/**
* Alias method for `on`
*/
addListener(event: string|symbol, fn: Function, context?: any): this;
/**
* This function doesn't apply anymore.
* @deprecated
*/
setMaxListeners(): EventEmitter;
setMaxListeners(): this;
static prefixed: string|boolean;
}
}
declare module 'eventemitter3' {
//
// Expose the module.
//
var EventEmitter3: EventEmitter3.EventEmitter3Static;
export = EventEmitter3;
export = EventEmitter3.EventEmitter;
}