Bug 555904 - When closing a tab, remove the browser and the tabpanel in two steps. r=mano
authorDão Gottwald <dao@mozilla.com>
Fri, 30 Jul 2010 08:50:08 +0200
changeset 48398 26dc2e50858786b9335790ba22d62731af87d23c
parent 48397 aee9fa2b6e9dc0bc688e9fcda37500f1edf2bacd
child 48399 b5781cd2d4fc5093af25815ea8454e8b0d1ac49e
push id14713
push userdgottwald@mozilla.com
push dateFri, 30 Jul 2010 06:53:57 +0000
treeherdermozilla-central@5b189034696e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmano
bugs555904
milestone2.0b3pre
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 555904 - When closing a tab, remove the browser and the tabpanel in two steps. r=mano
browser/base/content/tabbrowser.xml
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1454,28 +1454,41 @@
 
               // update tab close buttons state
               this.tabContainer.adjustTabstrip();
             }
 
             // update first-tab/last-tab/beforeselected/afterselected attributes
             this.selectedTab._selected = true;
 
+            // Removing the panel requires fixing up selectedPanel immediately
+            // (see below), which would be hindered by the potentially expensive
+            // browser removal. So we remove the browser and the panel in two
+            // steps.
+            var panel = browser.parentNode;
+
             // This will unload the document. An unload handler could remove
             // dependant tabs, so it's important that the tabbrowser is now in
             // a consistent state (tab removed, tab positions updated, etc.).
-            // Also, it's important that another tab has been selected before
-            // the panel is removed; otherwise, a random sibling panel can flash.
-            this.mPanelContainer.removeChild(browser.parentNode);
-
-            // As the panel is removed, the removal of a dependent document can
+            panel.removeChild(browser);
+
+            // As the browser is removed, the removal of a dependent document can
             // cause the whole window to close. So at this point, it's possible
             // that the binding is destructed.
-            if (this.mTabBox)
-              this.mTabBox.selectedPanel = this.getBrowserForTab(this.mCurrentTab).parentNode;
+            if (this.mTabBox) {
+              let selectedPanel = this.mTabBox.selectedPanel;
+
+              this.mPanelContainer.removeChild(panel);
+
+              // Under the hood, a selectedIndex attribute controls which panel
+              // is displayed. Removing a panel A which precedes the selected
+              // panel B makes selectedIndex point to the panel next to B. We
+              // need to explicitly preserve B as the selected panel.
+              this.mTabBox.selectedPanel = selectedPanel;
+            }
 
             if (aCloseWindow)
               this._windowIsClosing = closeWindow(true);
           ]]>
         </body>
       </method>
 
       <method name="_blurTab">