Bug 1400618 part 4 - Destroy frames before calling nsXBLBinding::ChangeDocument in a few places. r=bz
☠☠ backed out by ebc611dc8c85 ☠ ☠
authorMats Palmgren <mats@mozilla.com>
Sat, 04 Nov 2017 23:26:50 +0100
changeset 443475 fc5b7c39dd167042591c756e94f458c8605ffeea
parent 443474 82f3de55cfdf597656fc696c95ef9fab21cd6ce6
child 443476 14c27d1d3d54bea1e78a706e3c3fd9a1a699a5cf
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1400618
milestone58.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 1400618 part 4 - Destroy frames before calling nsXBLBinding::ChangeDocument in a few places. r=bz nsXBLBinding::ChangeDocument calls UnbindAnonymousContent which calls UnbindFromTree on the content so any frames must be destroyed before that to maintain the invariant that frames are destroyed before unbinding. MozReview-Commit-ID: 8Icj7zqpuZS
dom/xbl/nsBindingManager.cpp
dom/xml/nsXMLPrettyPrinter.cpp
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -271,29 +271,35 @@ nsBindingManager::ClearBinding(Element* 
 
   // Hold strong ref in case removing the binding tries to close the
   // window or something.
   // XXXbz should that be ownerdoc?  Wouldn't we need a ref to the
   // currentdoc too?  What's the one that should be passed to
   // ChangeDocument?
   nsCOMPtr<nsIDocument> doc = aElement->OwnerDoc();
 
+  // Destroy the frames here before the UnbindFromTree happens.
+  nsIPresShell* presShell = doc->GetShell();
+  if (presShell) {
+    presShell->DestroyFramesForAndRestyle(aElement);
+  }
+
   // Finally remove the binding...
   // XXXbz this doesn't remove the implementation!  Should fix!  Until
   // then we need the explicit UnhookEventHandlers here.
   binding->UnhookEventHandlers();
   binding->ChangeDocument(doc, nullptr);
   aElement->SetXBLBinding(nullptr, this);
   binding->MarkForDeath();
 
   // ...and recreate its frames. We need to do this since the frames may have
   // been removed and style may have changed due to the removal of the
   // anonymous children.
   // XXXbz this should be using the current doc (if any), not the owner doc.
-  nsIPresShell *presShell = doc->GetShell();
+  presShell = doc->GetShell(); // get the shell again, just in case it changed
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
 
   presShell->PostRecreateFramesFor(aElement);
   return NS_OK;
 }
 
 nsresult
 nsBindingManager::LoadBindingDocument(nsIDocument* aBoundDoc,
--- a/dom/xml/nsXMLPrettyPrinter.cpp
+++ b/dom/xml/nsXMLPrettyPrinter.cpp
@@ -43,17 +43,18 @@ nsXMLPrettyPrinter::~nsXMLPrettyPrinter(
 
 nsresult
 nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument,
                                 bool* aDidPrettyPrint)
 {
     *aDidPrettyPrint = false;
 
     // Check for iframe with display:none. Such iframes don't have presshells
-    if (!aDocument->GetShell()) {
+    nsIPresShell* shell = aDocument->GetShell();
+    if (!shell) {
         return NS_OK;
     }
 
     // check if we're in an invisible iframe
     nsPIDOMWindowOuter *internalWin = aDocument->GetWindow();
     nsCOMPtr<Element> frameElem;
     if (internalWin) {
         frameElem = internalWin->GetFrameElementInternal();
@@ -146,16 +147,21 @@ nsXMLPrettyPrinter::PrettyPrint(nsIDocum
     nsCOMPtr<nsIContent> rootCont = aDocument->GetRootElement();
     NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED);
 
     // Grab the system principal.
     nsCOMPtr<nsIPrincipal> sysPrincipal;
     nsContentUtils::GetSecurityManager()->
         GetSystemPrincipal(getter_AddRefs(sysPrincipal));
 
+    // Destroy any existing frames before we unbind anonymous content.
+    if (rootCont->IsElement()) {
+        shell->DestroyFramesForAndRestyle(rootCont->AsElement());
+    }
+
     // Load the bindings.
     RefPtr<nsXBLBinding> unused;
     bool ignored;
     rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal,
                                   getter_AddRefs(unused), &ignored);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Fire an event at the bound element to pass it |resultFragment|.