Bug 1494162 - Part 57: Set the node front before the components are initialized to unblock it from waiting until the markup is loaded before initializing. r=pbro
authorGabriel Luong <gabriel.luong@gmail.com>
Fri, 05 Oct 2018 12:44:39 -0400
changeset 495563 289fbd180e441c224b9a42b8987e9cf425ab3583
parent 495562 7c132c5ae38d40a3fdf6e5d4fa13065d6922cf4d
child 495564 2614ca0a8884a2995a59d07a59340d412450e4f2
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspbro
bugs1494162
milestone64.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 1494162 - Part 57: Set the node front before the components are initialized to unblock it from waiting until the markup is loaded before initializing. r=pbro Currently, we block the markup and all other sidebar panels from rendering their content until the markup iframe is loaded. So, we prevent this by setting the default node front at the beginning. We also move all the remaining event handlers to prevent unnecessary events since this is the first time the inspector is being constructed. In particular, we move the "new-node-front" event handler and manually call the actions that are performed in onNewSelection to prevent these updates from taking place until all the components are initialized.
devtools/client/inspector/inspector.js
devtools/client/inspector/markup/markup.js
--- a/devtools/client/inspector/inspector.js
+++ b/devtools/client/inspector/inspector.js
@@ -258,52 +258,53 @@ Inspector.prototype = {
    */
   _handleRejectionIfNotDestroyed: function(e) {
     if (!this._panelDestroyer) {
       console.error(e);
     }
   },
 
   _deferredOpen: async function() {
-    this.walker.on("new-root", this.onNewRoot);
-    this.toolbox.on("host-changed", this.onHostChanged);
-    this.selection.on("new-node-front", this.onNewSelection);
-    this.selection.on("detached-front", this.onDetached);
-
     this._initMarkup();
     this.isReady = false;
 
-    // Setup the splitter before the sidebar is displayed so,
-    // we don't miss any events.
+    // Set the node front so that the markup and sidebar panels will have the selected
+    // nodeFront ready when they're initialized.
+    if (this._defaultNode) {
+      this.selection.setNodeFront(this._defaultNode, { reason: "inspector-open" });
+    }
+
+    // Setup the splitter before the sidebar is displayed so, we don't miss any events.
     this.setupSplitter();
 
     // We can display right panel with: tab bar, markup view and breadbrumb. Right after
     // the splitter set the right and left panel sizes, in order to avoid resizing it
     // during load of the inspector.
     this.panelDoc.getElementById("inspector-main-content").style.visibility = "visible";
 
+    // Setup the sidebar panels.
     this.setupSidebar();
 
     await this.once("markuploaded");
     this.isReady = true;
 
-    // All the components are initialized. Let's select a node.
-    if (this._defaultNode) {
-      const onAllPanelsUpdated = this.once("inspector-updated");
-      this.selection.setNodeFront(this._defaultNode, { reason: "inspector-open" });
-      await onAllPanelsUpdated;
-      await this.markup.expandNode(this.selection.nodeFront);
-    }
-
-    // Take care of the remaining initialization and setup.
+    // All the components are initialized. Take care of the remaining initialization
+    // and setup.
     this.breadcrumbs = new HTMLBreadcrumbs(this);
     this.setupExtensionSidebars();
     this.setupSearchBox();
     await this.setupToolbar();
 
+    this.onNewSelection();
+
+    this.walker.on("new-root", this.onNewRoot);
+    this.toolbox.on("host-changed", this.onHostChanged);
+    this.selection.on("new-node-front", this.onNewSelection);
+    this.selection.on("detached-front", this.onDetached);
+
     if (this.target.isLocalTab) {
       this.target.on("thread-paused", this._updateDebuggerPausedWarning);
       this.target.on("thread-resumed", this._updateDebuggerPausedWarning);
       this.toolbox.on("select", this._updateDebuggerPausedWarning);
       this._updateDebuggerPausedWarning();
     }
 
     // Log the 3 pane inspector setting on inspector open. The question we want to answer
@@ -1244,16 +1245,28 @@ Inspector.prototype = {
     if (this._selectionCssSelector &&
         this._selectionCssSelector.url === this._target.url) {
       return this._selectionCssSelector.selector;
     }
     return null;
   },
 
   /**
+   * On any new selection made by the user, store the unique css selector
+   * of the selected node so it can be restored after reload of the same page
+   */
+  updateSelectionCssSelector() {
+    if (this.selection.isElementNode()) {
+      this.selection.nodeFront.getUniqueSelector().then(selector => {
+        this.selectionCssSelector = selector;
+      }, this._handleRejectionIfNotDestroyed);
+    }
+  },
+
+  /**
    * Can a new HTML element be inserted into the currently selected element?
    * @return {Boolean}
    */
   canAddHTMLChild: function() {
     const selection = this.selection;
 
     // Don't allow to insert an element into these elements. This should only
     // contain elements where walker.insertAdjacentHTML has no effect.
@@ -1263,16 +1276,28 @@ Inspector.prototype = {
            selection.isElementNode() &&
            !selection.isPseudoElementNode() &&
            !selection.isAnonymousNode() &&
            !invalidTagNames.includes(
             selection.nodeFront.nodeName.toLowerCase());
   },
 
   /**
+   * Update the state of the add button in the toolbar depending on the current selection.
+   */
+  updateAddElementButton() {
+    const btn = this.panelDoc.getElementById("inspector-element-add-button");
+    if (this.canAddHTMLChild()) {
+      btn.removeAttribute("disabled");
+    } else {
+      btn.setAttribute("disabled", "true");
+    }
+  },
+
+  /**
    * Handler for the "host-changed" event from the toolbox. Resets the inspector
    * sidebar sizes when the toolbox host type changes.
    */
   async onHostChanged() {
     // Eagerly call our resize handling code to process the fact that we
     // switched hosts. If we don't do this, we'll wait for resize events + 200ms
     // to have passed, which causes the old layout to noticeably show up in the
     // new host, followed by the updated one.
@@ -1289,41 +1314,23 @@ Inspector.prototype = {
   /**
    * When a new node is selected.
    */
   onNewSelection: function(value, reason) {
     if (reason === "selection-destroy") {
       return;
     }
 
-    // Wait for all the known tools to finish updating and then let the
-    // client know.
-    const selection = this.selection.nodeFront;
-
-    // Update the state of the add button in the toolbar depending on the
-    // current selection.
-    const btn = this.panelDoc.querySelector("#inspector-element-add-button");
-    if (this.canAddHTMLChild()) {
-      btn.removeAttribute("disabled");
-    } else {
-      btn.setAttribute("disabled", "true");
-    }
-
-    // On any new selection made by the user, store the unique css selector
-    // of the selected node so it can be restored after reload of the same page
-    if (this.selection.isElementNode()) {
-      selection.getUniqueSelector().then(selector => {
-        this.selectionCssSelector = selector;
-      }, this._handleRejectionIfNotDestroyed);
-    }
+    this.updateAddElementButton();
+    this.updateSelectionCssSelector();
 
     const selfUpdate = this.updating("inspector-panel");
     executeSoon(() => {
       try {
-        selfUpdate(selection);
+        selfUpdate(this.selection.nodeFront);
       } catch (ex) {
         console.error(ex);
       }
     });
   },
 
   /**
    * Delay the "inspector-updated" notification while a tool
@@ -1951,21 +1958,18 @@ Inspector.prototype = {
     this._markupFrame.addEventListener("load", this._onMarkupFrameLoad, true);
     this._markupFrame.setAttribute("src", "markup/markup.xhtml");
     this._markupFrame.setAttribute("aria-label",
       INSPECTOR_L10N.getStr("inspector.panelLabel.markupView"));
   },
 
   _onMarkupFrameLoad: function() {
     this._markupFrame.removeEventListener("load", this._onMarkupFrameLoad, true);
-
     this._markupFrame.contentWindow.focus();
-
     this.markup = new MarkupView(this, this._markupFrame, this._toolbox.win);
-
     this._markupBox.style.visibility = "visible";
     this.emit("markuploaded");
   },
 
   _destroyMarkup: function() {
     let destroyPromise;
 
     if (this._markupFrame) {
--- a/devtools/client/inspector/markup/markup.js
+++ b/devtools/client/inspector/markup/markup.js
@@ -129,16 +129,17 @@ function MarkupView(inspector, frame, co
     this._initTooltips();
   } else {
     this._elt.addEventListener("mousemove", () => {
       this._initTooltips();
     }, { once: true });
   }
 
   this._onNewSelection();
+  this.expandNode(this.inspector.selection.nodeFront);
 
   this._prefObserver = new PrefObserver("devtools.markup");
   this._prefObserver.on(ATTR_COLLAPSE_ENABLED_PREF, this._onCollapseAttributesPrefChange);
   this._prefObserver.on(ATTR_COLLAPSE_LENGTH_PREF, this._onCollapseAttributesPrefChange);
 
   this._initShortcuts();
 }