Bug 1180120 - Part 6.2: Refactor MaybeReframeFor{Before,After}Pseudo. r=dbaron a=sylvestre
authorCameron McCormack <cam@mcc.id.au>
Sat, 29 Aug 2015 06:13:48 +1000
changeset 289222 121de382cd526ac99d0087fdcacef274bf5944aa
parent 289221 80143eb3ab7333a09939f264cd8748edb228f4bc
child 289223 124b3fa18283e6d689f511f83ee9ef484a3695e7
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, sylvestre
bugs1180120
milestone42.0a2
Bug 1180120 - Part 6.2: Refactor MaybeReframeFor{Before,After}Pseudo. r=dbaron a=sylvestre
layout/base/RestyleManager.cpp
layout/base/RestyleManager.h
--- a/layout/base/RestyleManager.cpp
+++ b/layout/base/RestyleManager.cpp
@@ -3825,20 +3825,22 @@ ElementRestyler::RestyleChildrenOfDispla
   nsRestyleHint          aRestyleHint,
   const RestyleHintData& aRestyleHintData)
 {
   MOZ_ASSERT(!(mHintsHandled & nsChangeHint_ReconstructFrame), "why call me?");
 
   const bool mightReframePseudos = aRestyleHint & eRestyle_Subtree;
   DoRestyleUndisplayedDescendants(nsRestyleHint(0), mContent, aNewContext);
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame) && mightReframePseudos) {
-    MaybeReframeForBeforePseudo(aParentFrame, nullptr, mContent, aNewContext);
+    MaybeReframeForPseudo(nsCSSPseudoElements::ePseudo_before,
+                          aParentFrame, nullptr, mContent, aNewContext);
   }
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame) && mightReframePseudos) {
-    MaybeReframeForAfterPseudo(aParentFrame, nullptr, mContent, aNewContext);
+    MaybeReframeForPseudo(nsCSSPseudoElements::ePseudo_after,
+                          aParentFrame, nullptr, mContent, aNewContext);
   }
   if (!(mHintsHandled & nsChangeHint_ReconstructFrame)) {
     InitializeAccessibilityNotifications(aNewContext);
 
     // Then process child frames for content that is a descendant of mContent.
     // XXX perhaps it's better to walk child frames (before reresolving
     // XXX undisplayed contexts above) and mark those that has a stylecontext
     // XXX leading up to mContent's old context? (instead of the
@@ -4060,100 +4062,114 @@ ElementRestyler::RestyleUndisplayedNodes
       }
     }
   }
 }
 
 void
 ElementRestyler::MaybeReframeForBeforePseudo()
 {
-  MaybeReframeForBeforePseudo(mFrame, mFrame, mFrame->GetContent(),
-                              mFrame->StyleContext());
-}
-
-void
-ElementRestyler::MaybeReframeForBeforePseudo(nsIFrame* aGenConParentFrame,
-                                             nsIFrame* aFrame,
-                                             nsIContent* aContent,
-                                             nsStyleContext* aStyleContext)
-{
-  // Make sure not to do this for pseudo-frames or frames that
-  // can't have generated content.
-  nsContainerFrame* cif;
-  if (!aStyleContext->GetPseudo() &&
-      ((aGenConParentFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
-       // Our content insertion frame might have gotten flagged.
-       ((cif = aGenConParentFrame->GetContentInsertionFrame()) &&
-        (cif->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)))) {
-    // Check for a ::before pseudo style and the absence of a ::before content,
-    // but only if aFrame is null or is the first continuation/ib-split.
-    if (!aFrame ||
-        nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) {
-      // Checking for a ::before frame is cheaper than getting the
-      // ::before style context.
-      if (!nsLayoutUtils::GetBeforeFrameForContent(aGenConParentFrame, aContent) &&
-          nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
-                                        nsCSSPseudoElements::ePseudo_before,
-                                        mPresContext)) {
-        // Have to create the new ::before frame.
-        LOG_RESTYLE("MaybeReframeForBeforePseudo, appending "
-                    "nsChangeHint_ReconstructFrame");
-        NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-        mChangeList->AppendChange(aFrame, aContent,
-                                  nsChangeHint_ReconstructFrame);
-      }
-    }
-  }
+  MaybeReframeForPseudo(nsCSSPseudoElements::ePseudo_before,
+                        mFrame, mFrame, mFrame->GetContent(),
+                        mFrame->StyleContext());
 }
 
 /**
  * aFrame is the last continuation or block-in-inline sibling that this
  * ElementRestyler is restyling.
  */
 void
 ElementRestyler::MaybeReframeForAfterPseudo(nsIFrame* aFrame)
 {
   MOZ_ASSERT(aFrame);
-  MaybeReframeForAfterPseudo(aFrame, aFrame, aFrame->GetContent(),
-                             aFrame->StyleContext());
+  MaybeReframeForPseudo(nsCSSPseudoElements::ePseudo_after,
+                        aFrame, aFrame, aFrame->GetContent(),
+                        aFrame->StyleContext());
 }
 
