Bug 1318835 - Inspector should own the one instance of the HighlightersOverlay. r=pbro
authorGabriel Luong <gabriel.luong@gmail.com>
Mon, 28 Nov 2016 21:10:53 +0800
changeset 324443 1da7f7deca3216262b7140e578076ecb2cc65378
parent 324442 d6ec40f470fced56227e005c08ee40a0f5a47b5b
child 324444 ecd2e5b74e52d190cec7f887806adacd245d04d7
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewerspbro
bugs1318835
milestone53.0a1
Bug 1318835 - Inspector should own the one instance of the HighlightersOverlay. r=pbro
devtools/client/inspector/computed/computed.js
devtools/client/inspector/inspector.js
devtools/client/inspector/rules/rules.js
devtools/client/inspector/shared/highlighters-overlay.js
devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-01.js
devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-02.js
--- a/devtools/client/inspector/computed/computed.js
+++ b/devtools/client/inspector/computed/computed.js
@@ -12,17 +12,16 @@ const {ELEMENT_STYLE} = require("devtool
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const Services = require("Services");
 const {OutputParser} = require("devtools/client/shared/output-parser");
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {createChild} = require("devtools/client/inspector/shared/utils");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const {
   VIEW_NODE_SELECTOR_TYPE,
   VIEW_NODE_PROPERTY_TYPE,
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_IMAGE_URL_TYPE,
 } = require("devtools/client/inspector/shared/node-types");
 const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
 const TooltipsOverlay = require("devtools/client/inspector/shared/tooltips-overlay");
@@ -147,16 +146,17 @@ UpdateProcess.prototype = {
  * @param {Document} document
  *        The document that will contain the computed view.
  * @param {PageStyleFront} pageStyle
  *        Front for the page style actor that will be providing
  *        the style information.
  */
 function CssComputedView(inspector, document, pageStyle) {
   this.inspector = inspector;
+  this.highlighters = inspector.highlighters;
   this.styleDocument = document;
   this.styleWindow = this.styleDocument.defaultView;
   this.pageStyle = pageStyle;
 
   this.propertyViews = [];
 
   let cssProperties = getCssProperties(inspector.toolbox);
   this._outputParser = new OutputParser(document, cssProperties);
@@ -211,18 +211,17 @@ function CssComputedView(inspector, docu
   this.createStyleViews();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: false });
 
   // Add the tooltips and highlightersoverlay
   this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
 
-  this.highlighters = new HighlightersOverlay(this);
-  this.highlighters.addToView();
+  this.highlighters.addToView(this);
 }
 
 /**
  * Lookup a l10n string in the shared styleinspector string bundle.
  *
  * @param {String} name
  *        The key to lookup.
  * @returns {String} localized version of the given key.
@@ -748,17 +747,17 @@ CssComputedView.prototype = {
 
     // Remove context menu
     if (this._contextmenu) {
       this._contextmenu.destroy();
       this._contextmenu = null;
     }
 
     this.tooltips.destroy();
-    this.highlighters.destroy();
+    this.highlighters.removeFromView(this);
 
     // Remove bound listeners
     this.styleDocument.removeEventListener("mousedown", this.focusWindow);
     this.element.removeEventListener("click", this._onClick);
     this.element.removeEventListener("copy", this._onCopy);
     this.element.removeEventListener("contextmenu", this._onContextMenu);
     this.searchField.removeEventListener("input", this._onFilterStyles);
     this.searchField.removeEventListener("contextmenu",
@@ -776,16 +775,17 @@ CssComputedView.prototype = {
 
     // Property views
     for (let propView of this.propertyViews) {
       propView.destroy();
     }
     this.propertyViews = null;
 
     this.inspector = null;
+    this.highlighters = null;
     this.styleDocument = null;
     this.styleWindow = null;
 
     this._isDestroyed = true;
   }
 };
 
 function PropertyInfo(tree, name) {
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -19,24 +19,25 @@ var {KeyShortcuts} = require("devtools/c
 var {Task} = require("devtools/shared/task");
 const {initCssProperties} = require("devtools/shared/fronts/css-properties");
 const nodeConstants = require("devtools/shared/dom-node-constants");
 const Telemetry = require("devtools/client/shared/telemetry");
 
 const Menu = require("devtools/client/framework/menu");
 const MenuItem = require("devtools/client/framework/menu-item");
 
-const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
+const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
 const {ComputedViewTool} = require("devtools/client/inspector/computed/computed");
 const {FontInspector} = require("devtools/client/inspector/fonts/fonts");
-const {HTMLBreadcrumbs} = require("devtools/client/inspector/breadcrumbs");
 const {InspectorSearch} = require("devtools/client/inspector/inspector-search");
+const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
+const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
+const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
 const MarkupView = require("devtools/client/inspector/markup/markup");
-const {RuleViewTool} = require("devtools/client/inspector/rules/rules");
-const {ToolSidebar} = require("devtools/client/inspector/toolsidebar");
+const {CommandUtils} = require("devtools/client/shared/developer-toolbar");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 const clipboardHelper = require("devtools/shared/platform/clipboard");
 
 const {LocalizationHelper, localizeMarkup} = require("devtools/shared/l10n");
 const INSPECTOR_L10N =
       new LocalizationHelper("devtools/client/locales/inspector.properties");
 const TOOLBOX_L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
 
@@ -87,16 +88,17 @@ const PORTRAIT_MODE_WIDTH = 700;
  */
 function Inspector(toolbox) {
   this._toolbox = toolbox;
   this._target = toolbox.target;
   this.panelDoc = window.document;
   this.panelWin = window;
   this.panelWin.inspector = this;
 
+  this.highlighters = new HighlightersOverlay(this);
   this.telemetry = new Telemetry();
 
   this.nodeMenuTriggerInfo = null;
 
   this._handleRejectionIfNotDestroyed = this._handleRejectionIfNotDestroyed.bind(this);
   this._onBeforeNavigate = this._onBeforeNavigate.bind(this);
   this.onNewRoot = this.onNewRoot.bind(this);
   this._onContextMenu = this._onContextMenu.bind(this);
@@ -906,23 +908,29 @@ Inspector.prototype = {
     this.teardownSplitter();
 
     this.sidebar = null;
 
     this.teardownToolbar();
     this.breadcrumbs.destroy();
     this.selection.off("new-node-front", this.onNewSelection);
     this.selection.off("detached-front", this.onDetached);
+
     let markupDestroyer = this._destroyMarkup();
+
     this.panelWin.inspector = null;
     this.target = null;
     this.panelDoc = null;
     this.panelWin = null;
     this.breadcrumbs = null;
     this._toolbox = null;
+
+    this.highlighters.destroy();
+    this.highlighters = null;
+
     this.search.destroy();
     this.search = null;
     this.searchBox = null;
 
     this._panelDestroyer = promise.all([
       sidebarDestroyer,
       markupDestroyer,
       cssPropertiesDestroyer
--- a/devtools/client/inspector/rules/rules.js
+++ b/devtools/client/inspector/rules/rules.js
@@ -14,17 +14,16 @@ const {l10n} = require("devtools/shared/
 const {ELEMENT_STYLE} = require("devtools/shared/specs/styles");
 const {OutputParser} = require("devtools/client/shared/output-parser");
 const {PrefObserver, PREF_ORIG_SOURCES} = require("devtools/client/styleeditor/utils");
 const {ElementStyle} = require("devtools/client/inspector/rules/models/element-style");
 const {Rule} = require("devtools/client/inspector/rules/models/rule");
 const {RuleEditor} = require("devtools/client/inspector/rules/views/rule-editor");
 const {gDevTools} = require("devtools/client/framework/devtools");
 const {getCssProperties} = require("devtools/shared/fronts/css-properties");
-const HighlightersOverlay = require("devtools/client/inspector/shared/highlighters-overlay");
 const {
   VIEW_NODE_SELECTOR_TYPE,
   VIEW_NODE_PROPERTY_TYPE,
   VIEW_NODE_VALUE_TYPE,
   VIEW_NODE_IMAGE_URL_TYPE,
   VIEW_NODE_LOCATION_TYPE,
 } = require("devtools/client/inspector/shared/node-types");
 const StyleInspectorMenu = require("devtools/client/inspector/shared/style-inspector-menu");
@@ -95,16 +94,17 @@ const FILTER_STRICT_RE = /\s*`(.*?)`\s*$
  *        The CSS rule view can use this object to store metadata
  *        that might outlast the rule view, particularly the current
  *        set of disabled properties.
  * @param {PageStyleFront} pageStyle
  *        The PageStyleFront for communicating with the remote server.
  */
 function CssRuleView(inspector, document, store, pageStyle) {
   this.inspector = inspector;
+  this.highlighters = inspector.highlighters;
   this.styleDocument = document;
   this.styleWindow = this.styleDocument.defaultView;
   this.store = store || {};
   this.pageStyle = pageStyle;
 
   // Allow tests to override throttling behavior, as this can cause intermittents.
   this.throttle = throttle;
 
@@ -172,18 +172,18 @@ function CssRuleView(inspector, document
 
   this._showEmpty();
 
   this._contextmenu = new StyleInspectorMenu(this, { isRuleView: true });
 
   // Add the tooltips and highlighters to the view
   this.tooltips = new TooltipsOverlay(this);
   this.tooltips.addToView();
-  this.highlighters = new HighlightersOverlay(this);
-  this.highlighters.addToView();
+
+  this.highlighters.addToView(this);
 
   EventEmitter.decorate(this);
 }
 
 CssRuleView.prototype = {
   // The element that we're inspecting.
   _viewedElement: null,
 
@@ -247,59 +247,47 @@ CssRuleView.prototype = {
    *
    * @param {DOMNode} selectorIcon
    *        The icon that was clicked to toggle the selector. The
    *        class 'highlighted' will be added when the selector is
    *        highlighted.
    * @param {String} selector
    *        The selector used to find nodes in the page.
    */
-  toggleSelectorHighlighter: function (selectorIcon, selector) {
+  toggleSelectorHighlighter: Task.async(function* (selectorIcon, selector) {
     if (this.lastSelectorIcon) {
       this.lastSelectorIcon.classList.remove("highlighted");
     }
     selectorIcon.classList.remove("highlighted");
 
-    this.unhighlightSelector().then(() => {
-      if (selector !== this.highlighters.selectorHighlighterShown) {
-        this.highlighters.selectorHighlighterShown = selector;
-        selectorIcon.classList.add("highlighted");
-        this.lastSelectorIcon = selectorIcon;
-        this.highlightSelector(selector).then(() => {
-          this.emit("ruleview-selectorhighlighter-toggled", true);
-        }, e => console.error(e));
-      } else {
-        this.highlighters.selectorHighlighterShown = null;
-        this.emit("ruleview-selectorhighlighter-toggled", false);
-      }
-    }, e => console.error(e));
-  },
-
-  highlightSelector: Task.async(function* (selector) {
-    let highlighter = yield this.getSelectorHighlighter();
-    if (!highlighter) {
-      return;
-    }
-
-    let node = this.inspector.selection.nodeFront;
-
-    yield highlighter.show(node, {
-      hideInfoBar: true,
-      hideGuides: true,
-      selector
-    });
-  }),
-
-  unhighlightSelector: Task.async(function* () {
     let highlighter = yield this.getSelectorHighlighter();
     if (!highlighter) {
       return;
     }
 
     yield highlighter.hide();
+
+    if (selector !== this.highlighters.selectorHighlighterShown) {
+      this.highlighters.selectorHighlighterShown = selector;
+      selectorIcon.classList.add("highlighted");
+      this.lastSelectorIcon = selectorIcon;
+
+      let node = this.inspector.selection.nodeFront;
+
+      yield highlighter.show(node, {
+        hideInfoBar: true,
+        hideGuides: true,
+        selector
+      });
+
+      this.emit("ruleview-selectorhighlighter-toggled", true);
+    } else {
+      this.highlighters.selectorHighlighterShown = null;
+      this.emit("ruleview-selectorhighlighter-toggled", false);
+    }
   }),
 
   /**
    * Get the type of a given node in the rule-view
    *
    * @param {DOMNode} node
    *        The node which we want information about
    * @return {Object} The type information object contains the following props:
@@ -678,17 +666,17 @@ CssRuleView.prototype = {
 
     // Remove context menu
     if (this._contextmenu) {
       this._contextmenu.destroy();
       this._contextmenu = null;
     }
 
     this.tooltips.destroy();
-    this.highlighters.destroy();
+    this.highlighters.removeFromView(this);
 
     // Remove bound listeners
     this.shortcuts.destroy();
     this.element.removeEventListener("copy", this._onCopy);
     this.element.removeEventListener("contextmenu", this._onContextMenu);
     this.addRuleButton.removeEventListener("click", this._onAddRule);
     this.searchField.removeEventListener("input", this._onFilterStyles);
     this.searchField.removeEventListener("contextmenu",
@@ -704,16 +692,17 @@ CssRuleView.prototype = {
     this.searchClearButton = null;
     this.pseudoClassPanel = null;
     this.pseudoClassToggle = null;
     this.hoverCheckbox = null;
     this.activeCheckbox = null;
     this.focusCheckbox = null;
 
     this.inspector = null;
+    this.highlighters = null;
     this.styleDocument = null;
     this.styleWindow = null;
 
     if (this.element.parentNode) {
       this.element.parentNode.removeChild(this.element);
     }
 
     if (this._elementStyle) {
--- a/devtools/client/inspector/shared/highlighters-overlay.js
+++ b/devtools/client/inspector/shared/highlighters-overlay.js
@@ -11,121 +11,119 @@
  * property values.
  */
 
 const promise = require("promise");
 const EventEmitter = require("devtools/shared/event-emitter");
 const { VIEW_NODE_VALUE_TYPE } = require("devtools/client/inspector/shared/node-types");
 
 /**
- * Manages all highlighters in the style-inspector.
+ * Highlighters overlay is a singleton managing all highlighters in the Inspector.
  *
- * @param  {CssRuleView|CssComputedView} view
- *         Either the rule-view or computed-view panel
+ * @param  {Inspector} inspector
+ *         Inspector toolbox panel.
  */
-function HighlightersOverlay(view) {
-  this.view = view;
+function HighlightersOverlay(inspector) {
+  this.inspector = inspector;
+  this.highlighters = {};
+  this.highlighterUtils = this.inspector.toolbox.highlighterUtils;
 
-  let {CssRuleView} = require("devtools/client/inspector/rules/rules");
-  this.isRuleView = view instanceof CssRuleView;
-
-  this.highlighters = {};
+  // Only initialize the overlay if at least one of the highlighter types is supported.
+  this.supportsHighlighters = this.highlighterUtils.supportsCustomHighlighters();
 
   // NodeFront of the grid container that is highlighted.
   this.gridHighlighterShown = null;
   // Name of the highlighter shown on mouse hover.
   this.hoveredHighlighterShown = null;
   // Name of the selector highlighter shown.
   this.selectorHighlighterShown = null;
 
-  this.highlighterUtils = this.view.inspector.toolbox.highlighterUtils;
-
-  // Only initialize the overlay if at least one of the highlighter types is
-  // supported.
-  this.supportsHighlighters =
-    this.highlighterUtils.supportsCustomHighlighters();
-
   this._onClick = this._onClick.bind(this);
   this._onMouseMove = this._onMouseMove.bind(this);
   this._onMouseOut = this._onMouseOut.bind(this);
   this._onWillNavigate = this._onWillNavigate.bind(this);
 
   EventEmitter.decorate(this);
 }
 
 HighlightersOverlay.prototype = {
+  get isRuleView() {
+    return this.inspector.sidebar.getCurrentTabID() == "ruleview";
+  },
+
   /**
-   * Add the highlighters overlay to the view. This will start tracking mouse
-   * movements and display highlighters when needed.
+   * Add the highlighters overlay to the view. This will start tracking mouse events
+   * and display highlighters when needed.
+   *
+   * @param  {CssRuleView|CssComputedView|LayoutView} view
+   *         Either the rule-view or computed-view panel to add the highlighters overlay.
+   *
    */
-  addToView: function () {
-    if (!this.supportsHighlighters || this._isStarted || this._isDestroyed) {
+  addToView: function (view) {
+    if (!this.supportsHighlighters) {
       return;
     }
 
-    let el = this.view.element;
+    let el = view.element;
     el.addEventListener("click", this._onClick, true);
     el.addEventListener("mousemove", this._onMouseMove, false);
     el.addEventListener("mouseout", this._onMouseOut, false);
     el.ownerDocument.defaultView.addEventListener("mouseout", this._onMouseOut, false);
 
-    if (this.isRuleView) {
-      this.view.inspector.target.on("will-navigate", this._onWillNavigate);
-    }
-
-    this._isStarted = true;
+    this.inspector.target.on("will-navigate", this._onWillNavigate);
   },
 
   /**
-   * Remove the overlay from the current view. This will stop tracking mouse
-   * movement and showing highlighters.
+   * Remove the overlay from the given view. This will stop tracking mouse movement and
+   * showing highlighters.
+   *
+   * @param  {CssRuleView|CssComputedView|LayoutView} view
+   *         Either the rule-view or computed-view panel to remove the highlighters
+   *         overlay.
    */
-  removeFromView: function () {
-    if (!this.supportsHighlighters || !this._isStarted || this._isDestroyed) {
+  removeFromView: function (view) {
+    if (!this.supportsHighlighters) {
       return;
     }
 
-    let el = this.view.element;
+    let el = view.element;
     el.removeEventListener("click", this._onClick, true);
     el.removeEventListener("mousemove", this._onMouseMove, false);
     el.removeEventListener("mouseout", this._onMouseOut, false);
 
-    if (this.isRuleView) {
-      this.view.inspector.target.off("will-navigate", this._onWillNavigate);
-    }
-
-    this._isStarted = false;
+    this.inspector.target.off("will-navigate", this._onWillNavigate);
   },
 
   _onClick: function (event) {
     // Bail out if the target is not a grid property value.
-    if (!this._isDisplayGridValue(event.target)) {
+    if (!this._isRuleViewDisplayGrid(event.target)) {
       return;
     }
 
     event.stopPropagation();
 
     this._getHighlighter("CssGridHighlighter").then(highlighter => {
-      let node = this.view.inspector.selection.nodeFront;
+      let node = this.inspector.selection.nodeFront;
 
       // Toggle off the grid highlighter if the grid highlighter toggle is clicked
       // for the current highlighted grid.
       if (node === this.gridHighlighterShown) {
         return highlighter.hide();
       }
 
       return highlighter.show(node);
     }).then(isGridShown => {
       // Toggle all the grid icons in the current rule view.
-      for (let gridIcon of this.view.element.querySelectorAll(".ruleview-grid")) {
+      let ruleViewEl = this.inspector.ruleview.view.element;
+      for (let gridIcon of ruleViewEl.querySelectorAll(".ruleview-grid")) {
         gridIcon.classList.toggle("active", isGridShown);
       }
 
       if (isGridShown) {
-        this.gridHighlighterShown = this.view.inspector.selection.nodeFront;
+        this.gridHighlighterShown = this.inspector.selection.nodeFront;
         this.emit("highlighter-shown");
       } else {
         this.gridHighlighterShown = null;
         this.emit("highlighter-hidden");
       }
     }).catch(e => console.error(e));
   },
 
@@ -135,31 +133,33 @@ HighlightersOverlay.prototype = {
       return;
     }
 
     // Only one highlighter can be displayed at a time, hide the currently shown.
     this._hideHoveredHighlighter();
 
     this._lastHovered = event.target;
 
-    let nodeInfo = this.view.getNodeInfo(event.target);
+    let view = this.isRuleView ?
+      this.inspector.ruleview.view : this.inspector.computedview.computedView;
+    let nodeInfo = view.getNodeInfo(event.target);
     if (!nodeInfo) {
       return;
     }
 
     // Choose the type of highlighter required for the hovered node.
     let type;
     if (this._isRuleViewTransform(nodeInfo) ||
         this._isComputedViewTransform(nodeInfo)) {
       type = "CssTransformHighlighter";
     }
 
     if (type) {
       this.hoveredHighlighterShown = type;
-      let node = this.view.inspector.selection.nodeFront;
+      let node = this.inspector.selection.nodeFront;
       this._getHighlighter(type)
           .then(highlighter => highlighter.show(node))
           .then(shown => {
             if (shown) {
               this.emit("highlighter-shown");
             }
           });
     }
@@ -216,17 +216,17 @@ HighlightersOverlay.prototype = {
 
   /**
    * Is the current clicked node a grid display property value in the
    * rule-view.
    *
    * @param  {DOMNode} node
    * @return {Boolean}
    */
-  _isDisplayGridValue: function (node) {
+  _isRuleViewDisplayGrid: function (node) {
     return this.isRuleView && node.classList.contains("ruleview-grid");
   },
 
   /**
    * Hide the currently shown grid highlighter.
    */
   _hideGridHighlighter: function () {
     if (!this.gridHighlighterShown || !this.highlighters.CssGridHighlighter) {
@@ -284,32 +284,26 @@ HighlightersOverlay.prototype = {
     });
   },
 
   /**
    * Destroy this overlay instance, removing it from the view and destroying
    * all initialized highlighters.
    */
   destroy: function () {
-    this.removeFromView();
-
     for (let type in this.highlighters) {
       if (this.highlighters[type]) {
         this.highlighters[type].finalize();
         this.highlighters[type] = null;
       }
     }
 
+    this.inspector = null;
     this.highlighters = null;
-
+    this.highlighterUtils = null;
+    this.supportsHighlighters = null;
     this.gridHighlighterShown = null;
     this.hoveredHighlighterShown = null;
     this.selectorHighlighterShown = null;
-
-    this.highlighterUtils = null;
-    this.isRuleView = null;
-    this.view = null;
-
-    this._isDestroyed = true;
   }
 };
 
 module.exports = HighlightersOverlay;
--- a/devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-01.js
+++ b/devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-01.js
@@ -1,15 +1,16 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 /* Any copyright is dedicated to the Public Domain.
  http://creativecommons.org/publicdomain/zero/1.0/ */
 
 "use strict";
 
-// Test that the css transform highlighter is created only when asked
+// Test that the css transform highlighter is created only when asked and only one
+// instance exists across the inspector
 
 const TEST_URI = `
   <style type="text/css">
     body {
       transform: skew(16deg);
     }
   </style>
   Test the css transform highlighter
@@ -32,17 +33,13 @@ add_task(function* () {
   is(h, h2,
     "The same instance of highlighter is returned everytime in the rule-view");
 
   let onComputedViewReady = inspector.once("computed-view-refreshed");
   let cView = selectComputedView(inspector);
   yield onComputedViewReady;
   overlay = cView.highlighters;
 
-  ok(!overlay.highlighters[TYPE], "No highlighter exists in the computed-view");
-  h = yield overlay._getHighlighter(TYPE);
-  ok(overlay.highlighters[TYPE],
-    "The highlighter has been created in the computed-view");
-  is(h, overlay.highlighters[TYPE], "The right highlighter has been created");
-  h2 = yield overlay._getHighlighter(TYPE);
-  is(h, h2, "The same instance of highlighter is returned everytime " +
+  ok(overlay.highlighters[TYPE], "The highlighter exists in the computed-view");
+  let h3 = yield overlay._getHighlighter(TYPE);
+  is(h, h3, "The same instance of highlighter is returned everytime " +
     "in the computed-view");
 });
--- a/devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-02.js
+++ b/devtools/client/inspector/shared/test/browser_styleinspector_transform-highlighter-02.js
@@ -37,21 +37,26 @@ add_task(function* () {
   hs._onMouseMove({target: valueSpan});
   yield onHighlighterShown;
 
   let onComputedViewReady = inspector.once("computed-view-refreshed");
   let cView = selectComputedView(inspector);
   yield onComputedViewReady;
   hs = cView.highlighters;
 
-  ok(!hs.highlighters[TYPE], "No highlighter exists in the computed-view (1)");
+  info("Remove the created transform highlighter");
+  hs.highlighters[TYPE].finalize();
+  hs.highlighters[TYPE] = null;
 
   info("Faking a mousemove on a non-transform property");
   ({valueSpan} = getComputedViewProperty(cView, "color"));
   hs._onMouseMove({target: valueSpan});
-  ok(!hs.highlighters[TYPE], "No highlighter exists in the computed-view (2)");
+  ok(!hs.highlighters[TYPE], "No highlighter exists in the computed-view (3)");
 
   info("Faking a mousemove on a transform property");
   ({valueSpan} = getComputedViewProperty(cView, "transform"));
   onHighlighterShown = hs.once("highlighter-shown");
   hs._onMouseMove({target: valueSpan});
   yield onHighlighterShown;
+
+  ok(hs.highlighters[TYPE],
+    "The highlighter has been created in the computed-view");
 });