Title: [207854] trunk/Source/WebCore
Revision
207854
Author
[email protected]
Date
2016-10-25 16:21:03 -0700 (Tue, 25 Oct 2016)

Log Message

[CSS Parser] Improvements to selector parsing
https://bugs.webkit.org/show_bug.cgi?id=163964

Reviewed by Zalan Bujtas.

* css/CSSSelector.cpp:
(WebCore::CSSSelector::setAttribute):
(WebCore::CSSSelector::setNth):
* css/CSSSelector.h:
(WebCore::CSSSelector::setAttributeValueMatchingIsCaseInsensitive):
* css/StyleSheetContents.cpp:
(WebCore::StyleSheetContents::StyleSheetContents):
(WebCore::StyleSheetContents::parserAppendRule):
(WebCore::StyleSheetContents::ruleAt):
(WebCore::StyleSheetContents::ruleCount):
(WebCore::StyleSheetContents::clearRules):
(WebCore::StyleSheetContents::wrapperInsertRule):
(WebCore::StyleSheetContents::wrapperDeleteRule):
* css/StyleSheetContents.h:
* css/parser/CSSParser.cpp:
(WebCore::CSSParserContext::CSSParserContext):
(WebCore::CSSParser::parseSelector):
* css/parser/CSSParserValues.h:
(WebCore::CSSParserSelector::setAttribute):
(WebCore::CSSParserSelector::setArgument):
(WebCore::CSSParserSelector::setNth):
* css/parser/CSSSelectorParser.cpp:
(WebCore::consumeLangArgumentList):
(WebCore::CSSSelectorParser::consumeCompoundSelector):
(WebCore::CSSSelectorParser::consumeAttribute):
(WebCore::isPseudoClassFunction):
(WebCore::isPseudoElementFunction):
(WebCore::CSSSelectorParser::consumePseudo):
(WebCore::CSSSelectorParser::consumeCombinator):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (207853 => 207854)


--- trunk/Source/WebCore/ChangeLog	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/ChangeLog	2016-10-25 23:21:03 UTC (rev 207854)
@@ -1,3 +1,40 @@
+2016-10-25  Dave Hyatt  <[email protected]>
+
+        [CSS Parser] Improvements to selector parsing
+        https://bugs.webkit.org/show_bug.cgi?id=163964
+
+        Reviewed by Zalan Bujtas.
+
+        * css/CSSSelector.cpp:
+        (WebCore::CSSSelector::setAttribute):
+        (WebCore::CSSSelector::setNth):
+        * css/CSSSelector.h:
+        (WebCore::CSSSelector::setAttributeValueMatchingIsCaseInsensitive):
+        * css/StyleSheetContents.cpp:
+        (WebCore::StyleSheetContents::StyleSheetContents):
+        (WebCore::StyleSheetContents::parserAppendRule):
+        (WebCore::StyleSheetContents::ruleAt):
+        (WebCore::StyleSheetContents::ruleCount):
+        (WebCore::StyleSheetContents::clearRules):
+        (WebCore::StyleSheetContents::wrapperInsertRule):
+        (WebCore::StyleSheetContents::wrapperDeleteRule):
+        * css/StyleSheetContents.h:
+        * css/parser/CSSParser.cpp:
+        (WebCore::CSSParserContext::CSSParserContext):
+        (WebCore::CSSParser::parseSelector):
+        * css/parser/CSSParserValues.h:
+        (WebCore::CSSParserSelector::setAttribute):
+        (WebCore::CSSParserSelector::setArgument):
+        (WebCore::CSSParserSelector::setNth):
+        * css/parser/CSSSelectorParser.cpp:
+        (WebCore::consumeLangArgumentList):
+        (WebCore::CSSSelectorParser::consumeCompoundSelector):
+        (WebCore::CSSSelectorParser::consumeAttribute):
+        (WebCore::isPseudoClassFunction):
+        (WebCore::isPseudoElementFunction):
+        (WebCore::CSSSelectorParser::consumePseudo):
+        (WebCore::CSSSelectorParser::consumeCombinator):
+
 2016-10-25  Beth Dakin  <[email protected]>
 
         Numbered list should be represented without ‘…’

Modified: trunk/Source/WebCore/css/CSSSelector.cpp (207853 => 207854)


