Bug 1316700 - make developer-toolbar.js eslint-clean; r=jryans
authorTom Tromey <tom@tromey.com>
Thu, 10 Nov 2016 14:07:02 -0700
changeset 367288 a9d5f467f78d17f06bd56f581c1ec9f87bc0f652
parent 367287 5b4f52f937d2f06030cca5848d97598653495abd
child 367289 8842715529605c023207c667dd82b40b43632078
push id1369
push userjlorenzo@mozilla.com
push dateMon, 27 Feb 2017 14:59:41 +0000
treeherdermozilla-release@d75a1dba431f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjryans
bugs1316700
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1316700 - make developer-toolbar.js eslint-clean; r=jryans MozReview-Commit-ID: FgvsY8PTpCj
.eslintignore
devtools/client/shared/developer-toolbar.js
--- a/.eslintignore
+++ b/.eslintignore
@@ -90,17 +90,16 @@ devtools/client/netmonitor/test/**
 devtools/client/netmonitor/har/test/**
 devtools/client/projecteditor/**
 devtools/client/promisedebugger/**
 devtools/client/responsivedesign/**
 devtools/client/scratchpad/**
 devtools/client/shadereditor/**
 devtools/client/shared/*.jsm
 devtools/client/shared/webgl-utils.js
-devtools/client/shared/developer-toolbar.js
 devtools/client/shared/components/test/**
 devtools/client/shared/redux/middleware/test/**
 devtools/client/shared/test/**
 !devtools/client/shared/test/test-actor-registry.js
 devtools/client/shared/widgets/*.jsm
 devtools/client/sourceeditor/test/*.js
 devtools/client/webaudioeditor/**
 devtools/client/webconsole/**
--- a/devtools/client/shared/developer-toolbar.js
+++ b/devtools/client/shared/developer-toolbar.js
@@ -1,26 +1,26 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { Cc, Ci, Cu } = require("chrome");
+const { Ci } = require("chrome");
 const promise = require("promise");
 const defer = require("devtools/shared/defer");
 const Services = require("Services");
 const { TargetFactory } = require("devtools/client/framework/target");
 const Telemetry = require("devtools/client/shared/telemetry");
 const {ViewHelpers} = require("devtools/client/shared/widgets/view-helpers");
 const {LocalizationHelper} = require("devtools/shared/l10n");
 const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
+const {Task} = require("devtools/shared/task");
 
 const NS_XHTML = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const { PluralForm } = require("devtools/shared/plural-form");
 
 loader.lazyGetter(this, "prefBranch", function () {
   return Services.prefs.getBranch(null)
                     .QueryInterface(Ci.nsIPrefBranch2);
 });
 
@@ -39,17 +39,17 @@ var CommandUtils = {
   /**
    * Utility to ensure that things are loaded in the correct order
    */
   createRequisition: function (target, options) {
     if (!gcliInit) {
       return promise.reject("Unable to load gcli");
     }
     return gcliInit.getSystem(target).then(system => {
-      var Requisition = require("gcli/cli").Requisition;
+      let Requisition = require("gcli/cli").Requisition;
       return new Requisition(system, options);
     });
   },
 
   /**
    * Destroy the remote side of the requisition as well as the local side
    */
   destroyRequisition: function (requisition, target) {
@@ -85,28 +85,26 @@ var CommandUtils = {
           throw new Error("No command '" + typed + "'");
         }
 
         if (command.buttonId != null) {
           button.id = command.buttonId;
           if (command.buttonClass != null) {
             button.className = command.buttonClass;
           }
-        }
-        else {
+        } else {
           button.setAttribute("text-as-image", "true");
           button.setAttribute("label", command.name);
         }
 
         button.classList.add("devtools-button");
 
         if (command.tooltipText != null) {
           button.setAttribute("title", command.tooltipText);
-        }
-        else if (command.description != null) {
+        } else if (command.description != null) {
           button.setAttribute("title", command.description);
         }
 
         button.addEventListener("click",
           requisition.updateExec.bind(requisition, typed));
 
         button.addEventListener("keypress", (event) => {
           if (ViewHelpers.isSpaceOrReturn(event)) {
@@ -123,44 +121,41 @@ var CommandUtils = {
           /**
            * The onChange event should be called with an event object that
            * contains a target property which specifies which target the event
            * applies to. For legacy reasons the event object can also contain
            * a tab property.
            */
           onChange = (eventName, ev) => {
             if (ev.target == target || ev.tab == target.tab) {
-
               let updateChecked = (checked) => {
                 if (checked) {
                   button.setAttribute("checked", true);
-                }
-                else if (button.hasAttribute("checked")) {
+                } else if (button.hasAttribute("checked")) {
                   button.removeAttribute("checked");
                 }
               };
 
               // isChecked would normally be synchronous. An annoying quirk
               // of the 'csscoverage toggle' command forces us to accept a
               // promise here, but doing Promise.resolve(reply).then(...) here
               // makes this async for everyone, which breaks some tests so we
               // treat non-promise replies separately to keep then synchronous.
               let reply = command.state.isChecked(target);
               if (typeof reply.then == "function") {
                 reply.then(updateChecked, console.error);
-              }
-              else {
+              } else {
                 updateChecked(reply);
               }
             }
           };
 
           command.state.onChange(target, onChange);
           onChange("", { target: target });
-        };
+        }
         document.defaultView.addEventListener("unload", function (event) {
           if (onChange && command.state.offChange) {
             command.state.offChange(target, onChange);
           }
           button.remove();
           button = null;
         }, { once: true });
 
@@ -197,22 +192,24 @@ var CommandUtils = {
         return this.target.tab.ownerDocument.defaultView;
       },
 
       get chromeDocument() {
         return this.target.tab.ownerDocument.defaultView.document;
       },
 
       get window() {
-        // throw new Error("environment.window is not available in runAt:client commands");
+        // throw new
+        //    Error("environment.window is not available in runAt:client commands");
         return this.chromeWindow.gBrowser.contentWindowAsCPOW;
       },
 
       get document() {
-        // throw new Error("environment.document is not available in runAt:client commands");
+        // throw new
+        //    Error("environment.document is not available in runAt:client commands");
         return this.chromeWindow.gBrowser.contentDocumentAsCPOW;
       }
     };
   },
 };
 
 exports.CommandUtils = CommandUtils;
 
