From 15074fcfdfde266457761356fc2af53d0f84240a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 9 Nov 2020 11:59:31 +0000 Subject: [PATCH] Bug 1675950 - Check for explicit restyles posted to pseudo-elements to check whether we need a style flush in getComputedStyle. r=heycam Font loading invalidation may invalidate only pseudo-elements, like it happens on this test-case. Once we get to testing first-line / first-letter in the test-case (css/css-values/ch-pseudo-recalc-on-font-load.html), we end up flushing because those end up posting the restyle to the parent element correctly. Differential Revision: https://phabricator.services.mozilla.com/D96373 --- layout/style/nsComputedDOMStyle.cpp | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 27d31b1c8641..89031e9d2dc5 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -83,6 +83,22 @@ static nsDOMCSSValueList* GetROCSSValueList(bool aCommaDelimited) { return new nsDOMCSSValueList(aCommaDelimited); } +static Element* GetRenderedElement(Element* aElement, nsAtom* aPseudo) { + if (aPseudo == nsCSSPseudoElements::before()) { + return nsLayoutUtils::GetBeforePseudo(aElement); + } + if (aPseudo == nsCSSPseudoElements::after()) { + return nsLayoutUtils::GetAfterPseudo(aElement); + } + if (aPseudo == nsCSSPseudoElements::marker()) { + return nsLayoutUtils::GetMarkerPseudo(aElement); + } + if (!aPseudo) { + return aElement; + } + return nullptr; +} + // Whether aDocument needs to restyle for aElement static bool ElementNeedsRestyle(Element* aElement, nsAtom* aPseudo, bool aMayNeedToFlushLayout) { @@ -151,12 +167,12 @@ static bool ElementNeedsRestyle(Element* aElement, nsAtom* aPseudo, return false; } - // Then if there is a restyle root, we check if the root is an ancestor of - // this content. If it is not, then we don't need to restyle immediately. - // Note this is different from Gecko: we only check if any ancestor needs - // to restyle _itself_, not descendants, since dirty descendants can be - // another subtree. - return Servo_HasPendingRestyleAncestor(aElement, aMayNeedToFlushLayout); + // If there's a pseudo, we need to prefer that element, as the pseudo itself + // may have explicit restyles. + Element* styledElement = GetRenderedElement(aElement, aPseudo); + // Try to skip the restyle otherwise. + return Servo_HasPendingRestyleAncestor( + styledElement ? styledElement : aElement, aMayNeedToFlushLayout); } /** @@ -516,18 +532,7 @@ already_AddRefed nsComputedDOMStyle::DoGetComputedStyleNoFlush( // mPrimaryFrame). Remove it once that's fixed. if (inDocWithShell && aStyleType == eAll && !aElement->IsHTMLElement(nsGkAtoms::area)) { - Element* element = nullptr; - if (aPseudo == nsCSSPseudoElements::before()) { - element = nsLayoutUtils::GetBeforePseudo(aElement); - } else if (aPseudo == nsCSSPseudoElements::after()) { - element = nsLayoutUtils::GetAfterPseudo(aElement); - } else if (aPseudo == nsCSSPseudoElements::marker()) { - element = nsLayoutUtils::GetMarkerPseudo(aElement); - } else if (!aPseudo) { - element = aElement; - } - - if (element) { + if (Element* element = GetRenderedElement(aElement, aPseudo)) { if (nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(element)) { ComputedStyle* result = styleFrame->Style(); // Don't use the style if it was influenced by pseudo-elements,