--- trunk/Source/WebCore/css/CSSSelector.cpp	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/CSSSelector.cpp	2016-10-25 23:21:03 UTC (rev 207854)
@@ -763,6 +763,14 @@
     m_data.m_rareData->m_attributeCanonicalLocalName = isCaseInsensitive ? value.localName().convertToASCIILowercase() : value.localName();
 }
 
+void CSSSelector::setAttribute(const QualifiedName& value, bool convertToLowercase, AttributeMatchType matchType)
+{
+    createRareData();
+    m_data.m_rareData->m_attribute = value;
+    m_data.m_rareData->m_attributeCanonicalLocalName = convertToLowercase ? value.localName().convertToASCIILowercase() : value.localName();
+    m_caseInsensitiveAttributeValueMatching = matchType == CaseInsensitive;
+}
+    
 void CSSSelector::setArgument(const AtomicString& value)
 {
     createRareData();
@@ -781,6 +789,16 @@
     m_data.m_rareData->m_selectorList = WTFMove(selectorList);
 }
 
+void CSSSelector::setNth(int a, int b)
+{
+    createRareData();
+    m_parsedNth = true; // FIXME-NEWPARSER: Can remove this parsed boolean once old parser is gone.
+    m_data.m_rareData->m_a = a;
+    m_data.m_rareData->m_b = b;
+}
+    
+// FIXME-NEWPARSER: All the code to parse nth-child stuff can be removed when
+// the new parser is enabled.
 bool CSSSelector::parseNth() const
 {
     if (!m_hasRareData)

Modified: trunk/Source/WebCore/css/CSSSelector.h (207853 => 207854)


--- trunk/Source/WebCore/css/CSSSelector.h	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/CSSSelector.h	2016-10-25 23:21:03 UTC (rev 207854)
@@ -244,9 +244,13 @@
         const CSSSelectorList* selectorList() const { return m_hasRareData ? m_data.m_rareData->m_selectorList.get() : nullptr; }
 
         void setValue(const AtomicString&);
-        void setAttribute(const QualifiedName&, bool isCaseInsensitive);
+        
+        // FIXME-NEWPARSER: These two methods can go away once the old parser is gone.
+        void setAttribute(const QualifiedName&, bool);
+        void setAttributeValueMatchingIsCaseInsensitive(bool);
+        void setAttribute(const QualifiedName&, bool convertToLowercase, AttributeMatchType);
+        void setNth(int a, int b);
         void setArgument(const AtomicString&);
-        void setAttributeValueMatchingIsCaseInsensitive(bool);
         void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>);
         void setSelectorList(std::unique_ptr<CSSSelectorList>);
 
@@ -585,7 +589,7 @@
     ASSERT(isAttributeSelector() && match() != CSSSelector::Set);
     m_caseInsensitiveAttributeValueMatching = isCaseInsensitive;
 }
-
+    
 inline bool CSSSelector::attributeValueMatchingIsCaseInsensitive() const
 {
     return m_caseInsensitiveAttributeValueMatching;

Modified: trunk/Source/WebCore/css/StyleSheetContents.cpp (207853 => 207854)


--- trunk/Source/WebCore/css/StyleSheetContents.cpp	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/StyleSheetContents.cpp	2016-10-25 23:21:03 UTC (rev 207854)
@@ -80,6 +80,7 @@
     , m_originalURL(o.m_originalURL)
     , m_encodingFromCharsetRule(o.m_encodingFromCharsetRule)
     , m_importRules(o.m_importRules.size())
+    , m_namespaceRules(o.m_namespaceRules.size())
     , m_childRules(o.m_childRules.size())
     , m_namespaces(o.m_namespaces)
     , m_defaultNamespace(o.m_defaultNamespace)
@@ -142,6 +143,16 @@
         return;
     }
 
+    if (is<StyleRuleNamespace>(rule)) {
+        // Parser enforces that @namespace rules come before all rules other than
+        // import/charset rules
+        ASSERT(m_childRules.isEmpty());
+        StyleRuleNamespace& namespaceRule = downcast<StyleRuleNamespace>(rule.get());
+        parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri());
+        m_namespaceRules.append(downcast<StyleRuleNamespace>(rule.ptr()));
+        return;
+    }
+
     if (is<StyleRuleMedia>(rule))
         reportMediaQueryWarningIfNeeded(singleOwnerDocument(), downcast<StyleRuleMedia>(rule.get()).mediaQueries());
 