+#ifdef DEBUG
+bool
+ElementRestyler::MustReframeForBeforePseudo()
+{
+  return MustReframeForPseudo(nsCSSPseudoElements::ePseudo_before,
+                              mFrame, mFrame, mFrame->GetContent(),
+                              mFrame->StyleContext());
+}
+
+bool
+ElementRestyler::MustReframeForAfterPseudo(nsIFrame* aFrame)
+{
+  MOZ_ASSERT(aFrame);
+  return MustReframeForPseudo(nsCSSPseudoElements::ePseudo_after,
+                              aFrame, aFrame, aFrame->GetContent(),
+                              aFrame->StyleContext());
+}
+#endif
+
 void
-ElementRestyler::MaybeReframeForAfterPseudo(nsIFrame* aGenConParentFrame,
-                                            nsIFrame* aFrame,
-                                            nsIContent* aContent,
-                                            nsStyleContext* aStyleContext)
+ElementRestyler::MaybeReframeForPseudo(nsCSSPseudoElements::Type aPseudoType,
+                                       nsIFrame* aGenConParentFrame,
+                                       nsIFrame* aFrame,
+                                       nsIContent* aContent,
+                                       nsStyleContext* aStyleContext)
 {
-  // Make sure not to do this for pseudo-frames or frames that
-  // can't have generated content.
-  nsContainerFrame* cif;
-  if (!aStyleContext->GetPseudo() &&
-      ((aGenConParentFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT) ||
-       // Our content insertion frame might have gotten flagged.
-       ((cif = aGenConParentFrame->GetContentInsertionFrame()) &&
-        (cif->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)))) {
-    // Check for an ::after pseudo style and the absence of an ::after content,
-    // but only if aFrame is null or is the last continuation/ib-split.
-    if (!aFrame ||
-        !nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame)) {
-      // Checking for an ::after frame is cheaper than getting the
-      // ::after style context.
-      if (!nsLayoutUtils::GetAfterFrameForContent(aGenConParentFrame, aContent) &&
-          nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext,
-                                        nsCSSPseudoElements::ePseudo_after,
-                                        mPresContext)) {
-        // Have to create the new ::after frame.
-        LOG_RESTYLE("MaybeReframeForAfterPseudo, appending "
-                    "nsChangeHint_ReconstructFrame");
-        NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
-        mChangeList->AppendChange(aFrame, mContent,
-                                  nsChangeHint_ReconstructFrame);
-      }
+  if (MustReframeForPseudo(aPseudoType, aGenConParentFrame, aFrame, aContent,
+                           aStyleContext)) {
+    // Have to create the new ::before/::after frame.
+    LOG_RESTYLE("MaybeReframeForPseudo, appending "
+                "nsChangeHint_ReconstructFrame");
+    NS_UpdateHint(mHintsHandled, nsChangeHint_ReconstructFrame);
+    mChangeList->AppendChange(aFrame, aContent, nsChangeHint_ReconstructFrame);
+  }
+}
+
+bool
+ElementRestyler::MustReframeForPseudo(nsCSSPseudoElements::Type aPseudoType,
+                                      nsIFrame* aGenConParentFrame,
+                                      nsIFrame* aFrame,
+                                      nsIContent* aContent,
+                                      nsStyleContext* aStyleContext)
+{
+  MOZ_ASSERT(aPseudoType == nsCSSPseudoElements::ePseudo_before ||
+             aPseudoType == nsCSSPseudoElements::ePseudo_after);
+
+  // Make sure not to do this for pseudo-frames...
+  if (aStyleContext->GetPseudo()) {
+    return false;
+  }
+
+  // ... or frames that can't have generated content.
+  if (!(aGenConParentFrame->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)) {
+    // Our content insertion frame might have gotten flagged.
+    nsContainerFrame* cif = aGenConParentFrame->GetContentInsertionFrame();
+    if (!cif || !(cif->GetStateBits() & NS_FRAME_MAY_HAVE_GENERATED_CONTENT)) {
+      return false;
     }
   }
+
+  if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
+    // Check for a ::before pseudo style and the absence of a ::before content,
+    // but only if aFrame is null or is the first continuation/ib-split.
+    if ((aFrame && !nsLayoutUtils::IsFirstContinuationOrIBSplitSibling(aFrame)) ||
+        nsLayoutUtils::GetBeforeFrameForContent(aGenConParentFrame, aContent)) {
+      return false;
+    }
+  } else {
+    // Similarly for ::after, but check for being the last continuation/
+    // ib-split.
+    if ((aFrame && nsLayoutUtils::GetNextContinuationOrIBSplitSibling(aFrame)) ||
+        nsLayoutUtils::GetAfterFrameForContent(aGenConParentFrame, aContent)) {
+      return false;
+    }
+  }
+
+  // Checking for a ::before frame (which we do above) is cheaper than getting
+  // the ::before style context here.
+  return nsLayoutUtils::HasPseudoStyle(aContent, aStyleContext, aPseudoType,
+                                       mPresContext);
 }
 
 void
 ElementRestyler::InitializeAccessibilityNotifications(nsStyleContext* aNewContext)
 {
 #ifdef ACCESSIBILITY
   // Notify a11y for primary frame only if it's a root frame of visibility
   // changes or its parent frame was hidden while it stays visible and
--- a/layout/base/RestyleManager.h
+++ b/layout/base/RestyleManager.h
@@ -699,25 +699,31 @@ private:
                                        nsIContent* aParent,
                                        nsStyleContext* aParentStyleContext);
   void RestyleUndisplayedNodes(nsRestyleHint    aChildRestyleHint,
                                UndisplayedNode* aUndisplayed,
                                nsIContent*      aUndisplayedParent,
                                nsStyleContext*  aParentStyleContext,
                                const uint8_t    aDisplay);
   void MaybeReframeForBeforePseudo();
