Bug 1400618 part 4 - Destroy frames before calling nsXBLBinding::ChangeDocument in a few places. r=bz
authorMats Palmgren <mats@mozilla.com>
Tue, 07 Nov 2017 01:20:34 +0100
changeset 443695 82659642e0583a8e493bea4f0a7bfb75dc48accd
parent 443694 50c2aba68909c45c8136fd5ba20865e9c0309b87
child 443696 e46bd0b42454a446bd1080a4d32f92386d2d2336
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|.