@@ -164,6 +175,12 @@
         return m_importRules[childVectorIndex].get();
 
     childVectorIndex -= m_importRules.size();
+    
+    if (childVectorIndex < m_namespaceRules.size())
+        return m_namespaceRules[childVectorIndex].get();
+    
+    childVectorIndex -= m_namespaceRules.size();
+    
     return m_childRules[childVectorIndex].get();
 }
 
@@ -171,6 +188,7 @@
 {
     unsigned result = 0;
     result += m_importRules.size();
+    result += m_namespaceRules.size();
     result += m_childRules.size();
     return result;
 }
@@ -187,6 +205,7 @@
         m_importRules[i]->clearParentStyleSheet();
     }
     m_importRules.clear();
+    m_namespaceRules.clear();
     m_childRules.clear();
     clearCharsetRule();
 }
@@ -221,6 +240,31 @@
         return false;
     childVectorIndex -= m_importRules.size();
 
+    
+    if (childVectorIndex < m_namespaceRules.size() || (childVectorIndex == m_namespaceRules.size() && rule->isNamespaceRule())) {
+        // Inserting non-namespace rules other than import rule before @namespace is
+        // not allowed.
+        if (!is<StyleRuleNamespace>(rule))
+            return false;
+        // Inserting @namespace rule when rules other than import/namespace/charset
+        // are present is not allowed.
+        if (!m_childRules.isEmpty())
+            return false;
+        
+        StyleRuleNamespace& namespaceRule = downcast<StyleRuleNamespace>(rule.get());
+        m_namespaceRules.insert(index, downcast<StyleRuleNamespace>(rule.ptr()));
+        
+        // For now to be compatible with IE and Firefox if a namespace rule with the same
+        // prefix is added, it overwrites previous ones.
+        // FIXME: The eventual correct behavior would be to ensure that the last value in
+        // the list wins.
+        parserAddNamespace(namespaceRule.prefix(), namespaceRule.uri());
+        return true;
+    }
+    if (is<StyleRuleNamespace>(rule))
+        return false;
+    childVectorIndex -= m_namespaceRules.size();
+
     // If the number of selectors would overflow RuleData, we drop the operation.
     if (is<StyleRule>(rule) && downcast<StyleRule>(rule.get()).selectorList().componentCount() > RuleData::maximumSelectorComponentCount)
         return false;
@@ -242,6 +286,14 @@
     }
     childVectorIndex -= m_importRules.size();
 
+    if (childVectorIndex < m_namespaceRules.size()) {
+        if (!m_childRules.isEmpty())
+            return;
+        m_namespaceRules.remove(childVectorIndex);
+        return;
+    }
+    childVectorIndex -= m_namespaceRules.size();
+
     m_childRules.remove(childVectorIndex);
 }
 

Modified: trunk/Source/WebCore/css/StyleSheetContents.h (207853 => 207854)


--- trunk/Source/WebCore/css/StyleSheetContents.h	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/StyleSheetContents.h	2016-10-25 23:21:03 UTC (rev 207854)
@@ -41,6 +41,7 @@
 class SecurityOrigin;
 class StyleRuleBase;
 class StyleRuleImport;
