Title: [131002] trunk/Source/WebCore
Revision
131002
Author
[email protected]
Date
2012-10-10 20:07:32 -0700 (Wed, 10 Oct 2012)

Log Message

Minimize the recent template explosion in SelectorChecker.
https://bugs.webkit.org/show_bug.cgi?id=98829

Reviewed by Antti Koivisto.

We've recently added the capability to switch sibling traversal strategy to SelectorChecker, at some readability/clarity expense.
This patch tries to minimize the surface of this expense to SelectorChecker::checkOneSelector.

No new tests, no change in behavior.

* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkSelector): Turned back into a function.
(WebCore::SelectorChecker::checkOneSelector): Changed to specialize on traversal strategy, rather than the context, which was less clear.
(WebCore::SelectorChecker::DOMTraversalStrategy::isFirstChild): Turned into a function.
(WebCore::SelectorChecker::DOMTraversalStrategy::isLastChild): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::isFirstOfType): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::isLastOfType): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::countElementsBefore): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::countElementsOfTypeBefore): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::countElementsAfter): Ditto.
(WebCore::SelectorChecker::DOMTraversalStrategy::countElementsOfTypeAfter): Ditto.
* css/SelectorChecker.h:
(DOMTraversalStrategy): Changed into a class, rather than a template.
(SelectorChecker): Turned back into a function.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (131001 => 131002)


--- trunk/Source/WebCore/ChangeLog	2012-10-11 03:06:24 UTC (rev 131001)
+++ trunk/Source/WebCore/ChangeLog	2012-10-11 03:07:32 UTC (rev 131002)
@@ -1,3 +1,30 @@
+2012-10-10  Dimitri Glazkov  <[email protected]>
+
+        Minimize the recent template explosion in SelectorChecker.
+        https://bugs.webkit.org/show_bug.cgi?id=98829
+
+        Reviewed by Antti Koivisto.
+
+        We've recently added the capability to switch sibling traversal strategy to SelectorChecker, at some readability/clarity expense.
+        This patch tries to minimize the surface of this expense to SelectorChecker::checkOneSelector. 
+
+        No new tests, no change in behavior.
+
+        * css/SelectorChecker.cpp:
+        (WebCore::SelectorChecker::checkSelector): Turned back into a function.
+        (WebCore::SelectorChecker::checkOneSelector): Changed to specialize on traversal strategy, rather than the context, which was less clear.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::isFirstChild): Turned into a function.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::isLastChild): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::isFirstOfType): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::isLastOfType): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::countElementsBefore): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::countElementsOfTypeBefore): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::countElementsAfter): Ditto.
+        (WebCore::SelectorChecker::DOMTraversalStrategy::countElementsOfTypeAfter): Ditto.
+        * css/SelectorChecker.h:
+        (DOMTraversalStrategy): Changed into a class, rather than a template.
+        (SelectorChecker): Turned back into a function.
+
 2012-10-10  James Simonsen  <[email protected]>
 
         High res times should start at 0

Modified: trunk/Source/WebCore/css/SelectorChecker.cpp (131001 => 131002)


--- trunk/Source/WebCore/css/SelectorChecker.cpp	2012-10-11 03:06:24 UTC (rev 131001)
+++ trunk/Source/WebCore/css/SelectorChecker.cpp	2012-10-11 03:07:32 UTC (rev 131002)
@@ -439,11 +439,10 @@
 // * SelectorFailsLocally     - the selector fails for the element e
 // * SelectorFailsAllSiblings - the selector fails for e and any sibling of e
 // * SelectorFailsCompletely  - the selector fails for e and any sibling or ancestor of e
