Bug 1400936: Only tear down the servo data in SetXBLInsertionParent if the parent actually changed. r?bholley draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Sat, 23 Sep 2017 00:02:59 +0200
changeset 669431 f2186b245fc1119734e708e8ae6df313fd78094b
parent 669430 e2b5747346b787bcc89d75716d300656d057b7b3
child 669432 efcc13d22c45dacb4a888d9a8af9c38f9a9de854
push id81323
push userbmo:emilio@crisal.io
push dateSat, 23 Sep 2017 02:54:45 +0000
reviewersbholley
bugs1400936
milestone58.0a1
Bug 1400936: Only tear down the servo data in SetXBLInsertionParent if the parent actually changed. r?bholley This is the reason similar assertion failures can't be reproduced with elements and stuff like fieldset and form validity changes. nsBindingManager::ContentRemoved calls SetXBLInsertionParent, which clears all the Servo data from the subtree eagerly, which is a waste when the actual binding parent is the same (null). MozReview-Commit-ID: A5wLKfD4OTL Signed-off-by: Emilio Cobos Álvarez <emilio@crisal.io>
dom/base/FragmentOrElement.cpp
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -1326,30 +1326,33 @@ FragmentOrElement::GetExistingDestInsert
     return &slots->mDestInsertionPoints;
   }
   return nullptr;
 }
 
 void
 FragmentOrElement::SetXBLInsertionParent(nsIContent* aContent)
 {
+  nsCOMPtr<nsIContent> oldInsertionParent = nullptr;
   if (aContent) {
     nsExtendedDOMSlots* slots = ExtendedDOMSlots();
     SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
+    oldInsertionParent = slots->mXBLInsertionParent.forget();
     slots->mXBLInsertionParent = aContent;
   } else {
-    nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
-    if (slots) {
+    if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) {
+      oldInsertionParent = slots->mXBLInsertionParent.forget();
       slots->mXBLInsertionParent = nullptr;
     }
   }
 
   // We just changed the flattened tree, so any Servo style data is now invalid.
   // We rely on nsXBLService::LoadBindings to re-traverse the subtree afterwards.
-  if (IsStyledByServo() && IsElement() && AsElement()->HasServoData()) {
+  if (oldInsertionParent != aContent &&
+      IsStyledByServo() && IsElement() && AsElement()->HasServoData()) {
     ServoRestyleManager::ClearServoDataFromSubtree(AsElement());
   }
 }
 
 nsresult
 FragmentOrElement::InsertChildAt(nsIContent* aKid,
                                 uint32_t aIndex,
                                 bool aNotify)