+class StyleRuleNamespace;
 
 class StyleSheetContents final : public RefCounted<StyleSheetContents> {
 public:
@@ -104,6 +105,7 @@
     // Rules other than @charset and @import.
     const Vector<RefPtr<StyleRuleBase>>& childRules() const { return m_childRules; }
     const Vector<RefPtr<StyleRuleImport>>& importRules() const { return m_importRules; }
+    const Vector<RefPtr<StyleRuleNamespace>>& namespaceRules() const { return m_namespaceRules; }
 
     void notifyLoadedSheet(const CachedCSSStyleSheet*);
     
@@ -154,6 +156,7 @@
 
     String m_encodingFromCharsetRule;
     Vector<RefPtr<StyleRuleImport>> m_importRules;
+    Vector<RefPtr<StyleRuleNamespace>> m_namespaceRules;
     Vector<RefPtr<StyleRuleBase>> m_childRules;
     typedef HashMap<AtomicString, AtomicString> PrefixNamespaceURIMap;
     PrefixNamespaceURIMap m_namespaces;

Modified: trunk/Source/WebCore/css/parser/CSSParser.cpp (207853 => 207854)


--- trunk/Source/WebCore/css/parser/CSSParser.cpp	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParser.cpp	2016-10-25 23:21:03 UTC (rev 207854)
@@ -64,9 +64,11 @@
 #include "CSSReflectValue.h"
 #include "CSSRevertValue.h"
 #include "CSSSelector.h"
+#include "CSSSelectorParser.h"
 #include "CSSShadowValue.h"
 #include "CSSStyleSheet.h"
 #include "CSSTimingFunctionValue.h"
+#include "CSSTokenizer.h"
 #include "CSSUnicodeRangeValue.h"
 #include "CSSUnsetValue.h"
 #include "CSSValueKeywords.h"
@@ -1411,8 +1413,14 @@
 
 void CSSParser::parseSelector(const String& string, CSSSelectorList& selectorList)
 {
+    if (m_context.useNewParser && m_context.mode != UASheetMode) {
+        CSSTokenizer::Scope scope(string);
+        selectorList = CSSSelectorParser::parseSelector(scope.tokenRange(), m_context, nullptr);
+        return;
+    }
+
     m_selectorListForParseSelector = &selectorList;
-
+    
     setupParser("@-webkit-selector{", string, "}");
 
     cssyyparse(this);

Modified: trunk/Source/WebCore/css/parser/CSSParserValues.cpp (207853 => 207854)


--- trunk/Source/WebCore/css/parser/CSSParserValues.cpp	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParserValues.cpp	2016-10-25 23:21:03 UTC (rev 207854)
@@ -410,7 +410,13 @@
         argumentList->append(languageArgument);
     m_selector->setLangArgumentList(WTFMove(argumentList));
 }
-    
+
+void CSSParserSelector::setLangArgumentList(std::unique_ptr<Vector<AtomicString>> argumentList)
+{
+    ASSERT_WITH_MESSAGE(!argumentList->isEmpty(), "No CSS Selector takes an empty argument list.");
+    m_selector->setLangArgumentList(WTFMove(argumentList));
+}
+
 void CSSParserSelector::setSelectorList(std::unique_ptr<CSSSelectorList> selectorList)
 {
     m_selector->setSelectorList(WTFMove(selectorList));

Modified: trunk/Source/WebCore/css/parser/CSSParserValues.h (207853 => 207854)


--- trunk/Source/WebCore/css/parser/CSSParserValues.h	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSParserValues.h	2016-10-25 23:21:03 UTC (rev 207854)
@@ -222,9 +222,15 @@
     std::unique_ptr<CSSSelector> releaseSelector() { return WTFMove(m_selector); }
 
     void setValue(const AtomicString& value) { m_selector->setValue(value); }
+    
+    // FIXME-NEWPARSER: These two methods can go away once old parser is gone.
     void setAttribute(const QualifiedName& value, bool isCaseInsensitive) { m_selector->setAttribute(value, isCaseInsensitive); }
+    void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
+    
+    void setAttribute(const QualifiedName& value, bool convertToLowercase, CSSSelector::AttributeMatchType type) { m_selector->setAttribute(value, convertToLowercase, type); }
+    
     void setArgument(const AtomicString& value) { m_selector->setArgument(value); }
-    void setAttributeValueMatchingIsCaseInsensitive(bool isCaseInsensitive) { m_selector->setAttributeValueMatchingIsCaseInsensitive(isCaseInsensitive); }
+    void setNth(int a, int b) { m_selector->setNth(a, b); }
     void setMatch(CSSSelector::Match value) { m_selector->setMatch(value); }
     void setRelation(CSSSelector::RelationType value) { m_selector->setRelation(value); }
     void setForPage() { m_selector->setForPage(); }
@@ -235,6 +241,7 @@
 
     void adoptSelectorVector(Vector<std::unique_ptr<CSSParserSelector>>& selectorVector);
     void setLangArgumentList(const Vector<CSSParserString>& stringVector);
+    void setLangArgumentList(std::unique_ptr<Vector<AtomicString>>);
     void setSelectorList(std::unique_ptr<CSSSelectorList>);
 
     void setPseudoClassValue(const CSSParserString& pseudoClassString);

Modified: trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp (207853 => 207854)


--- trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp	2016-10-25 23:01:18 UTC (rev 207853)
+++ trunk/Source/WebCore/css/parser/CSSSelectorParser.cpp	2016-10-25 23:21:03 UTC (rev 207854)
@@ -100,6 +100,28 @@
     return list;
 }
 
+static bool consumeLangArgumentList(std::unique_ptr<Vector<AtomicString>>& argumentList, CSSParserTokenRange& range)
+{
+    const CSSParserToken& ident = range.consumeIncludingWhitespace();
+    if (ident.type() != IdentToken && ident.type() != StringToken)
+        return false;
+    StringView string = ident.value();
+    if (string.startsWith("--"))
+        return false;
+    argumentList->append(string.toAtomicString());
+    while (!range.atEnd() && range.peek().type() == CommaToken) {
+        range.consumeIncludingWhitespace();
+        const CSSParserToken& ident = range.consumeIncludingWhitespace();
+        if (ident.type() != IdentToken && ident.type() != StringToken)
+            return false;
+        StringView string = ident.value();
+        if (string.startsWith("--"))
+            return false;
+        argumentList->append(string.toAtomicString());
+    }
+    return range.atEnd();
+}
+
 namespace {
 
 enum CompoundSelectorFlags {
@@ -257,8 +279,6 @@
         if (compoundSelector->match() == CSSSelector::PseudoElement)
             compoundPseudoElement = compoundSelector->pseudoElementType();
     }
-    if (m_context.isHTMLDocument)
-        elementName = elementName.convertToASCIILowercase();
 
     while (std::unique_ptr<CSSParserSelector> simpleSelector = consumeSimpleSelector(range)) {
         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=161747
@@ -400,9 +420,6 @@
         return nullptr;
     block.consumeWhitespace();
 
-    if (m_context.isHTMLDocument)
-        attributeName = attributeName.convertToASCIILowercase();
-
     AtomicString namespaceURI = determineNamespace(namespacePrefix);
     if (namespaceURI.isNull())
         return nullptr;
@@ -414,7 +431,7 @@
     std::unique_ptr<CSSParserSelector> selector = std::unique_ptr<CSSParserSelector>(new CSSParserSelector());
 
     if (block.atEnd()) {
-        selector->setAttribute(qualifiedName, CSSSelector::CaseSensitive);
+        selector->setAttribute(qualifiedName, m_context.isHTMLDocument, CSSSelector::CaseSensitive);
         selector->setMatch(CSSSelector::Set);
         return selector;
     }
@@ -425,7 +442,8 @@
     if (attributeValue.type() != IdentToken && attributeValue.type() != StringToken)
         return nullptr;
     selector->setValue(attributeValue.value().toAtomicString());
-    selector->setAttribute(qualifiedName, consumeAttributeFlags(block));
+    
+    selector->setAttribute(qualifiedName, m_context.isHTMLDocument, consumeAttributeFlags(block));
 
     if (!block.atEnd())
         return nullptr;
@@ -432,6 +450,41 @@
     return selector;
 }
 
+static bool isPseudoClassFunction(CSSSelector::PseudoClassType pseudoClassType)
+{
+    switch (pseudoClassType) {
+    case CSSSelector::PseudoClassNot:
+    case CSSSelector::PseudoClassMatches:
+    case CSSSelector::PseudoClassNthChild:
+    case CSSSelector::PseudoClassNthLastChild:
+    case CSSSelector::PseudoClassNthOfType:
+    case CSSSelector::PseudoClassNthLastOfType:
+    case CSSSelector::PseudoClassLang:
+    case CSSSelector::PseudoClassAny:
+    case CSSSelector::PseudoClassHost:
+#if ENABLE_CSS_SELECTORS_LEVEL4
+    case CSSSelector::PseudoClassDir:
+    case CSSSelector::PseudoClassRole:
+#endif
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+    
+static bool isPseudoElementFunction(CSSSelector::PseudoElementType pseudoElementType)
+{
+    switch (pseudoElementType) {
+    case CSSSelector::PseudoElementCue:
+    case CSSSelector::PseudoElementSlotted:
+        return true;
+    default:
+        break;
+    }
+    return false;
+}
+
 std::unique_ptr<CSSParserSelector> CSSSelectorParser::consumePseudo(CSSParserTokenRange& range)
 {
     ASSERT(range.peek().type() == ColonToken);
@@ -459,7 +512,8 @@
 
     if (token.type() == IdentToken) {
         range.consume();
-        if ((selector->match() == CSSSelector::PseudoElement && selector->pseudoElementType() == CSSSelector::PseudoElementUnknown) || (selector->match() == CSSSelector::PseudoClass && selector->pseudoClassType() == CSSSelector::PseudoClassUnknown))
+        if ((selector->match() == CSSSelector::PseudoElement && (selector->pseudoElementType() == CSSSelector::PseudoElementUnknown || isPseudoElementFunction(selector->pseudoElementType())))
+            || (selector->match() == CSSSelector::PseudoClass && (selector->pseudoClassType() == CSSSelector::PseudoClassUnknown || isPseudoClassFunction(selector->pseudoClassType()))))
             return nullptr;
         return selector;
     }
@@ -469,78 +523,112 @@
     if (token.type() != FunctionToken)
         return nullptr;
 
-    switch (selector->pseudoClassType()) {
-    case CSSSelector::PseudoClassNot: {
-        std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block);
-        block.consumeWhitespace();
-        if (!innerSelector || !block.atEnd())
-            return nullptr;
-        Vector<std::unique_ptr<CSSParserSelector>> selectorVector;
-        selectorVector.append(WTFMove(innerSelector));
-        selector->adoptSelectorVector(selectorVector);
-        return selector;
-    }
-    case CSSSelector::PseudoClassNthChild:
-    case CSSSelector::PseudoClassNthLastChild:
-    case CSSSelector::PseudoClassNthOfType:
-    case CSSSelector::PseudoClassNthLastOfType: {
-        std::pair<int, int> ab;
-        if (!consumeANPlusB(block, ab))
-            return nullptr;
-        block.consumeWhitespace();
-        if (!block.atEnd())
-            return nullptr;
-        selector->setArgument(AtomicString::number(ab.first * ab.second));
-        return selector;
-    }
-    case CSSSelector::PseudoClassLang: {
-        // FIXME: CSS Selectors Level 4 allows :lang(*-foo)
-        const CSSParserToken& ident = block.consumeIncludingWhitespace();
-        if (ident.type() != IdentToken || !block.atEnd())
-            return nullptr;
-        selector->setArgument(ident.value().toAtomicString());
-        return selector;
-    }
-    // FIXME-NEWPARSER: Support :host-context
-    case CSSSelector::PseudoClassAny:
-    case CSSSelector::PseudoClassHost: {
-        DisallowPseudoElementsScope scope(this);
-        std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
-        *selectorList = consumeCompoundSelectorList(block);
-        if (!selectorList->isValid() || !block.atEnd())
-            return nullptr;
-        selector->setSelectorList(WTFMove(selectorList));
-        return selector;
-    }
-    default:
-        break;
-    }
+    if (selector->match() == CSSSelector::PseudoClass) {
+        switch (selector->pseudoClassType()) {
+        case CSSSelector::PseudoClassNot: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
+            *selectorList = consumeComplexSelectorList(block);
+            if (!selectorList->componentCount() || !block.atEnd())
+                return nullptr;
+            selector->setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        case CSSSelector::PseudoClassNthChild:
+        case CSSSelector::PseudoClassNthLastChild:
+        case CSSSelector::PseudoClassNthOfType:
+        case CSSSelector::PseudoClassNthLastOfType: {
+            std::pair<int, int> ab;
+            if (!consumeANPlusB(block, ab))
+                return nullptr;
+            block.consumeWhitespace();
+            if (!block.atEnd()) {
+                if (block.peek().type() != IdentToken)
+                    return nullptr;
+                const CSSParserToken& ident = block.consume();
+                if (!equalIgnoringASCIICase(ident.value(), "of"))
+                    return nullptr;
+                DisallowPseudoElementsScope scope(this);
+                block.consumeWhitespace();
+                std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
+                *selectorList = consumeComplexSelectorList(block);
+                if (!selectorList->componentCount() || !block.atEnd())
+                    return nullptr;
+                selector->setSelectorList(WTFMove(selectorList));
+            }
+            selector->setNth(ab.first, ab.second);
+            return selector;
+        }
+        case CSSSelector::PseudoClassLang: {
+            // FIXME: CSS Selectors Level 4 allows :lang(*-foo)
+            auto argumentList = std::make_unique<Vector<AtomicString>>();
+            if (!consumeLangArgumentList(argumentList, block))
+                return nullptr;
+            selector->setLangArgumentList(WTFMove(argumentList));
+            return selector;
+        }
+        case CSSSelector::PseudoClassMatches: {
+            std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
+            *selectorList = consumeComplexSelectorList(block);
+            if (!selectorList->componentCount() || !block.atEnd())
+                return nullptr;
+            selector->setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        // FIXME-NEWPARSER: Support :host-context
+        case CSSSelector::PseudoClassAny:
+        case CSSSelector::PseudoClassHost: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
+            *selectorList = consumeCompoundSelectorList(block);
+            if (!selectorList->componentCount() || !block.atEnd())
+                return nullptr;
+            selector->setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+#if ENABLE_CSS_SELECTORS_LEVEL4
+        case CSSSelector::PseudoClassDir:
+        case CSSSelector::PseudoClassRole: {
+            const CSSParserToken& ident = block.consumeIncludingWhitespace();
+            if (ident.type() != IdentToken)
+                return nullptr;
+            selector->setArgument(ident.value().toAtomicString());
+            return selector;
+        }
+#endif
+        default:
+            break;
+        }
 
-    switch (selector->pseudoElementType()) {
-    case CSSSelector::PseudoElementCue: {
-        DisallowPseudoElementsScope scope(this);
-        std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
-        *selectorList = consumeCompoundSelectorList(block);
-        if (!selectorList->isValid() || !block.atEnd())
-            return nullptr;
-        selector->setSelectorList(WTFMove(selectorList));
-        return selector;
     }
-    case CSSSelector::PseudoElementSlotted: {
-        DisallowPseudoElementsScope scope(this);
+    
+    if (selector->match() == CSSSelector::PseudoElement) {
+        switch (selector->pseudoElementType()) {
+        case CSSSelector::PseudoElementCue: {
+            DisallowPseudoElementsScope scope(this);
+            std::unique_ptr<CSSSelectorList> selectorList = std::unique_ptr<CSSSelectorList>(new CSSSelectorList());
+            *selectorList = consumeCompoundSelectorList(block);
+            if (!selectorList->isValid() || !block.atEnd())
+                return nullptr;
+            selector->setSelectorList(WTFMove(selectorList));
+            return selector;
+        }
+        case CSSSelector::PseudoElementSlotted: {
+            DisallowPseudoElementsScope scope(this);
 
-        std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block);
-        block.consumeWhitespace();
-        if (!innerSelector || !block.atEnd())
-            return nullptr;
-        Vector<std::unique_ptr<CSSParserSelector>> selectorVector;
-        selectorVector.append(WTFMove(innerSelector));
-        selector->adoptSelectorVector(selectorVector);
-        return selector;
+            std::unique_ptr<CSSParserSelector> innerSelector = consumeCompoundSelector(block);
+            block.consumeWhitespace();
+            if (!innerSelector || !block.atEnd())
+                return nullptr;
+            Vector<std::unique_ptr<CSSParserSelector>> selectorVector;
+            selectorVector.append(WTFMove(innerSelector));
+            selector->adoptSelectorVector(selectorVector);
+            return selector;
+        }
+        default:
+            break;
+        }
     }
-    default:
-        break;
-    }
 
     return nullptr;
 }
@@ -564,6 +652,13 @@
             return CSSSelector::DirectAdjacent;
         if (delimiter == '~')
             return CSSSelector::IndirectAdjacent;
+#if ENABLE_CSS_SELECTORS_LEVEL4
+        // FIXME-NEWPARSER: Need to set that this was a >> so serialization is correct
+        if (delimiter == '>' && range.peek().type() == DelimiterToken && range.peek().delimiter() == '>') {
+            range.consumeIncludingWhitespace();
+            return CSSSelector::Descendant;
+        }
+#endif
         return CSSSelector::Child;
     }
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to