Bug 1394935: Assert that we don't call into NoteDirtyElement with extra bits on the restyle root's parent chain. r?bholley draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Thu, 31 Aug 2017 09:42:22 +0200
changeset 656816 44811bfa011dd9330bef4b9a1d8852fa9db45d79
parent 656815 2253ef9871c6d1ea3c3de8e8d5f20a529e9083cf
child 656817 5ef53b0cdeba4b5374d3861b4a1ae9912703bc83
push id77325
push userbmo:emilio@crisal.io
push dateThu, 31 Aug 2017 18:09:13 +0000
reviewersbholley
bugs1394935
milestone57.0a1
Bug 1394935: Assert that we don't call into NoteDirtyElement with extra bits on the restyle root's parent chain. r?bholley MozReview-Commit-ID: Kt5aZSRBvlE
dom/base/Element.cpp
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -4260,16 +4260,31 @@ BitIsPropagated(const Element* aElement,
     MOZ_ASSERT_IF(!curr,
                   parentNode == aElement->OwnerDoc() ||
                   parentNode == parentNode->OwnerDoc()->GetRootElement());
   }
   return true;
 }
 #endif
 
+static inline void
+AssertNoBitsPropagatedFrom(nsINode* aRoot) {
+#ifdef DEBUG
+  if (!aRoot || !aRoot->IsElement()) {
+    return;
+  }
+
+  auto* element = aRoot->GetFlattenedTreeParentElementForStyle();
+  while (element) {
+    MOZ_ASSERT(!element->HasAnyOfFlags(Element::kAllServoDescendantBits));
+    element = element->GetFlattenedTreeParentElementForStyle();
+  }
+#endif
+}
+
 // Sets |aBits| on aElement and all of its flattened-tree ancestors up to and
 // including aStopAt or the root element (whichever is encountered first).
 static inline Element*
 PropagateBits(Element* aElement, uint32_t aBits, nsINode* aStopAt)
 {
   Element* curr = aElement;
   while (curr && !curr->HasAllFlags(aBits)) {
     curr->SetFlags(aBits);
@@ -4342,20 +4357,25 @@ NoteDirtyElement(Element* aElement, uint
     }
   }
 
   nsIDocument* doc = aElement->GetComposedDoc();
   if (nsIPresShell* shell = doc->GetShell()) {
     shell->EnsureStyleFlush();
   }
 
+  nsINode* existingRoot = doc->GetServoRestyleRoot();
+  uint32_t existingBits = existingRoot ? doc->GetServoRestyleRootDirtyBits() : 0;
+
+  // The bit checks below rely on this to arrive to useful conclusions about the
+  // shape of the tree.
+  AssertNoBitsPropagatedFrom(existingRoot);
+
   // If there's no existing restyle root, or if the root is already aElement,
   // just note the root+bits and return.
-  nsINode* existingRoot = doc->GetServoRestyleRoot();
-  uint32_t existingBits = existingRoot ? doc->GetServoRestyleRootDirtyBits() : 0;
   if (!existingRoot || existingRoot == aElement) {
     doc->SetServoRestyleRoot(aElement, existingBits | aBit);
     return;
   }
 
   // There is an existing restyle root - walk up the tree from our element,
   // propagating bits as wel go.
   const bool reachedDocRoot = !parent || !PropagateBits(parent, aBit, existingRoot);