Skip to content

Note Web Inspector event listeners

Brian Burg edited this page Mar 29, 2014 · 2 revisions

Web Inspector uses two different event dispatch systems:

DOM event dispatch

This is the event dispatch used on normal webpages (MDN Docs). Event names are typically provided as a string. the last argument is whether it's a capturing handler (=true) or bubbling handler.

    this.element.addEventListener("dblclick", this._onMiniviewDoubleClicked.bind(this), true);

In this case, you need not worry about removing the event listener from this.element, because it will be removed by garbage collection when this.element is removed from the document and GC'd. (In old versions of IE, this was not GC'd, and was a horrible memory leak for everyone.)

Inspector event dispatch

This event dispatch system is homegrown for the inspector frontend. Instead of a tree-based dispatch algorithm, it uses a simple array of listeners for each WebInspector.Object instance, and dispatches the event linearly to each listener. Here's an example:

    this._model.addEventListener(eventNames.InputPaused, this._onInputPaused, this);

Several things are different:

  • The first argument is usually a property of an object, which corresponds to a string. This provides better scoping.
  • The third argument is the object to be used as the this context for the listener invocation. This is nicer because we don't have to store the this-bound closure, but...
  • Without further care, this will leak memory even when unused, because the dispatching object (in this case, this._model) will keep a reference to the this-object.

If WebInspector.Object used a weak map to store this-objects, then this wouldn't be a problem. But, they don't yet, so we must be careful to remove event listeners when they aren't needed any more. This is especially a problem for listeners registered with objects that rarely or never get GC'd by design. In Timelapse code, this is WebInspector.TimelapseModel (singleton like much of Inspector code) and WebInspector.TimelapseRecording (cleared when unloaded).

Something went wrong with that request. Please try again.