| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408 | 
							- 'use strict';
 
- const anyMap = new WeakMap();
 
- const eventsMap = new WeakMap();
 
- const producersMap = new WeakMap();
 
- const anyProducer = Symbol('anyProducer');
 
- const resolvedPromise = Promise.resolve();
 
- const listenerAdded = Symbol('listenerAdded');
 
- const listenerRemoved = Symbol('listenerRemoved');
 
- function assertEventName(eventName) {
 
- 	if (typeof eventName !== 'string' && typeof eventName !== 'symbol') {
 
- 		throw new TypeError('eventName must be a string or a symbol');
 
- 	}
 
- }
 
- function assertListener(listener) {
 
- 	if (typeof listener !== 'function') {
 
- 		throw new TypeError('listener must be a function');
 
- 	}
 
- }
 
- function getListeners(instance, eventName) {
 
- 	const events = eventsMap.get(instance);
 
- 	if (!events.has(eventName)) {
 
- 		events.set(eventName, new Set());
 
- 	}
 
- 	return events.get(eventName);
 
- }
 
- function getEventProducers(instance, eventName) {
 
- 	const key = typeof eventName === 'string' || typeof eventName === 'symbol' ? eventName : anyProducer;
 
- 	const producers = producersMap.get(instance);
 
- 	if (!producers.has(key)) {
 
- 		producers.set(key, new Set());
 
- 	}
 
- 	return producers.get(key);
 
- }
 
- function enqueueProducers(instance, eventName, eventData) {
 
- 	const producers = producersMap.get(instance);
 
- 	if (producers.has(eventName)) {
 
- 		for (const producer of producers.get(eventName)) {
 
- 			producer.enqueue(eventData);
 
- 		}
 
- 	}
 
- 	if (producers.has(anyProducer)) {
 
- 		const item = Promise.all([eventName, eventData]);
 
- 		for (const producer of producers.get(anyProducer)) {
 
- 			producer.enqueue(item);
 
- 		}
 
- 	}
 
- }
 
- function iterator(instance, eventNames) {
 
- 	eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 	let isFinished = false;
 
- 	let flush = () => {};
 
- 	let queue = [];
 
- 	const producer = {
 
- 		enqueue(item) {
 
- 			queue.push(item);
 
- 			flush();
 
- 		},
 
- 		finish() {
 
- 			isFinished = true;
 
- 			flush();
 
- 		}
 
- 	};
 
- 	for (const eventName of eventNames) {
 
- 		getEventProducers(instance, eventName).add(producer);
 
- 	}
 
- 	return {
 
- 		async next() {
 
- 			if (!queue) {
 
- 				return {done: true};
 
- 			}
 
- 			if (queue.length === 0) {
 
- 				if (isFinished) {
 
- 					queue = undefined;
 
- 					return this.next();
 
- 				}
 
- 				await new Promise(resolve => {
 
- 					flush = resolve;
 
- 				});
 
- 				return this.next();
 
- 			}
 
- 			return {
 
- 				done: false,
 
- 				value: await queue.shift()
 
- 			};
 
- 		},
 
- 		async return(value) {
 
- 			queue = undefined;
 
- 			for (const eventName of eventNames) {
 
- 				getEventProducers(instance, eventName).delete(producer);
 
- 			}
 
- 			flush();
 
- 			return arguments.length > 0 ?
 
- 				{done: true, value: await value} :
 
- 				{done: true};
 
- 		},
 
- 		[Symbol.asyncIterator]() {
 
- 			return this;
 
- 		}
 
- 	};
 
- }
 
- function defaultMethodNamesOrAssert(methodNames) {
 
- 	if (methodNames === undefined) {
 
- 		return allEmitteryMethods;
 
- 	}
 
- 	if (!Array.isArray(methodNames)) {
 
- 		throw new TypeError('`methodNames` must be an array of strings');
 
- 	}
 
- 	for (const methodName of methodNames) {
 
- 		if (!allEmitteryMethods.includes(methodName)) {
 
- 			if (typeof methodName !== 'string') {
 
- 				throw new TypeError('`methodNames` element must be a string');
 
- 			}
 
- 			throw new Error(`${methodName} is not Emittery method`);
 
- 		}
 
- 	}
 
- 	return methodNames;
 
- }
 
