Bug 1294863 - Part 1: Expose nsCSSRuleProcessor's RefreshRuleCascade as a virtual function (default no-op) on nsIStyleRuleProcessor, up through nsStyleSet and nsPresContext. r?heycam draft
authorJonathan Chan <jyc@eqv.io>
Mon, 15 Aug 2016 00:56:49 -0700
changeset 400619 f38ddb1bc25a3144e3d5191fe331038df4881b16
parent 400618 02b3ff3a02ac6c715c1370e66b956fcf6d65a791
child 400620 d26f9df3c80904bb193f6a4e872337f4baf91f7c
push id26211
push userjchan@mozilla.com
push dateMon, 15 Aug 2016 08:07:32 +0000
reviewersheycam
bugs1294863
milestone51.0a1
Bug 1294863 - Part 1: Expose nsCSSRuleProcessor's RefreshRuleCascade as a virtual function (default no-op) on nsIStyleRuleProcessor, up through nsStyleSet and nsPresContext. r?heycam RefreshRuleCascade is currently called by MediumFeaturesChanged. Refreshing the rule cascade causes us to check which rule groups we need to apply (if media feature values have changed). The checks for individual rule groups are implemented in MediaRule::UseForPresentation. (MediaRule::UseForPresentation). This patch series will change the behavior of SupportsRule::UseFromPresentation to support custom property registrations changing, requiring reevaluation of the @supports condition. When registrations change, we want to refresh the rule cascade so that SupportsRule::UseFromPresentation is reevaluated. We could call nsPresContext::MediaFeatureValuesChanged, but that does extra work, and CSS variable registrations are not really media features. MozReview-Commit-ID: GUEX7w9hrUK
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
layout/style/nsIStyleRuleProcessor.h
layout/style/nsStyleSet.cpp
layout/style/nsStyleSet.h
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -1848,16 +1848,29 @@ nsPresContext::MediaFeatureValuesChanged
       aChangeHint
     };
 
     mDocument->EnumerateSubDocuments(MediaFeatureValuesChangedAllDocumentsCallback,
                                      &hints);
 }
 
 void
