Index: Source/core/css/parser/CSSSelectorParser.cpp |
diff --git a/Source/core/css/parser/CSSSelectorParser.cpp b/Source/core/css/parser/CSSSelectorParser.cpp |
index cc7d7b28e231e95f76ce4ddabc486ea386bc2331..9ca42f231982aa90212eebaf7e2a89c3f8587666 100644 |
--- a/Source/core/css/parser/CSSSelectorParser.cpp |
+++ b/Source/core/css/parser/CSSSelectorParser.cpp |
@@ -5,6 +5,7 @@ |
#include "config.h" |
#include "core/css/parser/CSSSelectorParser.h" |
+#include "core/css/CSSLocalNameToLowerMaps.h" |
#include "core/css/CSSSelectorList.h" |
#include "core/css/StyleSheetContents.h" |
#include "core/frame/UseCounter.h" |
@@ -106,13 +107,18 @@ PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars |
AtomicString namespacePrefix; |
AtomicString elementName; |
bool hasNamespace; |
+ TagSelectorCase tagSelectorCase = TagLowerCase; |
if (!consumeName(range, elementName, namespacePrefix, hasNamespace)) { |
compoundSelector = consumeSimpleSelector(range); |
if (!compoundSelector) |
return nullptr; |
} |
- if (m_context.isHTMLDocument()) |
- elementName = elementName.lower(); |
+ if (m_context.isHTMLDocument() && !elementName.isNull()) { |
+ if (CSSLocalNameToLowerMaps::elementToLower(elementName).isNull()) |
+ elementName = elementName.lower(); |
+ else |
+ tagSelectorCase = TagCamelCase; |
+ } |
while (OwnPtr<CSSParserSelector> simpleSelector = consumeSimpleSelector(range)) { |
if (compoundSelector) |
@@ -123,10 +129,10 @@ PassOwnPtr<CSSParserSelector> CSSSelectorParser::consumeCompoundSelector(CSSPars |
if (!compoundSelector) { |
if (hasNamespace) |
- return CSSParserSelector::create(determineNameInNamespace(namespacePrefix, elementName)); |
- return CSSParserSelector::create(QualifiedName(nullAtom, elementName, m_defaultNamespace)); |
+ return CSSParserSelector::create(determineNameInNamespace(namespacePrefix, elementName), false, tagSelectorCase); |
+ return CSSParserSelector::create(QualifiedName(nullAtom, elementName, m_defaultNamespace), false, tagSelectorCase); |
} |
- prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.get()); |
+ prependTypeSelectorIfNeeded(namespacePrefix, elementName, compoundSelector.get(), tagSelectorCase); |
return compoundSelector.release(); |
} |
@@ -518,7 +524,7 @@ QualifiedName CSSSelectorParser::determineNameInNamespace(const AtomicString& pr |
return QualifiedName(prefix, localName, m_styleSheet->determineNamespace(prefix)); |
} |
-void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector) |
+void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespacePrefix, const AtomicString& elementName, CSSParserSelector* compoundSelector, TagSelectorCase tagSelectorCase) |
{ |
if (elementName.isNull() && m_defaultNamespace == starAtom && !compoundSelector->crossesTreeScopes()) |
return; |
@@ -528,19 +534,19 @@ void CSSSelectorParser::prependTypeSelectorIfNeeded(const AtomicString& namespac |
QualifiedName tag(namespacePrefix, determinedElementName, determinedNamespace); |
if (compoundSelector->crossesTreeScopes()) |
- return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compoundSelector, elementName.isNull()); |
+ return rewriteSpecifiersWithElementNameForCustomPseudoElement(tag, compoundSelector, elementName.isNull(), tagSelectorCase); |
if (compoundSelector->isContentPseudoElement()) |
- return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, compoundSelector, elementName.isNull()); |
+ return rewriteSpecifiersWithElementNameForContentPseudoElement(tag, compoundSelector, elementName.isNull(), tagSelectorCase); |
// *:host never matches, so we can't discard the * otherwise we can't tell the |
// difference between *:host and just :host. |
if (tag == anyQName() && !compoundSelector->hasHostPseudoSelector()) |
return; |
- compoundSelector->prependTagSelector(tag, elementName.isNull()); |
+ compoundSelector->prependTagSelector(tag, elementName.isNull(), tagSelectorCase); |
} |
-void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) |
+void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit, TagSelectorCase tagSelectorCase) |
{ |
CSSParserSelector* lastShadowPseudo = specifiers; |
CSSParserSelector* history = specifiers; |
@@ -552,18 +558,18 @@ void CSSSelectorParser::rewriteSpecifiersWithElementNameForCustomPseudoElement(c |
if (lastShadowPseudo->tagHistory()) { |
if (tag != anyQName()) |
- lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsImplicit); |
+ lastShadowPseudo->tagHistory()->prependTagSelector(tag, tagIsImplicit, tagSelectorCase); |
return; |
} |
// For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. |
// We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). |
- OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(tag); |
+ OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(tag, false /* isImplicit */, tagSelectorCase); |
lastShadowPseudo->setTagHistory(elementNameSelector.release()); |
lastShadowPseudo->setRelation(CSSSelector::ShadowPseudo); |
} |
-void CSSSelectorParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit) |
+void CSSSelectorParser::rewriteSpecifiersWithElementNameForContentPseudoElement(const QualifiedName& tag, CSSParserSelector* specifiers, bool tagIsImplicit, TagSelectorCase tagSelectorCase) |
{ |
CSSParserSelector* last = specifiers; |
CSSParserSelector* history = specifiers; |
@@ -575,13 +581,13 @@ void CSSSelectorParser::rewriteSpecifiersWithElementNameForContentPseudoElement( |
if (last->tagHistory()) { |
if (tag != anyQName()) |
- last->tagHistory()->prependTagSelector(tag, tagIsImplicit); |
+ last->tagHistory()->prependTagSelector(tag, tagIsImplicit, tagSelectorCase); |
return; |
} |
// For shadow-ID pseudo-elements to be correctly matched, the ShadowPseudo combinator has to be used. |
// We therefore create a new Selector with that combinator here in any case, even if matching any (host) element in any namespace (i.e. '*'). |
- OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(tag); |
+ OwnPtr<CSSParserSelector> elementNameSelector = CSSParserSelector::create(tag, false /* isImplicit */, tagSelectorCase); |
last->setTagHistory(elementNameSelector.release()); |
} |