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;
}