Bug 996151 - Clear out XBL binding and insertion parent of content even if nsBindingManager is destroyed. r=mrbkap
authorWilliam Chen <wchen@mozilla.com>
Tue, 29 Apr 2014 11:37:02 -0700
changeset 181284 de19c62cbc6b583b04f8458e7e8b281c88551b3a
parent 181283 62f2593a641256bb73e8017457132f16e40764de
child 181285 1f052f973ee10b534adfe96bcb4020dfa3b2536a
child 181316 db8043427ac20c7f1a200000316d450b5c9dbd50
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmrbkap
bugs996151
milestone32.0a1
Bug 996151 - Clear out XBL binding and insertion parent of content even if nsBindingManager is destroyed. r=mrbkap
content/base/src/FragmentOrElement.cpp
dom/xbl/nsBindingManager.cpp
--- a/content/base/src/FragmentOrElement.cpp
+++ b/content/base/src/FragmentOrElement.cpp
@@ -1245,16 +1245,19 @@ FragmentOrElement::ClearContentUnbinder(
   ContentUnbinder::UnbindAll();
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(FragmentOrElement)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
   nsINode::Unlink(tmp);
 
+  // The XBL binding is removed by RemoveFromBindingManagerRunnable
+  // which is dispatched in UnbindFromTree.
+
   if (tmp->HasProperties()) {
     if (tmp->IsHTML()) {
       nsIAtom*** props = nsGenericHTMLElement::PropertiesToTraverseAndUnlink();
       for (uint32_t i = 0; props[i]; ++i) {
         tmp->DeleteProperty(*props[i]);
       }
     }
   }
--- a/dom/xbl/nsBindingManager.cpp
+++ b/dom/xbl/nsBindingManager.cpp
@@ -211,27 +211,32 @@ nsBindingManager::SetWrappedJS(nsIConten
 }
 
 void
 nsBindingManager::RemovedFromDocumentInternal(nsIContent* aContent,
                                               nsIDocument* aOldDocument)
 {
   NS_PRECONDITION(aOldDocument != nullptr, "no old document");
 
-  if (mDestroyed)
-    return;
-
   nsRefPtr<nsXBLBinding> binding = aContent->GetXBLBinding();
   if (binding) {
-    binding->PrototypeBinding()->BindingDetached(binding->GetBoundElement());
-    binding->ChangeDocument(aOldDocument, nullptr);
+    // The binding manager may have been destroyed before a runnable
+    // has had a chance to reach this point. If so, we bail out on calling
+    // BindingDetached (which may invoke a XBL destructor) and
+    // ChangeDocument, but we still want to clear out the binding
+    // and insertion parent that may hold references.
+    if (!mDestroyed) {
+      binding->PrototypeBinding()->BindingDetached(binding->GetBoundElement());
+      binding->ChangeDocument(aOldDocument, nullptr);
+    }
+
     aContent->SetXBLBinding(nullptr, this);
   }
 
-  // Clear out insertion parents and content lists.
+  // Clear out insertion parent and content lists.
   aContent->SetXBLInsertionParent(nullptr);
 }
 
 nsIAtom*
 nsBindingManager::ResolveTag(nsIContent* aContent, int32_t* aNameSpaceID)
 {
   nsXBLBinding *binding = aContent->GetXBLBinding();