-
-
Notifications
You must be signed in to change notification settings - Fork 211
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
events: replace EventEmitter with a more simple version with the same…
… API
- Loading branch information
1 parent
881f9e0
commit f727b28
Showing
2 changed files
with
45 additions
and
298 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,301 +1,61 @@ | ||
/* istanbul ignore file */ | ||
/* eslint-disable */ | ||
/* | ||
* 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. | ||
*/ | ||
|
||
function EventEmitter() { | ||
this._events = this._events || {}; | ||
this._maxListeners = this._maxListeners || undefined; | ||
} | ||
|
||
module.exports = EventEmitter; | ||
|
||
// Backwards-compat with node 0.10.x | ||
EventEmitter.EventEmitter = EventEmitter; | ||
|
||
EventEmitter.prototype._events = undefined; | ||
EventEmitter.prototype._maxListeners = undefined; | ||
|
||
// By default EventEmitters will print a warning if more than 10 listeners are | ||
// added to it. This is a useful default which helps finding memory leaks. | ||
EventEmitter.defaultMaxListeners = 10; | ||
|
||
// Obviously not all Emitters should be limited to 10. This function allows | ||
// that to be increased. Set to zero for unlimited. | ||
EventEmitter.prototype.setMaxListeners = function(n) { | ||
if (!isNumber(n) || n < 0 || isNaN(n)) { | ||
throw TypeError("n must be a positive number"); | ||
class EventEmitter { | ||
constructor() { | ||
this._events = new Map(); | ||
} | ||
|
||
this._maxListeners = n; | ||
|
||
return this; | ||
}; | ||
|
||
EventEmitter.prototype.emit = function(type) { | ||
var er, handler, len, args, i, listeners; | ||
|
||
if (!this._events) { this._events = {}; } | ||
|
||
// If there is no 'error' event listener then throw. | ||
if (type === "error") { | ||
if (!this._events.error || (isObject(this._events.error) && !this._events.error.length)) { | ||
er = arguments[1]; | ||
if (er instanceof Error) { throw er; } | ||
throw TypeError("Uncaught, unspecified \"error\" event."); | ||
emit(type, ...args) { | ||
const listeners = this._events.get(type); | ||
if(!listeners) { | ||
return false; | ||
} | ||
} | ||
|
||
handler = this._events[type]; | ||
|
||
if (isUndefined(handler)) { return false; } | ||
|
||
if (isFunction(handler)) { | ||
switch (arguments.length) { | ||
// fast cases | ||
case 1: | ||
handler.call(this); | ||
break; | ||
case 2: | ||
handler.call(this, arguments[1]); | ||
break; | ||
case 3: | ||
handler.call(this, arguments[1], arguments[2]); | ||
break; | ||
// slower | ||
default: | ||
args = Array.prototype.slice.call(arguments, 1); | ||
handler.apply(this, args); | ||
for(const listener of listeners) { | ||
listener.apply(this, args); | ||
} | ||
} else if (isObject(handler)) { | ||
args = Array.prototype.slice.call(arguments, 1); | ||
listeners = handler.slice(); | ||
len = listeners.length; | ||
for (i = 0; i < len; i++) { listeners[i].apply(this, args); } | ||
} | ||
|
||
return true; | ||
}; | ||
|
||
EventEmitter.prototype.addListener = function(type, listener) { | ||
var m; | ||
|
||
if (!isFunction(listener)) { throw TypeError("listener must be a function"); } | ||
|
||
if (!this._events) { this._events = {}; } | ||
|
||
// To avoid recursion in the case that type === "newListener"! Before | ||
// adding it to the listeners, first emit "newListener". | ||
if (this._events.newListener) { | ||
this.emit("newListener", type, isFunction(listener.listener) ? listener.listener : listener); | ||
return true; | ||
} | ||
|
||
// Optimize the case of one listener. Don't need the extra array object. | ||
if (!this._events[type]) { this._events[type] = listener; } | ||
// If we've already got an array, just append. | ||
else if (isObject(this._events[type])) { this._events[type].push(listener); } | ||
// Adding the second element, need to change to array. | ||
else { this._events[type] = [this._events[type], listener]; } | ||
|
||
// Check for listener leak | ||
if (isObject(this._events[type]) && !this._events[type].warned) { | ||
if (!isUndefined(this._maxListeners)) { | ||
m = this._maxListeners; | ||
} else { | ||
m = EventEmitter.defaultMaxListeners; | ||
} | ||
|
||
if (m && m > 0 && this._events[type].length > m) { | ||
this._events[type].warned = true; | ||
console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.", this._events[type].length); | ||
// Not supported in IE 10 | ||
if (typeof console.trace === "function") { | ||
console.trace(); | ||
} | ||
emits(types, values) { | ||
for(let i = 0; i < types.length; i++) { | ||
const val = i < values.length ? values[i] : values[values.length - 1]; | ||
this.emit.apply(this, [ types[i] ].concat(val)); | ||
} | ||
} | ||
|
||
return this; | ||
}; | ||
|
||
EventEmitter.prototype.on = EventEmitter.prototype.addListener; | ||
|
||
// Modified to support multiple calls.. | ||
EventEmitter.prototype.once = function(type, listener) { | ||
if (!isFunction(listener)) { throw TypeError("listener must be a function"); } | ||
|
||
var fired = false; | ||
|
||
if (this._events.hasOwnProperty(type) && type.charAt(0) === "_") { | ||
var count = 1; | ||
var searchFor = type; | ||
|
||
for (var k in this._events){ | ||
if (this._events.hasOwnProperty(k) && k.startsWith(searchFor)) { | ||
count++; | ||
} | ||
addListener(type, listener) { | ||
if(!this._events.has(type)) { | ||
this._events.set(type, new Set()); | ||
} | ||
type = type + count; | ||
this._events.get(type).add(listener); | ||
} | ||
|
||
function g() { | ||
if (type.charAt(0) === "_" && !isNaN(type.substr(type.length - 1))) { | ||
type = type.substring(0, type.length - 1); | ||
} | ||
this.removeListener(type, g); | ||
|
||
if (!fired) { | ||
fired = true; | ||
listener.apply(this, arguments); | ||
} | ||
on(type, listener) { | ||
this.addListener(type, listener); | ||
} | ||
|
||
g.listener = listener; | ||
this.on(type, g); | ||
|
||
return this; | ||
}; | ||
|
||
// Emits a "removeListener" event if the listener was removed.. | ||
// Modified to support multiple calls from .once().. | ||
EventEmitter.prototype.removeListener = function(type, listener) { | ||
var list, position, length, i; | ||
|
||
if (!isFunction(listener)) { throw TypeError("listener must be a function"); } | ||
|
||
if (!this._events || !this._events[type]) { return this; } | ||
|
||
list = this._events[type]; | ||
length = list.length; | ||
position = -1; | ||
if (list === listener || (isFunction(list.listener) && list.listener === listener)) { | ||
delete this._events[type]; | ||
|
||
if (this._events.hasOwnProperty(type + "2") && type.charAt(0) === "_") { | ||
var searchFor = type; | ||
for (var k in this._events){ | ||
if (this._events.hasOwnProperty(k) && k.startsWith(searchFor)) { | ||
if (!isNaN(parseInt(k.substr(k.length - 1)))) { | ||
this._events[type + parseInt(k.substr(k.length - 1) - 1)] = this._events[k]; | ||
delete this._events[k]; | ||
} | ||
} | ||
} | ||
|
||
this._events[type] = this._events[type + "1"]; | ||
delete this._events[type + "1"]; | ||
} | ||
if (this._events.removeListener) { this.emit("removeListener", type, listener); } | ||
once(type, listener) { | ||
const wrapped = (...args) => { | ||
this.removeListener(type, wrapped); | ||
listener.apply(this, args); | ||
}; | ||
this.addListener(type, wrapped); | ||
} | ||
else if (isObject(list)) { | ||
for (i = length; i-- > 0;) { | ||
if (list[i] === listener || | ||
(list[i].listener && list[i].listener === listener)) { | ||
position = i; | ||
break; | ||
} | ||
removeListener(type, listener) { | ||
if(!this._events.has(type)) { | ||
return; | ||
} | ||
|
||
if (position < 0) { return this; } | ||
|
||
if (list.length === 1) { | ||
list.length = 0; | ||
delete this._events[type]; | ||
} | ||
else { list.splice(position, 1); } | ||
|
||
if (this._events.removeListener) { this.emit("removeListener", type, listener); } | ||
this._events.get(type).delete(listener); | ||
} | ||
|
||
return this; | ||
}; | ||
|
||
EventEmitter.prototype.removeAllListeners = function(type) { | ||
var key, listeners; | ||
|
||
if (!this._events) { return this; } | ||
|
||
// not listening for removeListener, no need to emit | ||
if (!this._events.removeListener) { | ||
if (arguments.length === 0) { this._events = {}; } | ||
else if (this._events[type]) { delete this._events[type]; } | ||
return this; | ||
off(type, listener) { | ||
this.removeListener(type, listener); | ||
} | ||
|
||
// emit removeListener for all listeners on all events | ||
if (arguments.length === 0) { | ||
for (key in this._events) { | ||
if (key === "removeListener") { continue; } | ||
this.removeAllListeners(key); | ||
} | ||
this.removeAllListeners("removeListener"); | ||
this._events = {}; | ||
return this; | ||
removeAllListeners(type) { | ||
this._events.delete(type); | ||
} | ||
|
||
listeners = this._events[type]; | ||
|
||
if (isFunction(listeners)) { this.removeListener(type, listeners); } | ||
else if (listeners) { while (listeners.length) { this.removeListener(type, listeners[listeners.length - 1]); } } | ||
delete this._events[type]; | ||
|
||
return this; | ||
}; | ||
|
||
EventEmitter.prototype.listeners = function(type) { | ||
var ret; | ||
if (!this._events || !this._events[type]) { ret = []; } | ||
else if (isFunction(this._events[type])) { ret = [this._events[type]]; } | ||
else { ret = this._events[type].slice(); } | ||
return ret; | ||
}; | ||
|
||
EventEmitter.prototype.listenerCount = function(type) { | ||
if (this._events) { | ||
var evlistener = this._events[type]; | ||
|
||
if (isFunction(evlistener)) { return 1; } | ||
else if (evlistener) { return evlistener.length; } | ||
listeners(type) { | ||
return this._events.get(type); | ||
} | ||
listenerCount(type) { | ||
const listeners = this._events.get(type); | ||
if(!listeners) { | ||
return 0; | ||
} | ||
return listeners.size; | ||
} | ||
return 0; | ||
}; | ||
|
||
EventEmitter.listenerCount = function(emitter, type) { | ||
return emitter.listenerCount(type); | ||
}; | ||
|
||
function isFunction(arg) { | ||
return typeof arg === "function"; | ||
} | ||
|
||
function isNumber(arg) { | ||
return typeof arg === "number"; | ||
} | ||
|
||
function isObject(arg) { | ||
return typeof arg === "object" && arg !== null; | ||
} | ||
|
||
function isUndefined(arg) { | ||
return arg === void 0; | ||
} | ||
module.exports = EventEmitter; |