- const isListenerSymbol = symbol => symbol === listenerAdded || symbol === listenerRemoved;
 
- class Emittery {
 
- 	static mixin(emitteryPropertyName, methodNames) {
 
- 		methodNames = defaultMethodNamesOrAssert(methodNames);
 
- 		return target => {
 
- 			if (typeof target !== 'function') {
 
- 				throw new TypeError('`target` must be function');
 
- 			}
 
- 			for (const methodName of methodNames) {
 
- 				if (target.prototype[methodName] !== undefined) {
 
- 					throw new Error(`The property \`${methodName}\` already exists on \`target\``);
 
- 				}
 
- 			}
 
- 			function getEmitteryProperty() {
 
- 				Object.defineProperty(this, emitteryPropertyName, {
 
- 					enumerable: false,
 
- 					value: new Emittery()
 
- 				});
 
- 				return this[emitteryPropertyName];
 
- 			}
 
- 			Object.defineProperty(target.prototype, emitteryPropertyName, {
 
- 				enumerable: false,
 
- 				get: getEmitteryProperty
 
- 			});
 
- 			const emitteryMethodCaller = methodName => function (...args) {
 
- 				return this[emitteryPropertyName][methodName](...args);
 
- 			};
 
- 			for (const methodName of methodNames) {
 
- 				Object.defineProperty(target.prototype, methodName, {
 
- 					enumerable: false,
 
- 					value: emitteryMethodCaller(methodName)
 
- 				});
 
- 			}
 
- 			return target;
 
- 		};
 
- 	}
 
- 	constructor() {
 
- 		anyMap.set(this, new Set());
 
- 		eventsMap.set(this, new Map());
 
- 		producersMap.set(this, new Map());
 
- 	}
 
- 	on(eventNames, listener) {
 
- 		assertListener(listener);
 
- 		eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 		for (const eventName of eventNames) {
 
- 			assertEventName(eventName);
 
- 			getListeners(this, eventName).add(listener);
 
- 			if (!isListenerSymbol(eventName)) {
 
- 				this.emit(listenerAdded, {eventName, listener});
 
- 			}
 
- 		}
 
- 		return this.off.bind(this, eventNames, listener);
 
- 	}
 
- 	off(eventNames, listener) {
 
- 		assertListener(listener);
 
- 		eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 		for (const eventName of eventNames) {
 
- 			assertEventName(eventName);
 
- 			getListeners(this, eventName).delete(listener);
 
- 			if (!isListenerSymbol(eventName)) {
 
- 				this.emit(listenerRemoved, {eventName, listener});
 
- 			}
 
- 		}
 
- 	}
 
- 	once(eventNames) {
 
- 		return new Promise(resolve => {
 
- 			const off = this.on(eventNames, data => {
 
- 				off();
 
- 				resolve(data);
 
- 			});
 
- 		});
 
- 	}
 
- 	events(eventNames) {
 
- 		eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 		for (const eventName of eventNames) {
 
- 			assertEventName(eventName);
 
- 		}
 
- 		return iterator(this, eventNames);
 
- 	}
 
- 	async emit(eventName, eventData) {
 
- 		assertEventName(eventName);
 
- 		enqueueProducers(this, eventName, eventData);
 
- 		const listeners = getListeners(this, eventName);
 
- 		const anyListeners = anyMap.get(this);
 
- 		const staticListeners = [...listeners];
 
- 		const staticAnyListeners = isListenerSymbol(eventName) ? [] : [...anyListeners];
 
- 		await resolvedPromise;
 
- 		await Promise.all([
 
- 			...staticListeners.map(async listener => {
 
- 				if (listeners.has(listener)) {
 
- 					return listener(eventData);
 
- 				}
 
- 			}),
 
- 			...staticAnyListeners.map(async listener => {
 
- 				if (anyListeners.has(listener)) {
 
- 					return listener(eventName, eventData);
 
- 				}
 
- 			})
 
- 		]);
 
- 	}
 
- 	async emitSerial(eventName, eventData) {
 
- 		assertEventName(eventName);
 
- 		const listeners = getListeners(this, eventName);
 
- 		const anyListeners = anyMap.get(this);
 
- 		const staticListeners = [...listeners];
 
- 		const staticAnyListeners = [...anyListeners];
 
- 		await resolvedPromise;
 
- 		/* eslint-disable no-await-in-loop */
 
- 		for (const listener of staticListeners) {
 
- 			if (listeners.has(listener)) {
 
- 				await listener(eventData);
 
- 			}
 
- 		}
 
- 		for (const listener of staticAnyListeners) {
 
- 			if (anyListeners.has(listener)) {
 
- 				await listener(eventName, eventData);
 
- 			}
 
- 		}
 
- 		/* eslint-enable no-await-in-loop */
 
- 	}
 
- 	onAny(listener) {
 
- 		assertListener(listener);
 
- 		anyMap.get(this).add(listener);
 
- 		this.emit(listenerAdded, {listener});
 
- 		return this.offAny.bind(this, listener);
 
- 	}
 
- 	anyEvent() {
 
- 		return iterator(this);
 
- 	}
 
- 	offAny(listener) {
 
- 		assertListener(listener);
 
- 		this.emit(listenerRemoved, {listener});
 
- 		anyMap.get(this).delete(listener);
 
- 	}
 
- 	clearListeners(eventNames) {
 
- 		eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 		for (const eventName of eventNames) {
 
- 			if (typeof eventName === 'string' || typeof eventName === 'symbol') {
 
- 				getListeners(this, eventName).clear();
 
- 				const producers = getEventProducers(this, eventName);
 
- 				for (const producer of producers) {
 
- 					producer.finish();
 
- 				}
 
- 				producers.clear();
 
- 			} else {
 
- 				anyMap.get(this).clear();
 
- 				for (const listeners of eventsMap.get(this).values()) {
 
- 					listeners.clear();
 
- 				}
 
- 				for (const producers of producersMap.get(this).values()) {
 
- 					for (const producer of producers) {
 
- 						producer.finish();
 
- 					}
 
- 					producers.clear();
 
- 				}
 
- 			}
 
- 		}
 
- 	}
 
- 	listenerCount(eventNames) {
 
- 		eventNames = Array.isArray(eventNames) ? eventNames : [eventNames];
 
- 		let count = 0;
 
- 		for (const eventName of eventNames) {
 
- 			if (typeof eventName === 'string') {
 
- 				count += anyMap.get(this).size + getListeners(this, eventName).size +
 
- 					getEventProducers(this, eventName).size + getEventProducers(this).size;
 
- 				continue;
 
- 			}
 
- 			if (typeof eventName !== 'undefined') {
 
- 				assertEventName(eventName);
 
- 			}
 
- 			count += anyMap.get(this).size;
 
- 			for (const value of eventsMap.get(this).values()) {
 
- 				count += value.size;
 
- 			}
 
- 			for (const value of producersMap.get(this).values()) {
 
- 				count += value.size;
 
- 			}
 
- 		}
 
- 		return count;
 
- 	}
 
- 	bindMethods(target, methodNames) {
 
- 		if (typeof target !== 'object' || target === null) {
 
- 			throw new TypeError('`target` must be an object');
 
- 		}
 
- 		methodNames = defaultMethodNamesOrAssert(methodNames);
 
- 		for (const methodName of methodNames) {
 
- 			if (target[methodName] !== undefined) {
 
- 				throw new Error(`The property \`${methodName}\` already exists on \`target\``);
 
- 			}
 
- 			Object.defineProperty(target, methodName, {
 
- 				enumerable: false,
 
- 				value: this[methodName].bind(this)
 
- 			});
 
- 		}
 
- 	}
 
- }
 
- const allEmitteryMethods = Object.getOwnPropertyNames(Emittery.prototype).filter(v => v !== 'constructor');
 
- Object.defineProperty(Emittery, 'listenerAdded', {
 
- 	value: listenerAdded,
 
- 	writable: false,
 
- 	enumerable: true,
 
- 	configurable: false
 
- });
 
- Object.defineProperty(Emittery, 'listenerRemoved', {
 
- 	value: listenerRemoved,
 
- 	writable: false,
 
- 	enumerable: true,
 
- 	configurable: false
 
- });
 
- module.exports = Emittery;
 
 
  |