Bug 1324619 part 6. Handle dynamic restyles of ::first-line in stylo. r?emilio
MozReview-Commit-ID: 3jQhIqPuL1g
--- a/layout/base/ServoRestyleManager.cpp
+++ b/layout/base/ServoRestyleManager.cpp
@@ -53,16 +53,26 @@ ExpectedOwnerForChild(const nsIFrame& aF
if (IsAnonBox(aFrame) && !aFrame.IsTextFrame()) {
return aFrame.GetParent()->IsViewportFrame() ? nullptr : aFrame.GetParent();
}
if (aFrame.IsBulletFrame()) {
return aFrame.GetParent();
}
+ if (aFrame.IsLineFrame()) {
+ // A ::first-line always ends up here via its block, which is therefore the
+ // right expected owner. That block can be an
+ // anonymous box. For example, we could have a ::first-line on a columnated
+ // block; the blockframe is the column-content anonymous box in that case.
+ // So we don't want to end up in the code below, which steps out of anon
+ // boxes. Just return the parent of the line frame, which is the block.
+ return aFrame.GetParent();
+ }
+
const nsIFrame* parent = FirstContinuationOrPartOfIBSplit(aFrame.GetParent());
if (aFrame.IsTableFrame()) {
MOZ_ASSERT(parent->IsTableWrapperFrame());
parent = FirstContinuationOrPartOfIBSplit(parent->GetParent());
}
// We've handled already anon boxes and bullet frames, so now we're looking at
@@ -706,18 +716,40 @@ ServoRestyleManager::ProcessPostTraversa
}
}
}
// We want to update frame pseudo-element styles after we've traversed our
// kids, because some of those updates (::first-line/::first-letter) need to
// modify the styles of the kids, and the child traversal above would just
// clobber those modifications.
- if (wasRestyled && styleFrame) {
- UpdateFramePseudoElementStyles(styleFrame, childrenRestyleState);
+ if (styleFrame) {
+ if (wasRestyled) {
+ UpdateFramePseudoElementStyles(styleFrame, childrenRestyleState);
+ } else if (traverseElementChildren &&
+ styleFrame->IsFrameOfType(nsIFrame::eBlockFrame)) {
+ // Even if we were not restyled, if we're a block with a first-line and
+ // one of our descendant elements which is on the first line was restyled,
+ // we need to update the styles of things on the first line, because
+ // they're wrong now.
+ //
+ // FIXME(bz) Could we do better here? For example, could we keep track of
+ // frames that are "block with a ::first-line so we could avoid
+ // IsFrameOfType() and digging about for the first-line frame if not?
+ // Could we keep track of whether the element children we actually restyle
+ // are affected by first-line? Something else? Bug 1385443 tracks making
+ // this better.
+ nsIFrame* firstLineFrame =
+ static_cast<nsBlockFrame*>(styleFrame)->GetFirstLineFrame();
+ if (firstLineFrame) {
+ for (nsIFrame* kid : firstLineFrame->PrincipalChildList()) {
+ ReparentStyleContext(kid);
+ }
+ }
+ }
}
if (!forThrottledAnimationFlush) {
aElement->UnsetHasDirtyDescendantsForServo();
aElement->UnsetFlags(NODE_DESCENDANTS_NEED_FRAMES);
}
aElement->UnsetHasAnimationOnlyDirtyDescendantsForServo();
return recreatedAnyContext;
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -7571,16 +7571,47 @@ void
nsBlockFrame::UpdatePseudoElementStyles(ServoRestyleState& aRestyleState)
{
if (nsBulletFrame* bullet = GetBullet()) {
CSSPseudoElementType type = bullet->StyleContext()->GetPseudoType();
RefPtr<nsStyleContext> newBulletStyle =
ResolveBulletStyle(type, &aRestyleState.StyleSet());
UpdateStyleOfOwnedChildFrame(bullet, newBulletStyle, aRestyleState);
}
+
+ if (nsIFrame* firstLineFrame = GetFirstLineFrame()) {
+ nsIFrame* styleParent =
+ CorrectStyleParentFrame(firstLineFrame->GetParent(),
+ nsCSSPseudoElements::firstLine);
+
+ ServoStyleContext* parentStyle = styleParent->StyleContext()->AsServo();
+ RefPtr<ServoStyleContext> firstLineStyle =
+ aRestyleState.StyleSet()
+ .ResolvePseudoElementStyle(mContent->AsElement(),
+ CSSPseudoElementType::firstLine,
+ parentStyle,
+ nullptr);
+
+ // FIXME(bz): Can we make first-line continuations be non-inheriting anon
+ // boxes?
+ RefPtr<ServoStyleContext> continuationStyle = aRestyleState.StyleSet().
+ ResolveInheritingAnonymousBoxStyle(nsCSSAnonBoxes::mozLineFrame,
+ parentStyle);
+
+ UpdateStyleOfOwnedChildFrame(firstLineFrame, firstLineStyle, aRestyleState,
+ Some(continuationStyle.get()));
+
+ // We also want to update the styles of the first-line's descendants. We
+ // don't need to compute a changehint for this, though, since any changes to
+ // them are handled by the first-line anyway.
+ ServoRestyleManager* manager = PresContext()->RestyleManager()->AsServo();
+ for (nsIFrame* kid : firstLineFrame->PrincipalChildList()) {
+ manager->ReparentStyleContext(kid);
+ }
+ }
}
already_AddRefed<nsStyleContext>
nsBlockFrame::ResolveBulletStyle(CSSPseudoElementType aType,
StyleSetHandle aStyleSet)
{
nsStyleContext* parentStyle =
CorrectStyleParentFrame(this,
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -1691,17 +1691,17 @@ fuzzy-if(skiaContent,1,3500) == 660682-1
fuzzy-if(d2d,1,256) skip-if(Android) fuzzy-if(skiaContent,1,68000) == 664127-1.xul 664127-1-ref.xul # Android: Intermittent failures - bug 1019131
== 665597-1.html 665597-1-ref.html
== 665597-2.html 665597-2-ref.html
== 667079-1.html 667079-1-ref.html
== 668319-1.xul about:blank
!= 669015-1.xul 669015-1-notref.xul
skip-if(azureSkiaGL) == 670442-1.html 670442-1-ref.html
== 670467-1.html 670467-1-ref.html
-fails-if(styloVsGecko||stylo) == 670467-2.html 670467-2-ref.html
+== 670467-2.html 670467-2-ref.html
== 690164-1.html 690164-1-ref.html
== 690643-1.html 690643-1-ref.html
!= 691087-1.html 691087-1-ref.html
== 691571-1.html 691571-1-ref.html
fuzzy-if(skiaContent,1,200) == 696307-1.html 696307-1-ref.html
fuzzy-if(skiaContent,1,550) == 696739-1.html 696739-1-ref.html
needs-focus == 703186-1.html 703186-1-ref.html
needs-focus == 703186-2.html 703186-2-ref.html
--- a/layout/reftests/first-line/reftest.list
+++ b/layout/reftests/first-line/reftest.list
@@ -27,15 +27,15 @@ load stress-10.html # crash test
== border-not-apply.html border-not-apply-ref.html
== 287088-1.html 287088-1-ref.html
== 287088-2.html 287088-2-ref.html
== 403177-1.html 403177-1-ref.html
== 469227-2.html 469227-2-ref.html
== 469227-3.html 469227-3-ref.html
-fails-if(styloVsGecko||stylo) == restyle-inside-first-line.html restyle-inside-first-line-ref.html
+== restyle-inside-first-line.html restyle-inside-first-line-ref.html
== font-styles.html font-styles-ref.html
fuzzy-if(OSX==1010,1,2) == font-styles-nooverflow.html font-styles-ref.html
fails-if(!stylo) == ib-split-1.html ib-split-1-ref.html
== first-line-in-columnset-1.html first-line-in-columnset-1-ref.html