haikuwebkit/LayoutTests/fast/css/tagname-case-sensitivity-sv...

44 lines
1.3 KiB
HTML
Raw Permalink Normal View History

Fix CSS Selector's tag name matching when mixing HTML and XML https://bugs.webkit.org/show_bug.cgi?id=140878 Reviewed by Darin Adler. Source/WebCore: Previsouly, WebKit was unable to match any XML element that had any uppercase character if the stylesheet was in a HTML document. This problem was most often reported due to the inability to style SVG-in-HTML. The reason was that the tag local name was incorrectly transformed to lowercase at parsing time. Instead, we are supposed to only do case-insensitive match for HTML elements in a HTML document. This fix is very similar with how we handle attributes: -Keep both the original and the lowercase versions of the name. -When matching, chose which version to use depending on the element being matched. There is one major difference in the way the names are stored. Unlike attribute selectors, tag name selectors are common, and the uppercase version is not that uncommon. I wanted to preserve the dense representation so I specialized CSSSelector specifically for tag names. To store the data, if the name is already lowercase, just use the m_data pointer as usual. If the name is not lowercase, allocate a new small structure in the union to store both names. Tests: fast/css/tagname-and-namespace-case-sensitivity-xml-in-html.html fast/css/tagname-and-namespace-case-sensitivity-xml-in-xhtml-expected.xhtml fast/css/tagname-and-namespace-case-sensitivity-xml-in-xhtml.xhtml fast/css/tagname-case-sensitivity-svg-in-html.html fast/css/tagname-case-sensitivity-svg-in-xhtml-expected.xhtml fast/css/tagname-case-sensitivity-svg-in-xhtml.xhtml fast/css/tagname-case-sensitivity-xml-in-html.html fast/css/tagname-case-sensitivity-xml-in-xhtml-expected.xhtml fast/css/tagname-case-sensitivity-xml-in-xhtml.xhtml fast/selectors/element-closest-tagname-case-sensitivity-svg-in-html.html fast/selectors/element-closest-tagname-case-sensitivity-svg-in-xhtml.xhtml fast/selectors/element-matches-tagname-case-sensitivity-svg-in-html.html fast/selectors/element-matches-tagname-case-sensitivity-svg-in-xhtml.xhtml fast/selectors/querySelector-tagname-case-sensitivity-svg-in-html.html fast/selectors/querySelector-tagname-case-sensitivity-svg-in-xhtml.xhtml fast/selectors/querySelector-tagname-case-sensitivity-xml-in-html.html fast/selectors/querySelector-tagname-case-sensitivity-xml-in-xhtml.xhtml fast/selectors/tagname-adjacent-backtracking-case-sensitivity-html.html fast/selectors/tagname-descendant-backtracking-case-sensitivity-html.html * css/CSSGrammar.y.in: The parser is unaware of anything case related. CSSSelector takes care of that. * css/CSSSelector.cpp: (WebCore::CSSSelector::CSSSelector): (WebCore::CSSSelector::createRareData): * css/CSSSelector.h: (WebCore::CSSSelector::NameWithCase::NameWithCase): (WebCore::CSSSelector::CSSSelector): (WebCore::CSSSelector::~CSSSelector): (WebCore::CSSSelector::tagQName): (WebCore::CSSSelector::tagLowercaseLocalName): The new representation stores both the original form and the lower case form. * css/RuleSet.cpp: (WebCore::RuleSet::addRule): (WebCore::RuleSet::shrinkToFit): * css/RuleSet.h: (WebCore::RuleSet::tagRules): * css/ElementRuleCollector.cpp: (WebCore::ElementRuleCollector::collectMatchingRules): The tag name partition is now split in two: lowercase and original case. If the matched element is HTML, the lowercase partition is used. * css/SelectorFilter.cpp: (WebCore::collectElementIdentifierHashes): (WebCore::collectDescendantSelectorIdentifierHashes): This is the most annoying part of the patch performance wise: the bloom filter knows the case of the real elements but it cannot know how selectors will match them. To make it work, all names are now converted to lowercase. That implies that we can filter less on XML and we may have to pay for converting the tag name to lowercase. I expect the performance hit to be small because: -Having two XML elements with the same name but different case is uncommon. -Most elements use lowercase names. Still sad...that's the price to pay for correctness. * css/SelectorChecker.cpp: (WebCore::tagMatches): (WebCore::SelectorChecker::checkOne): * css/SelectorChecker.h: (WebCore::SelectorChecker::tagMatches): Deleted. Update the legacy matcher, nothing special. * cssjit/SelectorCompiler.cpp: (WebCore::SelectorCompiler::SelectorFragment::SelectorFragment): (WebCore::SelectorCompiler::TagNamePattern::TagNamePattern): (WebCore::SelectorCompiler::constructFragmentsInternal): (WebCore::SelectorCompiler::equalTagNames): (WebCore::SelectorCompiler::equalTagNamePatterns): (WebCore::SelectorCompiler::computeBacktrackingStartOffsetInChain): (WebCore::SelectorCompiler::computeBacktrackingHeightFromDescendant): (WebCore::SelectorCompiler::computeBacktrackingWidthFromIndirectAdjacent): (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementMatching): (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementHasTagName): Tag names are used to optimize backtracking; this is quite common for descendant (e.g. div > ul > li). We have to differenciate one new case there: if two tag names are equal when compared case-insensitively but strictly different, they may still be equal if they don't match the same kind of elements or both matches and HTML element. * dom/SelectorQuery.cpp: (WebCore::localNameMatches): (WebCore::elementsForLocalName): (WebCore::SelectorDataList::executeSingleTagNameSelectorData): Update the inline versions of SelectorQuery. LayoutTests: We had very little coverage for XHTML and XML in HTML. I added lots of new tests to cover the basics. * fast/dom/css-dom-read-2-expected.txt: * fast/dom/css-dom-read-expected.txt: CSSOM now provide the tagname in the original case instead of lowercase, which is actually what the spec defines: "If the character is not handled by one of the above rules and is greater than or equal to U+0080, is "-" (U+002D) or "_" (U+005F), or is in one of the ranges [0-9] (U+0030 to U+0039), [A-Z] (U+0041 to U+005A), or [a-z] (U+0061 to U+007A), then the character itself." * fast/css/tagname-and-namespace-case-sensitivity-xml-in-html-expected.html: Added. * fast/css/tagname-and-namespace-case-sensitivity-xml-in-html.html: Added. * fast/css/tagname-and-namespace-case-sensitivity-xml-in-xhtml-expected.xhtml: Added. * fast/css/tagname-and-namespace-case-sensitivity-xml-in-xhtml.xhtml: Added. * fast/css/tagname-case-sensitivity-svg-in-html-expected.html: Added. * fast/css/tagname-case-sensitivity-svg-in-html.html: Added. * fast/css/tagname-case-sensitivity-svg-in-xhtml-expected.xhtml: Added. * fast/css/tagname-case-sensitivity-svg-in-xhtml.xhtml: Added. * fast/css/tagname-case-sensitivity-xml-in-html-expected.html: Added. * fast/css/tagname-case-sensitivity-xml-in-html.html: Added. * fast/css/tagname-case-sensitivity-xml-in-xhtml-expected.xhtml: Added. * fast/css/tagname-case-sensitivity-xml-in-xhtml.xhtml: Added. * fast/selectors/element-closest-tagname-case-sensitivity-svg-in-html-expected.txt: Added. * fast/selectors/element-closest-tagname-case-sensitivity-svg-in-html.html: Added. * fast/selectors/element-closest-tagname-case-sensitivity-svg-in-xhtml-expected.txt: Added. * fast/selectors/element-closest-tagname-case-sensitivity-svg-in-xhtml.xhtml: Added. * fast/selectors/element-matches-tagname-case-sensitivity-svg-in-html-expected.txt: Added. * fast/selectors/element-matches-tagname-case-sensitivity-svg-in-html.html: Added. * fast/selectors/element-matches-tagname-case-sensitivity-svg-in-xhtml-expected.txt: Added. * fast/selectors/element-matches-tagname-case-sensitivity-svg-in-xhtml.xhtml: Added. * fast/selectors/querySelector-tagname-case-sensitivity-svg-in-html-expected.txt: Added. * fast/selectors/querySelector-tagname-case-sensitivity-svg-in-html.html: Added. * fast/selectors/querySelector-tagname-case-sensitivity-svg-in-xhtml-expected.txt: Added. * fast/selectors/querySelector-tagname-case-sensitivity-svg-in-xhtml.xhtml: Added. * fast/selectors/querySelector-tagname-case-sensitivity-xml-in-html-expected.txt: Added. * fast/selectors/querySelector-tagname-case-sensitivity-xml-in-html.html: Added. * fast/selectors/querySelector-tagname-case-sensitivity-xml-in-xhtml-expected.txt: Added. * fast/selectors/querySelector-tagname-case-sensitivity-xml-in-xhtml.xhtml: Added. * fast/selectors/tagname-adjacent-backtracking-case-sensitivity-html-expected.txt: Added. * fast/selectors/tagname-adjacent-backtracking-case-sensitivity-html.html: Added. * fast/selectors/tagname-descendant-backtracking-case-sensitivity-html-expected.txt: Added. * fast/selectors/tagname-descendant-backtracking-case-sensitivity-html.html: Added. Canonical link: https://commits.webkit.org/158886@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@179132 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2015-01-26 20:40:18 +00:00
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style>
rect {
width: 100px;
height: 100px;
background-color: green;
border: 1px solid red;
display: block;
float: left;
stroke: purple;
fill: blue;
}
Rect {
stroke: purple;
border: 2px dashed lime;
}
RECT {
fill: yellow;
background-color: orange;
}
</style>
</head>
<body>
<p>Test styling of elements using their local name. Matching the name should always be case-sensitive for XHTML.</p>
<div id="test-cases">
<rect></rect>
<Rect></Rect>
<RECT></RECT>
<svg xmlns="http://www.w3.org/2000/svg">
<rect width="100" height="100"></rect>
<Rect x="100" width="100" height="100"></Rect>
<RECT x="200" width="100" height="100"></RECT>
</svg>
</div>
</body>
<script><![CDATA[
var svgDocument = new DOMParser().parseFromString('<svg xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100"></rect><Rect x="100" width="100" height="100"></Rect><RECT x="200" width="100" height="100"></RECT></svg>', 'text/xml');
var testCases = document.getElementById("test-cases");
testCases.appendChild(document.importNode(svgDocument.documentElement, true));
]]></script>
</html>