@@ -228,25 +225,25 @@ loader.lazyGetter(this, "isLinux", funct
 });
 loader.lazyGetter(this, "isMac", function () {
   return Services.appinfo.OS == "Darwin";
 });
 
 /**
  * A component to manage the global developer toolbar, which contains a GCLI
  * and buttons for various developer tools.
- * @param aChromeWindow The browser window to which this toolbar is attached
+ * @param chromeWindow The browser window to which this toolbar is attached
  */
-function DeveloperToolbar(aChromeWindow)
-{
-  this._chromeWindow = aChromeWindow;
+function DeveloperToolbar(chromeWindow) {
+  this._chromeWindow = chromeWindow;
 
-  this.target = null; // Will be setup when show() is called
+  // Will be setup when show() is called
+  this.target = null;
 
-  this._doc = aChromeWindow.document;
+  this._doc = chromeWindow.document;
 
   this._telemetry = new Telemetry();
   this._errorsCount = {};
   this._warningsCount = {};
   this._errorListeners = {};
 
   this._onToolboxReady = this._onToolboxReady.bind(this);
   this._onToolboxDestroyed = this._onToolboxDestroyed.bind(this);
@@ -352,62 +349,61 @@ DeveloperToolbar.prototype.createToolbar
     toolbar.appendChild(toolboxBtn);
     toolbar.appendChild(close);
   }
 
   this._element = toolbar;
   let bottomBox = this._doc.getElementById("browser-bottombox");
   if (bottomBox) {
     bottomBox.appendChild(this._element);
-  } else { // SeaMonkey does not have a "browser-bottombox".
+  } else {
+    // SeaMonkey does not have a "browser-bottombox".
     let statusBar = this._doc.getElementById("status-bar");
-    if (statusBar)
+    if (statusBar) {
       statusBar.parentNode.insertBefore(this._element, statusBar);
+    }
   }
 };
 
 /**
  * Called from browser.xul in response to menu-click or keyboard shortcut to
  * toggle the toolbar
  */
 DeveloperToolbar.prototype.toggle = function () {
   if (this.visible) {
     return this.hide().catch(console.error);
-  } else {
-    return this.show(true).catch(console.error);
   }
+  return this.show(true).catch(console.error);
 };
 
 /**
  * Called from browser.xul in response to menu-click or keyboard shortcut to
  * toggle the toolbar
  */
 DeveloperToolbar.prototype.focus = function () {
   if (this.visible) {
     this._input.focus();
     return promise.resolve();
-  } else {
-    return this.show(true);
   }
+  return this.show(true);
 };
 
 /**
  * Called from browser.xul in response to menu-click or keyboard shortcut to
  * toggle the toolbar
  */
 DeveloperToolbar.prototype.focusToggle = function () {
   if (this.visible) {
     // If we have focus then the active element is the HTML input contained
     // inside the xul input element
     let active = this._chromeWindow.document.activeElement;
     let position = this._input.compareDocumentPosition(active);
     if (position & nodeConstants.DOCUMENT_POSITION_CONTAINED_BY) {
       this.hide();
-    }
-    else {
+    } else {
       this._input.focus();
     }
   } else {
     this.show(true);
   }
 };
 
 /**
@@ -421,155 +417,157 @@ DeveloperToolbar.introShownThisSession =
 /**
  * Show the developer toolbar
  */
 DeveloperToolbar.prototype.show = function (focus) {
   if (this._showPromise != null) {
     return this._showPromise;
   }
 
-  // hide() is async, so ensure we don't need to wait for hide() to finish
-  var waitPromise = this._hidePromise || promise.resolve();
+  this._showPromise = Task.spawn((function* () {
+    // hide() is async, so ensure we don't need to wait for hide() to
+    // finish.  We unconditionally yield here, even if _hidePromise is
+    // null, so that the spawn call returns a promise before starting
+    // to do any real work.
+    yield this._hidePromise;
 
-  this._showPromise = waitPromise.then(() => {
     this.createToolbar();
 
     Services.prefs.setBoolPref("devtools.toolbar.visible", true);
 
     this._telemetry.toolOpened("developertoolbar");
 
     this._notify(NOTIFICATIONS.LOAD);
 
     this._input = this._doc.querySelector(".gclitoolbar-input-node");
 
     // Initializing GCLI can only be done when we've got content windows to
     // write to, so this needs to be done asynchronously.
     let panelPromises = [
       TooltipPanel.create(this),
       OutputPanel.create(this)
     ];
-    return promise.all(panelPromises).then(panels => {
-      [ this.tooltipPanel, this.outputPanel ] = panels;
+    let panels = yield promise.all(panelPromises);
 
-      this._doc.getElementById("menu_devToolbar").setAttribute("checked", "true");
+    [ this.tooltipPanel, this.outputPanel ] = panels;
+
+    this._doc.getElementById("menu_devToolbar").setAttribute("checked", "true");
 
-      this.target = TargetFactory.forTab(this._chromeWindow.gBrowser.selectedTab);
-      const options = {
-        environment: CommandUtils.createEnvironment(this, "target"),
-        document: this.outputPanel.document,
-      };
-      return CommandUtils.createRequisition(this.target, options).then(requisition => {
-        this.requisition = requisition;
+    this.target = TargetFactory.forTab(this._chromeWindow.gBrowser.selectedTab);
+    const options = {
+      environment: CommandUtils.createEnvironment(this, "target"),
+      document: this.outputPanel.document,
+    };
+    let requisition = yield CommandUtils.createRequisition(this.target, options);
+    this.requisition = requisition;
 
-        // The <textbox> `value` may still be undefined on the XUL binding if
-        // we fetch it early
-        let value = this._input.value || "";
-        return this.requisition.update(value).then(() => {
-          const Inputter = require("gcli/mozui/inputter").Inputter;
-          const Completer = require("gcli/mozui/completer").Completer;
-          const Tooltip = require("gcli/mozui/tooltip").Tooltip;
-          const FocusManager = require("gcli/ui/focus").FocusManager;
+    // The <textbox> `value` may still be undefined on the XUL binding if
+    // we fetch it early
+    let value = this._input.value || "";
+    yield this.requisition.update(value);
 
-          this.onOutput = this.requisition.commandOutputManager.onOutput;
+    const Inputter = require("gcli/mozui/inputter").Inputter;
+    const Completer = require("gcli/mozui/completer").Completer;
+    const Tooltip = require("gcli/mozui/tooltip").Tooltip;
+    const FocusManager = require("gcli/ui/focus").FocusManager;
 
-          this.focusManager = new FocusManager(this._doc, requisition.system.settings);
+    this.onOutput = this.requisition.commandOutputManager.onOutput;
+
+    this.focusManager = new FocusManager(this._doc, requisition.system.settings);
 
-          this.inputter = new Inputter({
-            requisition: this.requisition,
-            focusManager: this.focusManager,
-            element: this._input,
-          });
+    this.inputter = new Inputter({
+      requisition: this.requisition,
+      focusManager: this.focusManager,
+      element: this._input,
+    });
 
-          this.completer = new Completer({
-            requisition: this.requisition,
-            inputter: this.inputter,
-            backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
-            element: this._doc.querySelector(".gclitoolbar-complete-node"),
-          });
+    this.completer = new Completer({
+      requisition: this.requisition,
+      inputter: this.inputter,
+      backgroundElement: this._doc.querySelector(".gclitoolbar-stack-node"),
+      element: this._doc.querySelector(".gclitoolbar-complete-node"),
+    });
 
-          this.tooltip = new Tooltip({
-            requisition: this.requisition,
-            focusManager: this.focusManager,
-            inputter: this.inputter,
-            element: this.tooltipPanel.hintElement,
-          });
+    this.tooltip = new Tooltip({
+      requisition: this.requisition,
+      focusManager: this.focusManager,
+      inputter: this.inputter,
+      element: this.tooltipPanel.hintElement,
+    });
 
-          this.inputter.tooltip = this.tooltip;
-
-          this.focusManager.addMonitoredElement(this.outputPanel._frame);
-          this.focusManager.addMonitoredElement(this._element);
+    this.inputter.tooltip = this.tooltip;
 
-          this.focusManager.onVisibilityChange.add(this.outputPanel._visibilityChanged,
-                                                   this.outputPanel);
-          this.focusManager.onVisibilityChange.add(this.tooltipPanel._visibilityChanged,
-                                                   this.tooltipPanel);
-          this.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
+    this.focusManager.addMonitoredElement(this.outputPanel._frame);
+    this.focusManager.addMonitoredElement(this._element);
+
+    this.focusManager.onVisibilityChange.add(this.outputPanel._visibilityChanged,
+                                             this.outputPanel);
+    this.focusManager.onVisibilityChange.add(this.tooltipPanel._visibilityChanged,
+                                             this.tooltipPanel);
+    this.onOutput.add(this.outputPanel._outputChanged, this.outputPanel);
 
-          let tabbrowser = this._chromeWindow.gBrowser;
-          tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
-          tabbrowser.tabContainer.addEventListener("TabClose", this, false);
-          tabbrowser.addEventListener("load", this, true);
-          tabbrowser.addEventListener("beforeunload", this, true);
+    let tabbrowser = this._chromeWindow.gBrowser;
+    tabbrowser.tabContainer.addEventListener("TabSelect", this, false);
+    tabbrowser.tabContainer.addEventListener("TabClose", this, false);
+    tabbrowser.addEventListener("load", this, true);
+    tabbrowser.addEventListener("beforeunload", this, true);
 
-          gDevTools.on("toolbox-ready", this._onToolboxReady);
-          gDevTools.on("toolbox-destroyed", this._onToolboxDestroyed);
+    gDevTools.on("toolbox-ready", this._onToolboxReady);
+    gDevTools.on("toolbox-destroyed", this._onToolboxDestroyed);
 
-          this._initErrorsCount(tabbrowser.selectedTab);
+    this._initErrorsCount(tabbrowser.selectedTab);
 
-          this._element.hidden = false;
+    this._element.hidden = false;
 
-          if (focus) {
-            // If the toolbar was just inserted, the <textbox> may still have
-            // its binding in process of being applied and not be focusable yet
-            let waitForBinding = () => {
-              // Bail out if the toolbar has been destroyed in the meantime
-              if (!this._input) {
-                return;
-              }
-              // mInputField is a xbl field of <xul:textbox>
-              if (typeof this._input.mInputField != "undefined") {
-                this._input.focus();
-                this._notify(NOTIFICATIONS.SHOW);
-              } else {
-                this._input.ownerDocument.defaultView.setTimeout(waitForBinding, 50);
-              }
-            };
-            waitForBinding();
-          } else {
-            this._notify(NOTIFICATIONS.SHOW);
-          }
+    if (focus) {
+      // If the toolbar was just inserted, the <textbox> may still have
+      // its binding in process of being applied and not be focusable yet
+      let waitForBinding = () => {
+        // Bail out if the toolbar has been destroyed in the meantime
+        if (!this._input) {
+          return;
+        }
+        // mInputField is a xbl field of <xul:textbox>
+        if (typeof this._input.mInputField != "undefined") {
+          this._input.focus();
+          this._notify(NOTIFICATIONS.SHOW);
+        } else {
+          this._input.ownerDocument.defaultView.setTimeout(waitForBinding, 50);
+        }
+      };
+      waitForBinding();
+    } else {
+      this._notify(NOTIFICATIONS.SHOW);
+    }
 
-          if (!DeveloperToolbar.introShownThisSession) {
-            let intro = require("gcli/ui/intro");
-            intro.maybeShowIntro(this.requisition.commandOutputManager,
-                                 this.requisition.conversionContext,
-                                 this.outputPanel);
-            DeveloperToolbar.introShownThisSession = true;
-          }
+    if (!DeveloperToolbar.introShownThisSession) {
+      let intro = require("gcli/ui/intro");
+      intro.maybeShowIntro(this.requisition.commandOutputManager,
+                           this.requisition.conversionContext,
+                           this.outputPanel);
+      DeveloperToolbar.introShownThisSession = true;
+    }
 
-          this._showPromise = null;
-        });
-      });
-    });
-  });
+    this._showPromise = null;
+  }).bind(this));
 
   return this._showPromise;
 };
 
 /**
  * Hide the developer toolbar.
  */
 DeveloperToolbar.prototype.hide = function () {
   // If we're already in the process of hiding, just use the other promise
   if (this._hidePromise != null) {
     return this._hidePromise;
   }
 
   // show() is async, so ensure we don't need to wait for show() to finish
-  var waitPromise = this._showPromise || promise.resolve();
+  let waitPromise = this._showPromise || promise.resolve();
 
   this._hidePromise = waitPromise.then(() => {
     this._element.hidden = true;
 
     Services.prefs.setBoolPref("devtools.toolbar.visible", false);
 
     this._doc.getElementById("menu_devToolbar").setAttribute("checked", "false");
     this.destroy();
@@ -637,17 +635,18 @@ DeveloperToolbar.prototype._stopErrorsCo
   this._updateErrorsCount();
 };
 
 /**
  * Hide the developer toolbar
  */
 DeveloperToolbar.prototype.destroy = function () {
   if (this._input == null) {
-    return; // Already destroyed
+    // Already destroyed
+    return;
   }
 
   let tabbrowser = this._chromeWindow.gBrowser;
   tabbrowser.tabContainer.removeEventListener("TabSelect", this, false);
   tabbrowser.tabContainer.removeEventListener("TabClose", this, false);
   tabbrowser.removeEventListener("load", this, true);
   tabbrowser.removeEventListener("beforeunload", this, true);
 
@@ -716,21 +715,19 @@ DeveloperToolbar.prototype.handleEvent =
       });
 
       if (ev.type == "TabSelect") {
         let toolboxOpen = gDevToolsBrowser.hasToolboxOpened(this._chromeWindow);
         this._errorCounterButton.setAttribute("checked", toolboxOpen);
         this._initErrorsCount(ev.target);
       }
     }
