Bug 1497975 - Prevent layouts during parse of browser.xhtml;r=Gijs,emilio
authorBrian Grinstead <bgrinstead@mozilla.com>
Thu, 11 Oct 2018 18:10:33 +0000
changeset 489101 bb7c6b3e49c79adb61ab85785e408b0e012b63bf
parent 489100 7a97fe41a34fabed6beeb3db2fc0a2c61623eeae
child 489102 0ff0cb5364283cb55240c42e476ca1e5458ec567
push id246
push userfmarier@mozilla.com
push dateSat, 13 Oct 2018 00:15:40 +0000
reviewersGijs, emilio
bugs1497975
milestone64.0a1
Bug 1497975 - Prevent layouts during parse of browser.xhtml;r=Gijs,emilio By hiding the documentElement with display:none and then waiting to show it until readystatechange, we can avoid inadvertently constructing XBL bindings as a result scripts running during parse like connectedCallback. This more closely matches XUL document behavior, where the initial layout doesn't happen until everything is parsed and loaded. It also lets us call gBrowserInit.onBeforeInitialXULLayout actually before layout happens. Differential Revision: https://phabricator.services.mozilla.com/D8297
browser/base/content/browser.xul
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -65,17 +65,21 @@
         tabsintitlebar="true"
         titlemenuseparator="&mainWindow.titlemodifiermenuseparator;"
         windowtype="navigator:browser"
         macanimationtype="document"
         screenX="4" screenY="4"
         fullscreenbutton="true"
         sizemode="normal"
         retargetdocumentfocus="urlbar"
-        persist="screenX screenY width height sizemode">
+        persist="screenX screenY width height sizemode"
+#ifdef BROWSER_XHTML
+        hidden="true"
+#endif
+        >
 
 # All JS files which are needed by browser.xul and other top level windows to
 # support MacOS specific features *must* go into the global-scripts.inc file so
 # that they can be shared with macWindow.inc.xul.
 #include global-scripts.inc
 
 <script type="application/javascript"
 #ifdef BROWSER_XHTML
@@ -83,19 +87,24 @@ xmlns="http://www.w3.org/1999/xhtml"
 #endif
 >
   Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", this);
   Services.scriptloader.loadSubScript("chrome://browser/content/tabbrowser.js", this);
 
   window.onload = gBrowserInit.onLoad.bind(gBrowserInit);
   window.onunload = gBrowserInit.onUnload.bind(gBrowserInit);
   window.onclose = WindowIsClosing;
+
 #ifdef BROWSER_XHTML
-  window.addEventListener("DOMContentLoaded",
-    gBrowserInit.onBeforeInitialXULLayout.bind(gBrowserInit), { once: true });
+  window.addEventListener("readystatechange", () => {
+    // We initially hide the window to prevent layouts during parse. This lets us
+    // avoid accidental XBL construction and better match browser.xul (see Bug 1497975).
+    gBrowserInit.onBeforeInitialXULLayout();
+    document.documentElement.removeAttribute("hidden");
+  }, { once: true, capture: true });
 #else
   window.addEventListener("MozBeforeInitialXULLayout",
     gBrowserInit.onBeforeInitialXULLayout.bind(gBrowserInit), { once: true });
 #endif
   // The listener of DOMContentLoaded must be set on window, rather than
   // document, because the window can go away before the event is fired.
   // In that case, we don't want to initialize anything, otherwise we
   // may be leaking things because they will never be destroyed after.