Bug 1390389. Fix anon box restyling assertions to correctly handle ib splits. r=xidorn
authorBoris Zbarsky <bzbarsky@mit.edu>
Thu, 31 Aug 2017 09:12:13 -0400
changeset 377979 ca0fcfb8cec2
parent 377978 0b7dd5c229be
child 377980 ebdcd630db29
push id32420
push userkwierso@gmail.com
push dateThu, 31 Aug 2017 23:26:51 +0000
treeherdermozilla-central@14eea6bedcf3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1390389
milestone57.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 1390389. Fix anon box restyling assertions to correctly handle ib splits. r=xidorn MozReview-Commit-ID: AtBFlvLyg6b
layout/base/ServoRestyleManager.cpp
layout/base/crashtests/1390389.html
layout/base/crashtests/crashtests.list
layout/generic/nsFrame.cpp
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -55,17 +55,18 @@ ExpectedOwnerForChild(const nsIFrame& aF
     MOZ_ASSERT(parent->IsTableWrapperFrame());
     parent = parent->GetParent();
   }
 
   if (IsAnonBox(aFrame) && !aFrame.IsTextFrame()) {
     if (parent->IsLineFrame()) {
       parent = parent->GetParent();
     }
-    return parent->IsViewportFrame() ? nullptr : parent;
+    return parent->IsViewportFrame() ?
+      nullptr : FirstContinuationOrPartOfIBSplit(parent);
   }
 
   if (aFrame.IsBulletFrame()) {
     return parent;
   }
 
   if (aFrame.IsLineFrame()) {
     // A ::first-line always ends up here via its block, which is therefore the
@@ -198,34 +199,37 @@ ServoRestyleState::ProcessMaybeNestedWra
   nsIFrame* parent = cur->GetParent();
   if (cur->IsTableFrame()) {
     MOZ_ASSERT(parent->IsTableWrapperFrame());
     parent = parent->GetParent();
   }
   if (parent->IsLineFrame()) {
     parent = parent->GetParent();
   }
-  MOZ_ASSERT(parent->FirstContinuation() == aParent ||
+  MOZ_ASSERT(FirstContinuationOrPartOfIBSplit(parent) == aParent ||
              (parent->StyleContext()->IsInheritingAnonBox() &&
               parent->GetContent() == aParent->GetContent()));
 
-  // Now "this" is a ServoRestyleState for aParent, so if parent != aParent we
-  // need a new ServoRestyleState for the kid.
+  // Now "this" is a ServoRestyleState for aParent, so if parent is not a prev
+  // continuation (possibly across ib splits) of aParent we need a new
+  // ServoRestyleState for the kid.
   Maybe<ServoRestyleState> parentRestyleState;
-  if (parent != aParent) {
+  nsIFrame* parentForRestyle = aParent;
+  if (nsLayoutUtils::FirstContinuationOrIBSplitSibling(parent) != aParent) {
     parentRestyleState.emplace(*parent, *this, nsChangeHint_Empty,
                                Type::InFlow);
+    parentForRestyle = parent;
   }
   ServoRestyleState& curRestyleState =
     parentRestyleState ? *parentRestyleState : *this;
 
   // This frame may already have been restyled.  Even if it has, we can't just
   // return, because the next frame may be a kid of it that does need restyling.
   if (cur->IsWrapperAnonBoxNeedingRestyle()) {
-    parent->UpdateStyleOfChildAnonBox(cur, curRestyleState);
+    parentForRestyle->UpdateStyleOfChildAnonBox(cur, curRestyleState);
     cur->SetIsWrapperAnonBoxNeedingRestyle(false);
   }
 
   size_t numProcessed = 1;
 
   // Note: no overflow possible here, since aIndex < length.
   if (aIndex + 1 < mPendingWrapperRestyles.Length()) {
     nsIFrame* next = mPendingWrapperRestyles[aIndex + 1];
new file mode 100644
--- /dev/null
+++ b/layout/base/crashtests/1390389.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<script>
+a = document.createElement("span");
+document.documentElement.appendChild(a);
+b = document.createElement("span");
+b.appendChild(document.createElement("div"));
+a.appendChild(b);
+a.appendChild(document.createElement("col"));
+</script>
+</head>
+<body>
+<style>
+q { color: red; }
+</style>
+</body>
+</html>
--- a/layout/base/crashtests/crashtests.list
+++ b/layout/base/crashtests/crashtests.list
@@ -489,8 +489,9 @@ load 1308848-1.html
 load 1308848-2.html
 load 1338772-1.html
 load 1343937.html
 asserts(0-1) load 1343606.html # bug 1343948
 load 1352380.html
 load 1362423-1.html
 load 1381323.html
 asserts-if(!stylo,1) load 1388625-1.html # bug 1389286
+load 1390389.html
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -10209,25 +10209,27 @@ nsFrame::BoxMetrics() const
   NS_ASSERTION(metrics, "A box layout method was called but InitBoxMetrics was never called");
   return metrics;
 }
 
 void
 nsIFrame::UpdateStyleOfChildAnonBox(nsIFrame* aChildFrame,
                                     ServoRestyleState& aRestyleState)
 {
-  MOZ_ASSERT(aChildFrame->GetParent() == this ||
-             (aChildFrame->IsTableFrame() &&
-              aChildFrame->GetParent()->GetParent() == this) ||
-             (aChildFrame->GetParent()->IsLineFrame() &&
-              aChildFrame->GetParent()->GetParent() == this) ||
-             (aChildFrame->IsTableFrame() &&
-              aChildFrame->GetParent()->GetParent()->IsLineFrame() &&
-              aChildFrame->GetParent()->GetParent()->GetParent() == this),
+#ifdef DEBUG
+  nsIFrame* parent = aChildFrame->GetParent();;
+  if (aChildFrame->IsTableFrame()) {
+    parent = parent->GetParent();
+  }
+  if (parent->IsLineFrame()) {
+    parent = parent->GetParent();
+  }
+  MOZ_ASSERT(nsLayoutUtils::FirstContinuationOrIBSplitSibling(parent) == this,
              "This should only be used for children!");
+#endif // DEBUG
   MOZ_ASSERT(!GetContent() || !aChildFrame->GetContent() ||
              aChildFrame->GetContent() == GetContent(),
              "What content node is it a frame for?");
   MOZ_ASSERT(!aChildFrame->GetPrevContinuation(),
              "Only first continuations should end up here");
 
   // We could force the caller to pass in the pseudo, since some callers know it
   // statically...  But this API is a bit nicer.