| Index: third_party/WebKit/Source/devtools/front_end/common/Object.js
 | 
| diff --git a/third_party/WebKit/Source/devtools/front_end/common/Object.js b/third_party/WebKit/Source/devtools/front_end/common/Object.js
 | 
| index cf053942051630186538752c734f6ee4ea6fcb5d..6f5d793c827a6d14ee94043e1b8a9248b4074a63 100644
 | 
| --- a/third_party/WebKit/Source/devtools/front_end/common/Object.js
 | 
| +++ b/third_party/WebKit/Source/devtools/front_end/common/Object.js
 | 
| @@ -90,6 +90,56 @@ Common.Object = class {
 | 
|      for (var i = 0; i < listeners.length; ++i)
 | 
|        listeners[i].listener.call(listeners[i].thisObject, event);
 | 
|    }
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @override
 | 
| +   * @param {function(new:T, ...)} eventType
 | 
| +   * @param {function(!T)} listener
 | 
| +   * @param {!Object=} thisObject
 | 
| +   * @return {!Common.EventTarget.TypedEventDescriptor}
 | 
| +   */
 | 
| +  on(eventType, listener, thisObject) {
 | 
| +    if (!this._listeners)
 | 
| +      this._listeners = new Map();
 | 
| +    if (!this._listeners.has(eventType))
 | 
| +      this._listeners.set(eventType, []);
 | 
| +    this._listeners.get(eventType).push({thisObject: thisObject, listener: listener});
 | 
| +    return new Common.EventTarget.TypedEventDescriptor(this, eventType, thisObject, listener);
 | 
| +  }
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @override
 | 
| +   * @param {function(new:T, ...)} eventType
 | 
| +   * @param {function(!T)} listener
 | 
| +   * @param {!Object=} thisObject
 | 
| +   */
 | 
| +  off(eventType, listener, thisObject) {
 | 
| +    if (!this._listeners || !this._listeners.has(eventType))
 | 
| +      return;
 | 
| +    var listeners = this._listeners.get(eventType);
 | 
| +    for (var i = 0; i < listeners.length; ++i) {
 | 
| +      if (listeners[i].listener === listener && listeners[i].thisObject === thisObject)
 | 
| +        listeners.splice(i--, 1);
 | 
| +    }
 | 
| +    if (!listeners.length)
 | 
| +      this._listeners.delete(eventType);
 | 
| +  }
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @override
 | 
| +   * @param {!T} event
 | 
| +   */
 | 
| +  emit(event) {
 | 
| +    var eventType = event.constructor;
 | 
| +    if (!this._listeners || !this._listeners.has(eventType))
 | 
| +      return;
 | 
| +    var listeners = this._listeners.get(eventType).slice(0);
 | 
| +    for (var i = 0; i < listeners.length; ++i)
 | 
| +      listeners[i].listener.call(listeners[i].thisObject, event);
 | 
| +  }
 | 
|  };
 | 
|  
 | 
|  /**
 | 
| @@ -110,12 +160,15 @@ Common.Event = class {
 | 
|  Common.EventTarget = function() {};
 | 
|  
 | 
|  /**
 | 
| - * @param {!Array<!Common.EventTarget.EventDescriptor>} eventList
 | 
| + * @param {!Array<!Common.EventTarget.EventDescriptor|!Common.EventTarget.TypedEventDescriptor>} eventList
 | 
|   */
 | 
|  Common.EventTarget.removeEventListeners = function(eventList) {
 | 
|    for (var i = 0; i < eventList.length; ++i) {
 | 
|      var eventInfo = eventList[i];
 | 
| -    eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.method, eventInfo.receiver);
 | 
| +    if (eventInfo instanceof Common.EventTarget.EventDescriptor)
 | 
| +      eventInfo.eventTarget.removeEventListener(eventInfo.eventType, eventInfo.method, eventInfo.receiver);
 | 
| +    else
 | 
| +      eventInfo.eventTarget.off(eventInfo.eventType, eventInfo.method, eventInfo.receiver);
 | 
|    }
 | 
|    // Do not hold references on unused event descriptors.
 | 
|    eventList.splice(0, eventList.length);
 | 
| @@ -148,6 +201,29 @@ Common.EventTarget.prototype = {
 | 
|     * @param {*=} eventData
 | 
|     */
 | 
|    dispatchEventToListeners(eventType, eventData) {},
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @param {function(new:T, ...)} eventType
 | 
| +   * @param {function(!T)} listener
 | 
| +   * @param {!Object=} thisObject
 | 
| +   * @return {!Common.EventTarget.TypedEventDescriptor}
 | 
| +   */
 | 
| +  on(eventType, listener, thisObject) {},
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @param {function(new:T, ...)} eventType
 | 
| +   * @param {function(!T)} listener
 | 
| +   * @param {!Object=} thisObject
 | 
| +   */
 | 
| +  off(eventType, listener, thisObject) {},
 | 
| +
 | 
| +  /**
 | 
| +   * @template T
 | 
| +   * @param {!T} event
 | 
| +   */
 | 
| +  emit(event) {},
 | 
|  };
 | 
|  
 | 
|  /**
 | 
| @@ -167,3 +243,22 @@ Common.EventTarget.EventDescriptor = class {
 | 
|      this.method = method;
 | 
|    }
 | 
|  };
 | 
| +
 | 
| +/**
 | 
| + * @template T
 | 
| + * @unrestricted
 | 
| + */
 | 
| +Common.EventTarget.TypedEventDescriptor = class {
 | 
| +  /**
 | 
| +   * @param {!Common.EventTarget} eventTarget
 | 
| +   * @param {function(new:T, ...)} eventType
 | 
| +   * @param {(!Object|undefined)} receiver
 | 
| +   * @param {function(!T)} method
 | 
| +   */
 | 
| +  constructor(eventTarget, eventType, receiver, method) {
 | 
| +    this.eventTarget = eventTarget;
 | 
| +    this.eventType = eventType;
 | 
| +    this.receiver = receiver;
 | 
| +    this.method = method;
 | 
| +  }
 | 
| +};
 | 
| 
 |