Bug 1316700 - make developer-toolbar.js eslint-clean; r?jryans draft
authorTom Tromey <tom@tromey.com>
Thu, 10 Nov 2016 14:07:02 -0700
changeset 437714 f7ac4c5bc0fe914bac73314355b18f90b3c6df71
parent 437713 3f1dcd04bc47823809e7776ca852977c3ed2881d
child 536710 e4a4c9b23bb082fa4d52cbe8433738915455a098
push id35494
push userbmo:ttromey@mozilla.com
push dateFri, 11 Nov 2016 14:13:03 +0000
reviewersjryans
bugs1316700
milestone52.0a1
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"