-template<typename CheckingContext>
-SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const CheckingContext& context, PseudoId& dynamicPseudo, bool& hasUnknownPseudoElements) const
+SelectorChecker::SelectorMatch SelectorChecker::checkSelector(const SelectorCheckingContext& context, PseudoId& dynamicPseudo, bool& hasUnknownPseudoElements) const
 {
     // first selector has to match
-    if (!checkOneSelector(context))
+    if (!checkOneSelector(context, DOMSiblingTraversalStrategy()))
         return SelectorFailsLocally;
 
     if (context.selector->m_match == CSSSelector::PseudoElement) {
@@ -473,7 +472,7 @@
     if (!historySelector)
         return SelectorMatches;
 
-    CheckingContext nextContext(context);
+    SelectorCheckingContext nextContext(context);
     nextContext.selector = historySelector;
 
     PseudoId ignoreDynamicPseudo = NOPSEUDO;
@@ -727,8 +726,8 @@
     return false;
 }
 
-template<typename CheckingContext>
-bool SelectorChecker::checkOneSelector(const CheckingContext& context) const
+template<typename SiblingTraversalStrategy>
+bool SelectorChecker::checkOneSelector(const SelectorCheckingContext& context, const SiblingTraversalStrategy& siblingTraversalStrategy) const
 {
     Element* const & element = context.element;
     CSSSelector* const & selector = context.selector;
@@ -765,7 +764,7 @@
             if (!selectorList)
                 return false;
 
-            CheckingContext subContext(context);
+            SelectorCheckingContext subContext(context);
             subContext.isSubSelector = true;
             for (subContext.selector = selectorList->first(); subContext.selector; subContext.selector = subContext.selector->tagHistory()) {
                 // :not cannot nest. I don't really know why this is a
@@ -775,7 +774,7 @@
                 // We select between :visited and :link when applying. We don't know which one applied (or not) yet.
                 if (subContext.selector->pseudoType() == CSSSelector::PseudoVisited || (subContext.selector->pseudoType() == CSSSelector::PseudoLink && subContext.visitedMatchType == VisitedMatchEnabled))
                     return true;
-                if (!checkOneSelector(subContext))
+                if (!checkOneSelector(subContext, DOMSiblingTraversalStrategy()))
                     return true;
             }
         } else if (context.hasScrollbarPseudo) {
@@ -819,7 +818,7 @@
         case CSSSelector::PseudoFirstChild:
             // first-child matches the first child that is an element
             if (element->parentElement()) {
-                bool result = DOMTraversalStrategy<CheckingContext>::isFirstChild(context, element);
+                bool result = siblingTraversalStrategy.isFirstChild(element);
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : element->parentNode()->renderStyle();
@@ -834,7 +833,7 @@
         case CSSSelector::PseudoFirstOfType:
             // first-of-type matches the first element of its type
             if (element->parentElement()) {
-                bool result = DOMTraversalStrategy<CheckingContext>::isFirstOfType(context, element, element->tagQName());
+                bool result = siblingTraversalStrategy.isFirstOfType(element, element->tagQName());
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : element->parentNode()->renderStyle();
                     if (parentStyle)
@@ -846,7 +845,7 @@
         case CSSSelector::PseudoLastChild:
             // last-child matches the last child that is an element
             if (Element* parentElement = element->parentElement()) {
-                bool result = parentElement->isFinishedParsingChildren() && DOMTraversalStrategy<CheckingContext>::isLastChild(context, element);
+                bool result = parentElement->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element);
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
@@ -868,13 +867,13 @@
                 }
                 if (!parentElement->isFinishedParsingChildren())
                     return false;
-                return DOMTraversalStrategy<CheckingContext>::isLastOfType(context, element, element->tagQName());
+                return siblingTraversalStrategy.isLastOfType(element, element->tagQName());
             }
             break;
         case CSSSelector::PseudoOnlyChild:
             if (Element* parentElement = element->parentElement()) {
-                bool firstChild = DOMTraversalStrategy<CheckingContext>::isFirstChild(context, element);
-                bool _onlyChild_ = firstChild && parentElement->isFinishedParsingChildren() && DOMTraversalStrategy<CheckingContext>::isLastChild(context, element);
+                bool firstChild = siblingTraversalStrategy.isFirstChild(element);
+                bool _onlyChild_ = firstChild && parentElement->isFinishedParsingChildren() && siblingTraversalStrategy.isLastChild(element);
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
@@ -902,14 +901,14 @@
                 }
                 if (!parentElement->isFinishedParsingChildren())
                     return false;
-                return DOMTraversalStrategy<CheckingContext>::isFirstOfType(context, element, element->tagQName()) && DOMTraversalStrategy<CheckingContext>::isLastOfType(context, element, element->tagQName());
+                return siblingTraversalStrategy.isFirstOfType(element, element->tagQName()) && siblingTraversalStrategy.isLastOfType(element, element->tagQName());
             }
             break;
         case CSSSelector::PseudoNthChild:
             if (!selector->parseNth())
                 break;
             if (Element* parentElement = element->parentElement()) {
-                int count = 1 + DOMTraversalStrategy<CheckingContext>::countElementsBefore(context, element);
+                int count = 1 + siblingTraversalStrategy.countElementsBefore(element);
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* childStyle = context.elementStyle ? context.elementStyle : element->renderStyle();
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
@@ -927,7 +926,7 @@
             if (!selector->parseNth())
                 break;
             if (Element* parentElement = element->parentElement()) {
-                int count = 1 + DOMTraversalStrategy<CheckingContext>::countElementsOfTypeBefore(context, element, element->tagQName());
+                int count = 1 + siblingTraversalStrategy.countElementsOfTypeBefore(element, element->tagQName());
                 if (m_mode == ResolvingStyle) {
                     RenderStyle* parentStyle = context.elementStyle ? context.elementParentStyle : parentElement->renderStyle();
                     if (parentStyle)
@@ -949,7 +948,7 @@
                 }
                 if (!parentElement->isFinishedParsingChildren())
                     return false;
-                int count = 1 + DOMTraversalStrategy<CheckingContext>::countElementsAfter(context, element);
+                int count = 1 + siblingTraversalStrategy.countElementsAfter(element);
                 if (selector->matchNth(count))
                     return true;
             }
@@ -966,7 +965,7 @@
                 if (!parentElement->isFinishedParsingChildren())
                     return false;
 
-                int count = 1 + DOMTraversalStrategy<CheckingContext>::countElementsOfTypeAfter(context, element, element->tagQName());
+                int count = 1 + siblingTraversalStrategy.countElementsOfTypeAfter(element, element->tagQName());
                 if (selector->matchNth(count))
                     return true;
             }
@@ -977,7 +976,7 @@
             break;
         case CSSSelector::PseudoAny:
             {
-                CheckingContext subContext(context);
+                SelectorCheckingContext subContext(context);
                 subContext.isSubSelector = true;
                 bool hasUnknownPseudoElements = false;
                 PseudoId ignoreDynamicPseudo = NOPSEUDO;
@@ -1359,20 +1358,17 @@
     return true;
 }
 
-template<>
-inline bool SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::isFirstChild(const SelectorChecker::SelectorCheckingContext&, Element* element)
+inline bool SelectorChecker::DOMSiblingTraversalStrategy::isFirstChild(Element* element) const
 {
     return !element->previousElementSibling();
 }
 
-template<>
-inline bool SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::isLastChild(const SelectorChecker::SelectorCheckingContext&, Element* element)
+inline bool SelectorChecker::DOMSiblingTraversalStrategy::isLastChild(Element* element) const
 {
     return !element->nextElementSibling();
 }
 
-template<>
-inline bool SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::isFirstOfType(const SelectorChecker::SelectorCheckingContext&, Element* element, const QualifiedName& type)
+inline bool SelectorChecker::DOMSiblingTraversalStrategy::isFirstOfType(Element* element, const QualifiedName& type) const
 {
     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
         if (sibling->hasTagName(type))
@@ -1381,8 +1377,7 @@
     return true;
 }
 
-template<>
-inline bool SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::isLastOfType(const SelectorChecker::SelectorCheckingContext&, Element* element, const QualifiedName& type)
+inline bool SelectorChecker::DOMSiblingTraversalStrategy::isLastOfType(Element* element, const QualifiedName& type) const
 {
     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
         if (sibling->hasTagName(type))
@@ -1391,8 +1386,7 @@
     return true;
 }
 
-template<>
-inline int SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::countElementsBefore(const SelectorChecker::SelectorCheckingContext&, Element* element)
+inline int SelectorChecker::DOMSiblingTraversalStrategy::countElementsBefore(Element* element) const
 {
     int count = 0;
     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
@@ -1408,8 +1402,7 @@
     return count;
 }
 
-template<>
-inline int SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::countElementsOfTypeBefore(const SelectorChecker::SelectorCheckingContext&, Element* element, const QualifiedName& type)
+inline int SelectorChecker::DOMSiblingTraversalStrategy::countElementsOfTypeBefore(Element* element, const QualifiedName& type) const
 {
     int count = 0;
     for (const Element* sibling = element->previousElementSibling(); sibling; sibling = sibling->previousElementSibling()) {
@@ -1420,8 +1413,7 @@
     return count;
 }
 
-template<>
-inline int SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::countElementsAfter(const SelectorChecker::SelectorCheckingContext&, Element* element)
+inline int SelectorChecker::DOMSiblingTraversalStrategy::countElementsAfter(Element* element) const
 {
     int count = 0;
     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling())
@@ -1430,8 +1422,7 @@
     return count;
 }
 
-template<>
-inline int SelectorChecker::DOMTraversalStrategy<SelectorChecker::SelectorCheckingContext>::countElementsOfTypeAfter(const SelectorChecker::SelectorCheckingContext&, Element* element, const QualifiedName& type)
+inline int SelectorChecker::DOMSiblingTraversalStrategy::countElementsOfTypeAfter(Element* element, const QualifiedName& type) const
 {
     int count = 0;
     for (const Element* sibling = element->nextElementSibling(); sibling; sibling = sibling->nextElementSibling()) {
@@ -1442,7 +1433,4 @@
     return count;
 }
 
-template
-SelectorChecker::SelectorMatch SelectorChecker::checkSelector<SelectorChecker::SelectorCheckingContext>(const SelectorCheckingContext&, PseudoId&, bool&) const;
-
 }

Modified: trunk/Source/WebCore/css/SelectorChecker.h (131001 => 131002)


--- trunk/Source/WebCore/css/SelectorChecker.h	2012-10-11 03:06:24 UTC (rev 131001)
+++ trunk/Source/WebCore/css/SelectorChecker.h	2012-10-11 03:07:32 UTC (rev 131002)
@@ -81,24 +81,23 @@
         bool hasSelectionPseudo;
     };
 
