diff --git a/lib/events.js b/lib/events.js index 58dde3ef318..d0bcc3b79a6 100644 --- a/lib/events.js +++ b/lib/events.js @@ -245,37 +245,42 @@ EventEmitter.prototype.removeListener = function(type, listener) { }; EventEmitter.prototype.removeAllListeners = function(type) { - if (!this._events) return this; + var key, listeners; - // fast path + if (arguments.length > 0 && typeof type !== 'string') + throw TypeError('type must not be set or must be a string'); + + 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 (type && this._events && this._events[type]) { + if (arguments.length === 0) + this._events = null; + else if (this._events[type]) this._events[type] = null; - } return this; } - // slow(ish) path, emit 'removeListener' events for all removals + // emit removeListener for all listeners on all events if (arguments.length === 0) { - for (var key in this._events) { + for (key in this._events) { if (key === 'removeListener') continue; this.removeAllListeners(key); } this.removeAllListeners('removeListener'); - this._events = {}; + this._events = null; return this; } - var listeners = this._events[type]; - if (isArray(listeners)) { - while (listeners.length) { - // LIFO order - this.removeListener(type, listeners[listeners.length - 1]); - } - } else if (listeners) { + listeners = this._events[type]; + + if (typeof listeners === 'function') { this.removeListener(type, listeners); + } else { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); } this._events[type] = null;