| Index: lib/events.js | 
| =================================================================== | 
| --- a/lib/events.js | 
| +++ b/lib/events.js | 
| @@ -48,19 +48,28 @@ | 
| * @param {string}   name | 
| * @param {function} listener | 
| */ | 
| off(name, listener) | 
| { | 
| let listeners = this._listeners.get(name); | 
| if (listeners) | 
| { | 
| -      let idx = listeners.indexOf(listener); | 
| -      if (idx != -1) | 
| -        listeners.splice(idx, 1); | 
| +      if (listeners.length > 1) | 
| +      { | 
| +        let idx = listeners.indexOf(listener); | 
| +        if (idx != -1) | 
| +          listeners.splice(idx, 1); | 
| +      } | 
| +      else if (listeners[0] === listener) | 
| +      { | 
| +        // We must use strict equality above for compatibility with | 
| +        // Array.prototype.indexOf | 
| +        this._listeners.delete(name); | 
| +      } | 
| } | 
| } | 
|  | 
| /** | 
| * Adds a one time listener and returns a promise that | 
| * is resolved the next time the specified event is emitted. | 
| * | 
| * @param {string} name | 
| @@ -83,27 +92,43 @@ | 
| /** | 
| * Returns a copy of the array of listeners for the specified event. | 
| * | 
| * @param {string} name | 
| * @returns {Array.<function>} | 
| */ | 
| listeners(name) | 
| { | 
| -    let listeners = this._listeners.get(name); | 
| +    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null; | 
| return listeners ? listeners.slice() : []; | 
| } | 
|  | 
| /** | 
| +   * Checks whether there are any listeners for the specified event. | 
| +   * | 
| +   * @param {string} [name] The name of the event. If omitted, checks whether | 
| +   *   there are any listeners for any event. | 
| +   * @returns {boolean} | 
| +   */ | 
| +  hasListeners(name) | 
| +  { | 
| +    return this._listeners.size > 0 && | 
| +           (typeof name == "undefined" || this._listeners.has(name)); | 
| +  } | 
| + | 
| +  /** | 
| * Calls all previously added listeners for the given event name. | 
| * | 
| * @param {string} name | 
| * @param {...*}   [args] | 
| */ | 
| emit(name, ...args) | 
| { | 
| -    let listeners = this.listeners(name); | 
| -    for (let listener of listeners) | 
| -      listener(...args); | 
| +    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null; | 
| +    if (listeners) | 
| +    { | 
| +      for (let listener of listeners.slice()) | 
| +        listener(...args); | 
| +    } | 
| } | 
| } | 
|  | 
| exports.EventEmitter = EventEmitter; | 
|  |