-  void MaybeReframeForBeforePseudo(nsIFrame* aGenConParentFrame,
-                                   nsIFrame* aFrame,
-                                   nsIContent* aContent,
-                                   nsStyleContext* aStyleContext);
   void MaybeReframeForAfterPseudo(nsIFrame* aFrame);
-  void MaybeReframeForAfterPseudo(nsIFrame* aGenConParentFrame,
-                                  nsIFrame* aFrame,
-                                  nsIContent* aContent,
-                                  nsStyleContext* aStyleContext);
+  void MaybeReframeForPseudo(nsCSSPseudoElements::Type aPseudoType,
+                             nsIFrame* aGenConParentFrame,
+                             nsIFrame* aFrame,
+                             nsIContent* aContent,
+                             nsStyleContext* aStyleContext);
+#ifdef DEBUG
+  bool MustReframeForBeforePseudo();
+  bool MustReframeForAfterPseudo(nsIFrame* aFrame);
+#endif
+  bool MustReframeForPseudo(nsCSSPseudoElements::Type aPseudoType,
+                            nsIFrame* aGenConParentFrame,
+                            nsIFrame* aFrame,
+                            nsIContent* aContent,
+                            nsStyleContext* aStyleContext);
   void RestyleContentChildren(nsIFrame* aParent,
                               nsRestyleHint aChildRestyleHint);
   void InitializeAccessibilityNotifications(nsStyleContext* aNewContext);
   void SendAccessibilityNotifications();
 
   enum DesiredA11yNotifications {
     eSkipNotifications,
     eSendAllNotifications,