+nsPresContext::RefreshRuleCascade()
+{
+  if (mShell) {
+    if (mShell->StyleSet()->IsGecko()) {
+      mShell->StyleSet()->AsGecko()->RefreshRuleCascade();
+    } else {
+      NS_WARNING("stylo: ServoStyleSet needs to expose the same functionality. "
+                 "See also the warning in MediaFeatureValuesChanged.");
+    }
+  }
+}
+
+void
 nsPresContext::MediaFeatureValuesChanged(nsRestyleHint aRestyleHint,
                                          nsChangeHint aChangeHint)
 {
   mPendingMediaFeatureValuesChanged = false;
 
   // MediumFeaturesChanged updates the applied rules, so it always gets called.
   if (mShell) {
     // XXXheycam ServoStyleSets don't support responding to medium
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -262,16 +262,22 @@ public:
   /**
    * Just like RebuildAllStyleData, except (1) asynchronous and (2) it
    * doesn't rebuild the user font set.
    */
   void PostRebuildAllStyleDataEvent(nsChangeHint aExtraHint,
                                     nsRestyleHint aRestyleHint);
 
   /**
+   * Refresh the rule cascade. This does not rebuild all style data -- call
+   * RebuildAllStyleData that is necessary.
+   */
+  void RefreshRuleCascade();
+
+  /**
    * Handle changes in the values of media features (used in media
    * queries).
    *
    * There are three sensible values to use for aRestyleHint:
    *  * nsRestyleHint(0) to rebuild style data, with rerunning of
    *    selector matching, only if media features have changed
    *  * eRestyle_ForceDescendants to force rebuilding of style data (but
    *    still only rerun selector matching if media query results have
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -3756,17 +3756,17 @@ nsCSSRuleProcessor::GetRuleCascade(nsPre
   if (!mRuleCascades || aPresContext != mLastPresContext) {
     RefreshRuleCascade(aPresContext);
   }
   mLastPresContext = aPresContext;
 
   return mRuleCascades;
 }
 
-void
+/* virtual */ void
 nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
 {
   // Having RuleCascadeData objects be per-medium (over all variation
   // caused by media queries, handled through mCacheKey) works for now
   // since nsCSSRuleProcessor objects are per-document.  (For a given
   // set of stylesheets they can vary based on medium (@media) or
   // document (@-moz-document).)
 
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -229,17 +229,17 @@ public:
 protected:
   virtual ~nsCSSRuleProcessor();
 
 private:
   static bool CascadeSheet(mozilla::CSSStyleSheet* aSheet,
                            CascadeEnumData* aData);
 
   RuleCascadeData* GetRuleCascade(nsPresContext* aPresContext);
-  void RefreshRuleCascade(nsPresContext* aPresContext);
+  virtual void RefreshRuleCascade(nsPresContext* aPresContext) override;
 
   nsRestyleHint HasStateDependentStyle(ElementDependentRuleProcessorData* aData,
                                        mozilla::dom::Element* aStatefulElement,
                                        mozilla::CSSPseudoElementType aPseudoType,
                                        mozilla::EventStates aStateMask);
 
   void ClearSheets();
 
--- a/layout/style/nsIStyleRuleProcessor.h
+++ b/layout/style/nsIStyleRuleProcessor.h
@@ -115,16 +115,25 @@ public:
    * only, and may err on the side of reporting more dependencies than
    * really exist.
    */
   virtual nsRestyleHint HasAttributeDependentStyle(
       AttributeRuleProcessorData* aData,
       mozilla::RestyleHintData& aRestyleHintDataResult) = 0;
 
   /**
+   * Refresh the rule cascade, if relevant.
+   * Currently only nsCSSRuleProcessor can/should.
+   */
+  virtual void RefreshRuleCascade(nsPresContext* aPresContext)
+  {
+    // No-op unless overridden.
+  };
+
+  /**
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether this rule
    * processor's rules have changed (e.g., because of media queries).
    */
   virtual bool MediumFeaturesChanged(nsPresContext* aPresContext) = 0;
 
   /**
    * Report the size of this style rule processor to about:memory.  A
--- a/layout/style/nsStyleSet.cpp
+++ b/layout/style/nsStyleSet.cpp
@@ -2405,16 +2405,35 @@ nsStyleSet::HasAttributeDependentStyle(E
   if (!(data.mHint & eRestyle_Subtree)) {
     // No point keeping the list of selectors around if we are going to
     // restyle the whole subtree unconditionally.
     aRestyleHintDataResult = Move(data.mHintData);
   }
   return data.mHint;
 }
 
+void
+nsStyleSet::RefreshRuleCascade()
+{
+  NS_ASSERTION(mBatching == 0, "rule processors out of date");
+
+  nsPresContext* presContext = PresContext();
+
+  for (nsIStyleRuleProcessor* processor : mRuleProcessors) {
+    if (!processor) {
+      continue;
+    }
+    processor->RefreshRuleCascade(presContext);
+  }
+
+  for (nsIStyleRuleProcessor* processor : mScopedDocSheetRuleProcessors) {
+    processor->RefreshRuleCascade(presContext);
+  }
+}
+
 bool
 nsStyleSet::MediumFeaturesChanged()
 {
   NS_ASSERTION(mBatching == 0, "rule processors out of date");
 
   // We can't use WalkRuleProcessors without a content node.
   nsPresContext* presContext = PresContext();
   bool stylesChanged = false;
--- a/layout/style/nsStyleSet.h
+++ b/layout/style/nsStyleSet.h
@@ -303,16 +303,21 @@ class nsStyleSet final
                                            nsIAtom*       aAttribute,
                                            int32_t        aModType,
                                            bool           aAttrHasChanged,
                                            const nsAttrValue* aOtherValue,
                                            mozilla::RestyleHintData&
                                              aRestyleHintDataResult);
 
   /*
+   * Refresh the rule cascade in all associated rule processors.
+   */
+  void RefreshRuleCascade();
+
+  /*
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether style rules
    * may have changed as a result.
    */
   bool MediumFeaturesChanged();
 
   // APIs for registering objects that can supply additional
   // rules during processing.