Bug 1180118 - Part 1: Add a method to match a single nsCSSSelector (without pseudo-elements) against an Element. r=bzbarsky
authorCameron McCormack <cam@mcc.id.au>
Wed, 05 Aug 2015 22:42:20 +1000
changeset 287956 7b8dc7443e3a970fed752690b5e972ce79129a31
parent 287955 352601bcc3070923eb908b5678613a4fcfcecdd9
child 287957 fc5ff8a35475b7fcf9010b08673b24d335122b79
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)
reviewersbzbarsky
bugs1180118
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1180118 - Part 1: Add a method to match a single nsCSSSelector (without pseudo-elements) against an Element. r=bzbarsky
layout/style/StyleRule.h
layout/style/nsCSSRuleProcessor.cpp
layout/style/nsCSSRuleProcessor.h
--- a/layout/style/StyleRule.h
+++ b/layout/style/StyleRule.h
@@ -154,16 +154,22 @@ public:
   }
 
   // Calculate the specificity of this selector (not including its mNext!).
   int32_t CalcWeight() const;
 
   void ToString(nsAString& aString, mozilla::CSSStyleSheet* aSheet,
                 bool aAppend = false) const;
 
+#ifdef DEBUG
+  bool IsRestrictedSelector() const {
+    return PseudoType() == nsCSSPseudoElements::ePseudo_NotPseudoElement;
+  }
+#endif
+
 private:
   void AddPseudoClassInternal(nsPseudoClassList *aPseudoClass);
   nsCSSSelector* Clone(bool aDeepNext, bool aDeepNegations) const;
 
   void AppendToStringWithoutCombinators(nsAString& aString,
                                         mozilla::CSSStyleSheet* aSheet) const;
   void AppendToStringWithoutCombinatorsOrNegations(nsAString& aString,
                                                    mozilla::CSSStyleSheet* aSheet,
--- a/layout/style/nsCSSRuleProcessor.cpp
+++ b/layout/style/nsCSSRuleProcessor.cpp
@@ -2288,16 +2288,46 @@ static bool SelectorMatches(Element* aEl
       result = result || dependence;
     }
   }
   return result;
 }
 
 #undef STATE_CHECK
 
+/* static */ bool
+nsCSSRuleProcessor::RestrictedSelectorMatches(
+    Element* aElement,
+    nsCSSSelector* aSelector,
+    TreeMatchContext& aTreeMatchContext)
+{
+  MOZ_ASSERT(aSelector->IsRestrictedSelector(),
+             "aSelector must not have a pseudo-element");
+
+  // We match aSelector as if :visited and :link both match visited and
+  // unvisited links.
+
+  NodeMatchContext nodeContext(EventStates(),
+                               nsCSSRuleProcessor::IsLink(aElement));
+  if (nodeContext.mIsRelevantLink) {
+    aTreeMatchContext.SetHaveRelevantLink();
+  }
+  aTreeMatchContext.ResetForUnvisitedMatching();
+  bool matches = SelectorMatches(aElement, aSelector, nodeContext,
+                                 aTreeMatchContext, SelectorMatchesFlags::NONE);
+  if (nodeContext.mIsRelevantLink) {
+    aTreeMatchContext.ResetForVisitedMatching();
+    if (SelectorMatches(aElement, aSelector, nodeContext, aTreeMatchContext,
+                        SelectorMatchesFlags::NONE)) {
+      matches = true;
+    }
+  }
+  return matches;
+}
+
 // Right now, there are four operators:
 //   ' ', the descendant combinator, is greedy
 //   '~', the indirect adjacent sibling combinator, is greedy
 //   '+' and '>', the direct adjacent sibling and child combinators, are not
 #define NS_IS_GREEDY_OPERATOR(ch) \
   ((ch) == char16_t(' ') || (ch) == char16_t('~'))
 
 static bool SelectorMatchesTree(Element* aPrevElement,
--- a/layout/style/nsCSSRuleProcessor.h
+++ b/layout/style/nsCSSRuleProcessor.h
@@ -107,16 +107,31 @@ public:
              nsRuleWalker::VisitedHandlingType aVisitedHandling,
              bool aIsRelevantLink);
 
   /*
    * Helper to test whether a node is a link
    */
   static bool IsLink(mozilla::dom::Element* aElement);
 
+  /**
+   * Returns true if the given aElement matches aSelector.
+   * Like nsCSSRuleProcessor.cpp's SelectorMatches (and unlike
+   * SelectorMatchesTree), this does not check an entire selector list
+   * separated by combinators.
+   *
+   * :visited and :link will match both visited and non-visited links,
+   * as if aTreeMatchContext->mVisitedHandling were eLinksVisitedOrUnvisited.
+   *
+   * aSelector is restricted to not containing pseudo-elements.
+   */
+  static bool RestrictedSelectorMatches(mozilla::dom::Element* aElement,
+                                        nsCSSSelector* aSelector,
+                                        TreeMatchContext& aTreeMatchContext);
+
   // nsIStyleRuleProcessor
   virtual void RulesMatching(ElementRuleProcessorData* aData) override;
 
   virtual void RulesMatching(PseudoElementRuleProcessorData* aData) override;
 
   virtual void RulesMatching(AnonBoxRuleProcessorData* aData) override;
 
 #ifdef MOZ_XUL