Bug 1359779: Also look at pseudo frames in nsComputedDOMStyle::DoGetStyleContextNoFlush. r?heycam draft
authorEmilio Cobos Álvarez <emilio@crisal.io>
Wed, 26 Apr 2017 13:54:44 +0200
changeset 568647 4239c095fe683bce84f12dd92bdd91abe079f170
parent 568646 b06b31b54d18d705a0f21f1c60b25c59c48095ec
child 625984 895d6725a70f11662bac336379417b0000cf4068
push id55935
push userbmo:emilio+bugs@crisal.io
push dateWed, 26 Apr 2017 11:57:38 +0000
reviewersheycam
bugs1359779
milestone55.0a1
Bug 1359779: Also look at pseudo frames in nsComputedDOMStyle::DoGetStyleContextNoFlush. r?heycam MozReview-Commit-ID: IvAehgyv18T
layout/style/nsComputedDOMStyle.cpp
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -514,16 +514,44 @@ public:
 
 private:
   GeckoRestyleManager* mRestyleManager = nullptr;
   bool mOldSkipAnimationRules = false;
   nsComputedDOMStyle::AnimationFlag mAnimationFlag;
 };
 }
 
+/**
+ * The following function checks whether we need to explicitly resolve the style
+ * again, even though we have a style context coming from the frame.
+ *
+ * This basically checks whether the style is or may be under a ::first-line or
+ * ::first-letter frame, in which case we can't return the frame style, and we
+ * need to resolve it. See bug 505515.
+ */
+static bool
+MustReresolveStyle(const nsStyleContext* aContext)
+{
+  MOZ_ASSERT(aContext);
+
+  if (aContext->HasPseudoElementData()) {
+    if (!aContext->GetPseudo() ||
+        aContext->StyleSource().IsServoComputedValues()) {
+      // TODO(emilio): When ::first-line is supported in Servo, we may want to
+      // fix this to avoid re-resolving pseudo-element styles.
+      return true;
+    }
+
+    return aContext->GetParent() &&
+           aContext->GetParent()->HasPseudoElementData();
+  }
+
+  return false;
+}
+
 already_AddRefed<nsStyleContext>
 nsComputedDOMStyle::DoGetStyleContextNoFlush(Element* aElement,
                                              nsIAtom* aPseudo,
                                              nsIPresShell* aPresShell,
                                              AnimationFlag aAnimationFlag)
 {
   MOZ_ASSERT(aElement, "NULL element");
   // If the content has a pres shell, we must use it.  Otherwise we'd
@@ -538,26 +566,32 @@ nsComputedDOMStyle::DoGetStyleContextNoF
     presShell = aPresShell;
     if (!presShell)
       return nullptr;
   }
 
   // XXX the !aElement->IsHTMLElement(nsGkAtoms::area)
   // check is needed due to bug 135040 (to avoid using
   // mPrimaryFrame). Remove it once that's fixed.
-  if (!aPseudo &&
-      inDocWithShell &&
+  if (inDocWithShell &&
       !aElement->IsHTMLElement(nsGkAtoms::area)) {
-    nsIFrame* frame = nsLayoutUtils::GetStyleFrame(aElement);
+    nsIFrame* frame = nullptr;
+    if (aPseudo == nsCSSPseudoElements::before) {
+      frame = nsLayoutUtils::GetBeforeFrame(aElement);
+    } else if (aPseudo == nsCSSPseudoElements::after) {
+      frame = nsLayoutUtils::GetAfterFrame(aElement);
+    } else if (!aPseudo) {
+      frame = nsLayoutUtils::GetStyleFrame(aElement);
+    }
     if (frame) {
       nsStyleContext* result = frame->StyleContext();
       // Don't use the style context if it was influenced by
       // pseudo-elements, since then it's not the primary style
-      // for this element.
-      if (!result->HasPseudoElementData()) {
+      // for this element / pseudo.
+      if (!MustReresolveStyle(result)) {
         // The existing style context may have animation styles so check if we
         // need to remove them.
         if (aAnimationFlag == eWithoutAnimation) {
           nsPresContext* presContext = presShell->GetPresContext();
           MOZ_ASSERT(presContext, "Should have a prescontext if we have a frame");
           MOZ_ASSERT(presContext->StyleSet()->IsGecko(),
                      "stylo: Need ResolveStyleByRemovingAnimation for stylo");
           if (presContext && presContext->StyleSet()->IsGecko()) {
@@ -574,17 +608,17 @@ nsComputedDOMStyle::DoGetStyleContextNoF
         return ret.forget();
       }
     }
   }
 
   // No frame has been created, or we have a pseudo, or we're looking
   // for the default style, so resolve the style ourselves.
 
-  nsPresContext *presContext = presShell->GetPresContext();
+  nsPresContext* presContext = presShell->GetPresContext();
   if (!presContext)
     return nullptr;
 
   StyleSetHandle styleSet = presShell->StyleSet();
 
   auto type = CSSPseudoElementType::NotPseudo;
   if (aPseudo) {
     type = nsCSSPseudoElements::
@@ -710,44 +744,16 @@ nsComputedDOMStyle::SetResolvedStyleCont
 
 void
 nsComputedDOMStyle::SetFrameStyleContext(nsStyleContext* aContext)
 {
   ClearStyleContext();
   mStyleContext = aContext;
 }
 
-/**
- * The following function checks whether we need to explicitly resolve the style
- * again, even though we have a style context coming from the frame.
- *
- * This basically checks whether the style is or may be under a ::first-line or
- * ::first-letter frame, in which case we can't return the frame style, and we
- * need to resolve it. See bug 505515.
- */
-static bool
-MustReresolveStyle(const nsStyleContext* aContext)
-{
-  MOZ_ASSERT(aContext);
-
-  if (aContext->HasPseudoElementData()) {
-    if (!aContext->GetPseudo() ||
-        aContext->StyleSource().IsServoComputedValues()) {
-      // TODO(emilio): When ::first-line is supported in Servo, we may want to
-      // fix this to avoid re-resolving pseudo-element styles.
-      return true;
-    }
-
-    return aContext->GetParent() &&
-           aContext->GetParent()->HasPseudoElementData();
-  }
-
-  return false;
-}
-
 void
 nsComputedDOMStyle::UpdateCurrentStyleSources(bool aNeedsLayoutFlush)
 {
   nsCOMPtr<nsIDocument> document = do_QueryReferent(mDocumentWeak);
   if (!document) {
     ClearStyleContext();
     return;
   }