Bug 1392081 - Use a document fragment to populate toolbar and menu Places views. r=Gijs
☠☠ backed out by aae17c1a570c ☠ ☠
authorMarco Bonardo <mbonardo@mozilla.com>
Fri, 25 Aug 2017 15:20:00 +0200
changeset 428515 2b76c3b079d9cbfb89a165fec3c5cf2796bbfe06
parent 428514 78cce071b69e26eb55df4da1f66409b3a2226d3b
child 428516 ecd61b92f9b3b033a253fd0a931161526dd8d085
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1392081
milestone57.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 1392081 - Use a document fragment to populate toolbar and menu Places views. r=Gijs MozReview-Commit-ID: 1Q4U3xXfF4Y
browser/components/places/content/browserPlacesViews.js
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -278,21 +278,22 @@ PlacesViewBase.prototype = {
       return;
     }
 
     this._cleanPopup(aPopup);
 
     let cc = resultNode.childCount;
     if (cc > 0) {
       this._setEmptyPopupStatus(aPopup, false);
-
+      let fragment = document.createDocumentFragment();
       for (let i = 0; i < cc; ++i) {
         let child = resultNode.getChild(i);
-        this._insertNewItemToPopup(child, aPopup, null);
+        this._insertNewItemToPopup(child, fragment);
       }
+      aPopup.insertBefore(fragment, aPopup._endMarker);
     } else {
       this._setEmptyPopupStatus(aPopup, true);
     }
     aPopup._built = true;
   },
 
   _removeChild: function PVB__removeChild(aChild) {
     // If document.popupNode pointed to this child, null it out,
@@ -399,26 +400,25 @@ PlacesViewBase.prototype = {
     element._placesNode = aPlacesNode;
     if (!this._domNodes.has(aPlacesNode))
       this._domNodes.set(aPlacesNode, element);
 
     return element;
   },
 
   _insertNewItemToPopup:
-  function PVB__insertNewItemToPopup(aNewChild, aPopup, aBefore) {
+  function PVB__insertNewItemToPopup(aNewChild, aInsertionNode, aBefore = null) {
     let element = this._createDOMNodeForPlacesNode(aNewChild);
-    let before = aBefore || aPopup._endMarker;
 
     if (element.localName == "menuitem" || element.localName == "menu") {
       if (typeof this.options.extraClasses.entry == "string")
         element.classList.add(this.options.extraClasses.entry);
     }
 
-    aPopup.insertBefore(element, before);
+    aInsertionNode.insertBefore(element, aBefore);
     return element;
   },
 
   _setLivemarkSiteURIMenuItem:
   function PVB__setLivemarkSiteURIMenuItem(aPopup) {
     let livemarkInfo = this.controller.getCachedLivemarkInfo(aPopup._placesNode);
     let siteUrl = livemarkInfo && livemarkInfo.siteURI ?
                   livemarkInfo.siteURI.spec : null;
@@ -630,17 +630,17 @@ PlacesViewBase.prototype = {
   function PVB_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
     let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
     if (!parentElt._built)
       return;
 
     let index = Array.prototype.indexOf.call(parentElt.childNodes, parentElt._startMarker) +
                 aIndex + 1;
     this._insertNewItemToPopup(aPlacesNode, parentElt,
-                               parentElt.childNodes[index]);
+                               parentElt.childNodes[index] || parentElt._endMarker);
     this._setEmptyPopupStatus(parentElt, false);
   },
 
   nodeMoved:
   function PBV_nodeMoved(aPlacesNode,
                          aOldParentPlacesNode, aOldIndex,
                          aNewParentPlacesNode, aNewIndex) {
     // Note: the current implementation of moveItem does not actually
@@ -1031,31 +1031,33 @@ PlacesToolbar.prototype = {
     if (this._overFolder.elt)
       this._clearOverFolder();
 
     this._openedMenuButton = null;
     while (this._rootElt.hasChildNodes()) {
       this._rootElt.firstChild.remove();
     }
 
+    let fragment = document.createDocumentFragment();
     let cc = this._resultNode.childCount;
     for (let i = 0; i < cc; ++i) {
-      this._insertNewItem(this._resultNode.getChild(i), null);
+      this._insertNewItem(this._resultNode.getChild(i), fragment);
     }
+    this._rootElt.appendChild(fragment);
 
     if (this._chevronPopup.hasAttribute("type")) {
       // Chevron has already been initialized, but since we are forcing
       // a rebuild of the toolbar, it has to be rebuilt.
       // Otherwise, it will be initialized when the toolbar overflows.
       this._chevronPopup.place = this.place;
     }
   },
 
   _insertNewItem:
-  function PT__insertNewItem(aChild, aBefore) {
+  function PT__insertNewItem(aChild, aInsertionNode, aBefore = null) {
     this._domNodes.delete(aChild);
 
     let type = aChild.type;
     let button;
     if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
       button = document.createElement("toolbarseparator");
     } else {
       button = document.createElement("toolbarbutton");
@@ -1094,19 +1096,19 @@ PlacesToolbar.prototype = {
       }
     }
 
     button._placesNode = aChild;
     if (!this._domNodes.has(aChild))
       this._domNodes.set(aChild, button);
 
     if (aBefore)
-      this._rootElt.insertBefore(button, aBefore);
+      aInsertionNode.insertBefore(button, aBefore);
     else
-      this._rootElt.appendChild(button);
+      aInsertionNode.appendChild(button);
   },
 
   _updateChevronPopupNodesVisibility:
   function PT__updateChevronPopupNodesVisibility() {
     for (let i = 0, node = this._chevronPopup._startMarker.nextSibling;
          node != this._chevronPopup._endMarker;
          i++, node = node.nextSibling) {
       node.hidden = this._rootElt.childNodes[i].style.visibility != "hidden";
@@ -1248,17 +1250,17 @@ PlacesToolbar.prototype = {
       this._updateChevronPopupNodesVisibility();
   },
 
   nodeInserted:
   function PT_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
     let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
     if (parentElt == this._rootElt) {
       let children = this._rootElt.childNodes;
-      this._insertNewItem(aPlacesNode,
+      this._insertNewItem(aPlacesNode, this._rootElt,
         aIndex < children.length ? children[aIndex] : null);
       this.updateChevron();
       return;
     }
 
     PlacesViewBase.prototype.nodeInserted.apply(this, arguments);
   },
 
@@ -1872,17 +1874,17 @@ PlacesPanelMenuView.prototype = {
     return PlacesViewBase.prototype.QueryInterface.apply(this, arguments);
   },
 
   uninit: function PAMV_uninit() {
     PlacesViewBase.prototype.uninit.apply(this, arguments);
   },
 
   _insertNewItem:
-  function PAMV__insertNewItem(aChild, aBefore) {
+  function PAMV__insertNewItem(aChild, aInsertionNode, aBefore = null) {
     this._domNodes.delete(aChild);
 
     let type = aChild.type;
     let button;
     if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR) {
       button = document.createElement("toolbarseparator");
       button.setAttribute("class", "small-separator");
     } else {
@@ -1914,27 +1916,27 @@ PlacesPanelMenuView.prototype = {
                             PlacesUIUtils.guessUrlSchemeForUI(aChild.uri));
       }
     }
 
     button._placesNode = aChild;
     if (!this._domNodes.has(aChild))
       this._domNodes.set(aChild, button);
 
-    this._rootElt.insertBefore(button, aBefore);
+    aInsertionNode.insertBefore(button, aBefore);
   },
 
   nodeInserted:
   function PAMV_nodeInserted(aParentPlacesNode, aPlacesNode, aIndex) {
     let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
     if (parentElt != this._rootElt)
       return;
 
     let children = this._rootElt.childNodes;
-    this._insertNewItem(aPlacesNode,
+    this._insertNewItem(aPlacesNode, this._rootElt,
       aIndex < children.length ? children[aIndex] : null);
   },
 
   nodeRemoved:
   function PAMV_nodeRemoved(aParentPlacesNode, aPlacesNode, aIndex) {
     let parentElt = this._getDOMNodeForPlacesNode(aParentPlacesNode);
     if (parentElt != this._rootElt)
       return;
@@ -1993,19 +1995,21 @@ PlacesPanelMenuView.prototype = {
     if (elt != this._rootElt)
       return;
 
     // Container is the toolbar itself.
     while (this._rootElt.hasChildNodes()) {
       this._rootElt.firstChild.remove();
     }
 
+    let fragment = document.createDocumentFragment();
     for (let i = 0; i < this._resultNode.childCount; ++i) {
-      this._insertNewItem(this._resultNode.getChild(i), null);
+      this._insertNewItem(this._resultNode.getChild(i), fragment);
     }
+    this._rootElt.appendChild(fragment);
   }
 };
 
 this.PlacesPanelview = class extends PlacesViewBase {
   constructor(container, panelview, place, options = {}) {
     options.rootElt = container;
     options.viewElt = panelview;
     super(place, options);