-  }
-  else if (ev.type == "TabClose") {
+  } else if (ev.type == "TabClose") {
     this._stopErrorsCount(ev.target);
-  }
-  else if (ev.type == "beforeunload") {
+  } else if (ev.type == "beforeunload") {
     this._onPageBeforeUnload(ev);
   }
 };
 
 /**
  * Update toolbox toggle button when toolbox goes on and off
  */
 DeveloperToolbar.prototype._onToolboxReady = function () {
@@ -863,17 +860,17 @@ function OutputPanel() {
  * called on Windows and OSX (bug 692348) ... this prevents the panel from
  * appearing the first time it is shown. Setting the panel's height to 1px
  * before calling openPopup works around this issue as we resize it ourselves
  * anyway.
  *
  * @param devtoolbar The parent DeveloperToolbar object
  */
 OutputPanel.create = function (devtoolbar) {
-  var outputPanel = Object.create(OutputPanel.prototype);
+  let outputPanel = Object.create(OutputPanel.prototype);
   return outputPanel._init(devtoolbar);
 };
 
 /**
  * @private See OutputPanel.create
  */
 OutputPanel.prototype._init = function (devtoolbar) {
   this._devtoolbar = devtoolbar;
@@ -1061,18 +1058,17 @@ OutputPanel.prototype._outputChanged = f
   }
 
   this.remove();
 
   this.displayedOutput = ev.output;
 
   if (this.displayedOutput.completed) {
     this._update();
-  }
-  else {
+  } else {
     this.displayedOutput.promise.then(this._update, this._update)
                                 .then(null, console.error);
   }
 };
 
 /**
  * Called when displayed Output says it's changed or from outputChanged, which
  * happens when there is a new displayed Output.
@@ -1094,18 +1090,18 @@ OutputPanel.prototype._update = function
       if (node == null) {
         return;
       }
 
       while (this._div.hasChildNodes()) {
         this._div.removeChild(this._div.firstChild);
       }
 
-      var links = node.querySelectorAll("*[href]");
-      for (var i = 0; i < links.length; i++) {
+      let links = node.querySelectorAll("*[href]");
+      for (let i = 0; i < links.length; i++) {
         links[i].setAttribute("target", "_blank");
       }
 
       this._div.appendChild(node);
       this.show();
     });
   }
 };
@@ -1183,27 +1179,26 @@ function TooltipPanel() {
  * called on Windows and OSX (bug 692348) ... this prevents the panel from
  * appearing the first time it is shown. Setting the panel's height to 1px
  * before calling openPopup works around this issue as we resize it ourselves
  * anyway.
  *
  * @param devtoolbar The parent DeveloperToolbar object
  */
 TooltipPanel.create = function (devtoolbar) {
-  var tooltipPanel = Object.create(TooltipPanel.prototype);
+  let tooltipPanel = Object.create(TooltipPanel.prototype);
   return tooltipPanel._init(devtoolbar);
 };
 
 /**
  * @private See TooltipPanel.create
  */
 TooltipPanel.prototype._init = function (devtoolbar) {
   let deferred = defer();
 
-  let chromeDocument = devtoolbar._doc;
   this._devtoolbar = devtoolbar;
   this._input = devtoolbar._doc.querySelector(".gclitoolbar-input-node");
   this._toolbar = devtoolbar._doc.querySelector("#developer-toolbar");
   this._dimensions = { start: 0, end: 0 };
 
   /*
   <tooltip|panel id="gcli-tooltip"
          type="arrow"