-    template<typename Context>
-    struct DOMTraversalStrategy {
-        static bool isFirstChild(const Context&, Element*);
-        static bool isLastChild(const Context&, Element*);
-        static bool isFirstOfType(const Context&, Element*, const QualifiedName&);
-        static bool isLastOfType(const Context&, Element*, const QualifiedName&);
+    class DOMSiblingTraversalStrategy {
+    public:
+        bool isFirstChild(Element*) const;
+        bool isLastChild(Element*) const;
+        bool isFirstOfType(Element*, const QualifiedName&) const;
+        bool isLastOfType(Element*, const QualifiedName&) const;
 
-        static int countElementsBefore(const Context&, Element*);
-        static int countElementsAfter(const Context&, Element*);
-        static int countElementsOfTypeBefore(const Context&, Element*, const QualifiedName&);
-        static int countElementsOfTypeAfter(const Context&, Element*, const QualifiedName&);
+        int countElementsBefore(Element*) const;
+        int countElementsAfter(Element*) const;
+        int countElementsOfTypeBefore(Element*, const QualifiedName&) const;
+        int countElementsOfTypeAfter(Element*, const QualifiedName&) const;
     };
 
     bool checkSelector(CSSSelector*, Element*, bool isFastCheckableSelector = false) const;
-    template<typename CheckingContext>
-    SelectorMatch checkSelector(const CheckingContext&, PseudoId&, bool& hasUnknownPseudoElements) const;
-    template<typename CheckingContext>
-    bool checkOneSelector(const CheckingContext&) const;
+    SelectorMatch checkSelector(const SelectorCheckingContext&, PseudoId&, bool& hasUnknownPseudoElements) const;
+    template<typename SiblingTraversalStrategy>
+    bool checkOneSelector(const SelectorCheckingContext&, const SiblingTraversalStrategy&) const;
 
     static bool isFastCheckableSelector(const CSSSelector*);
     bool fastCheckSelector(const CSSSelector*, const Element*) const;
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to