Title: [181512] trunk
Revision
181512
Author
[email protected]
Date
2015-03-15 12:43:18 -0700 (Sun, 15 Mar 2015)

Log Message

Change the exact attribute matching to be ASCII case-insensitive
https://bugs.webkit.org/show_bug.cgi?id=142609

Patch by Benjamin Poulain <[email protected]> on 2015-03-15
Reviewed by Darin Adler.

Source/WebCore:

In CSS, testing attribute values should be ASCII case-insensitive,
previously we were using full unicode case conversion.

Test: fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html

* css/CSSParser.cpp:
(WebCore::CSSParser::parseKeyframeSelector):
The CSS parser has its own fast version for ASCII case insensitive.
This code was using the general equalIgnoringASCIICase() which was causing name conflicts,
change that to the normal CSS parser version.

* css/SelectorCheckerTestFunctions.h:
(WebCore::equalIgnoringASCIICase): Deleted.
* cssjit/SelectorCompiler.cpp:
(WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeValueExactMatching):

Source/WTF:

Add support for ASCII case insensitive comparisons to all the string
classes.

The new file StringCommon.h has the common algorithm to avoid repeating
the same code with different types.

* WTF.vcxproj/WTF.vcxproj:
* WTF.vcxproj/WTF.vcxproj.filters:
* wtf/ASCIICType.h:
(WTF::toASCIILower):
* wtf/CMakeLists.txt:
* wtf/text/AtomicString.h:
(WTF::equalIgnoringASCIICase):
* wtf/text/StringCommon.h: Added.
(WTF::equalIgnoringASCIICase):
(WTF::equalIgnoringASCIICaseCommon):
* wtf/text/StringImpl.cpp:
(WTF::equalIgnoringASCIICase):
(WTF::equalIgnoringASCIICaseNonNull):
(WTF::StringImpl::utf8Impl):
(WTF::StringImpl::defaultWritingDirection): Deleted.
(WTF::StringImpl::adopt): Deleted.
(WTF::StringImpl::sizeInBytes): Deleted.
(WTF::putUTF8Triple): Deleted.
(WTF::StringImpl::utf8): Deleted.
* wtf/text/StringImpl.h:
(WTF::StringImpl::isSubString): Deleted.
(WTF::find): Deleted.

Tools:

* TestWebKitAPI/Tests/WTF/StringImpl.cpp:
* TestWebKitAPI/Tests/WTF/StringView.cpp:

LayoutTests:

* fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive-expected.txt: Added.
* fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (181511 => 181512)


--- trunk/LayoutTests/ChangeLog	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/LayoutTests/ChangeLog	2015-03-15 19:43:18 UTC (rev 181512)
@@ -1,3 +1,13 @@
+2015-03-15  Benjamin Poulain  <[email protected]>
+
+        Change the exact attribute matching to be ASCII case-insensitive
+        https://bugs.webkit.org/show_bug.cgi?id=142609
+
+        Reviewed by Darin Adler.
+
+        * fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive-expected.txt: Added.
+        * fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html: Added.
+
 2015-03-15  Brent Fulgham  <[email protected]>
 
         [Win] Document more debug assertions for later review.

Added: trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive-expected.txt (0 => 181512)


--- trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive-expected.txt	2015-03-15 19:43:18 UTC (rev 181512)
@@ -0,0 +1,213 @@
+When matching attributes case insensitively, it should be ASCII case insensitive. This test verifies the behavior for exact value matching (e.g. [a="b"])
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Testing "[data-attribute=WebKit-É]"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É]').length is 1
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É]')[0].id is "target1"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=webkit-É]"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É]').length is 1
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É]')[0].id is "target2"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=WEBKIT-É]"
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É]').length is 1
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É]')[0].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=WebKit-é]"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-é]').length is 1
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-é]')[0].id is "target4"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=webkit-é]"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-é]').length is 1
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-é]')[0].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[data-attribute=WebKit-É i]"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É i]').length is 3
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-É i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=webkit-É i]"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É i]').length is 3
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-É i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=WEBKIT-É i]"
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]').length is 3
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[data-attribute=WebKit-é i]"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-é i]').length is 2
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-é i]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [data-attribute=WebKit-é i]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[data-attribute=webkit-é i]"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-é i]').length is 2
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-é i]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [data-attribute=webkit-é i]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[multiple=WEBKIT-é]"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=WebKit-é]"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=Webkit-é]"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=webkit-É]"
+PASS document.querySelectorAll('#test-root [multiple=webkit-É]').length is 2
+PASS document.querySelectorAll('#test-root [multiple=webkit-É]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [multiple=webkit-É]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[multiple=webKit-É]"
+PASS document.querySelectorAll('#test-root [multiple=webKit-É]').length is 2
+PASS document.querySelectorAll('#test-root [multiple=webKit-É]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [multiple=webKit-É]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[multiple=WEBKIT-é i]"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é i]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=WEBKIT-é i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=WebKit-é i]"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é i]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=WebKit-é i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=Webkit-é i]"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é i]').length is 3
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é i]')[0].id is "target1"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é i]')[1].id is "target2"
+PASS document.querySelectorAll('#test-root [multiple=Webkit-é i]')[2].id is "target3"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(255, 0, 0)"
+
+Testing "[multiple=webkit-É i]"
+PASS document.querySelectorAll('#test-root [multiple=webkit-É i]').length is 2
+PASS document.querySelectorAll('#test-root [multiple=webkit-É i]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [multiple=webkit-É i]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+Testing "[multiple=webKit-É i]"
+PASS document.querySelectorAll('#test-root [multiple=webKit-É i]').length is 2
+PASS document.querySelectorAll('#test-root [multiple=webKit-É i]')[0].id is "target4"
+PASS document.querySelectorAll('#test-root [multiple=webKit-É i]')[1].id is "target5"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor is "rgb(255, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor is "rgb(10, 100, 200)"
+PASS getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor is "rgb(10, 100, 200)"
+
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html (0 => 181512)


--- trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html	2015-03-15 19:43:18 UTC (rev 181512)
@@ -0,0 +1,85 @@
+<!doctype html>
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+<style>
+#test-root * {
+    background-color: red;
+}
+</style>
+<style id="style">
+</style>
+</head>
+<body>
+    <div style="display:none" id="test-root">
+        <div data-attribute="WebKit-É" multiple="WEBKIT-é" id="target1"></div>
+        <div data-attribute="webkit-É" multiple="WebKit-é" id="target2"></div>
+        <div data-attribute="WEBKIT-É" multiple="Webkit-é" id="target3"></div>
+        <div data-attribute="WebKit-é" multiple="webkit-É" id="target4"></div>
+        <div data-attribute="webkit-é" multiple="webKit-É" id="target5"></div>
+    </div>
+</body>
+<script>
+description('When matching attributes case insensitively, it should be ASCII case insensitive. This test verifies the behavior for exact value matching (e.g. [a="b"])');
+
+function testQuerySelector(selector, expectedIds) {
+    shouldBe("document.querySelectorAll('" + selector + "').length", '' + expectedIds.length);
+    for (var i = 0; i < expectedIds.length; ++i)
+        shouldBeEqualToString("document.querySelectorAll('" + selector + "')[" + i + "].id", 'target' + expectedIds[i]);
+}
+
+function testStyling(selector, expectedIds) {
+    var stylingElement = document.getElementById("style");
+    stylingElement.innerHTML = '' + selector + ' { background-color: rgb(10, 100, 200); }';
+
+    var allTestCases = document.querySelectorAll("#test-root *");
+    for (var i = 0; i < allTestCases.length; ++i) {
+        var expectMatch = expectedIds.indexOf(parseInt(allTestCases[i].id.replace('target', ''))) >= 0;
+        shouldBeEqualToString('getComputedStyle(document.querySelectorAll("#test-root *")[' + i + ']).backgroundColor', expectMatch ? 'rgb(10, 100, 200)' : 'rgb(255, 0, 0)');
+    }
+
+    stylingElement.innerHTML = '';
+}
+
+function testSelector(selector, expectedIds) {
+    debug("Testing \"" + selector + "\"");
+    testQuerySelector("#test-root " + selector, expectedIds);
+    testStyling("#test-root " + selector, expectedIds);
+    debug("");
+}
+
+var testCases = [
+    // Regular attribute matching is case sensitive.
+    ['[data-attribute=WebKit-É]', [1]],
+    ['[data-attribute=webkit-É]', [2]],
+    ['[data-attribute=WEBKIT-É]', [3]],
+    ['[data-attribute=WebKit-é]', [4]],
+    ['[data-attribute=webkit-é]', [5]],
+
+    // Same selectors with the case-insensitivie flag.
+    ['[data-attribute=WebKit-É i]', [1, 2, 3]],
+    ['[data-attribute=webkit-É i]', [1, 2, 3]],
+    ['[data-attribute=WEBKIT-É i]', [1, 2, 3]],
+    ['[data-attribute=WebKit-é i]', [4, 5]],
+    ['[data-attribute=webkit-é i]', [4, 5]],
+
+    // "multiple" is one of those weird legacy exception: it is always case insensitive in HTML.
+    ['[multiple=WEBKIT-é]', [1, 2, 3]],
+    ['[multiple=WebKit-é]', [1, 2, 3]],
+    ['[multiple=Webkit-é]', [1, 2, 3]],
+    ['[multiple=webkit-É]', [4, 5]],
+    ['[multiple=webKit-É]', [4, 5]],
+    ['[multiple=WEBKIT-é i]', [1, 2, 3]],
+    ['[multiple=WebKit-é i]', [1, 2, 3]],
+    ['[multiple=Webkit-é i]', [1, 2, 3]],
+    ['[multiple=webkit-É i]', [4, 5]],
+    ['[multiple=webKit-É i]', [4, 5]],
+];
+
+for (var testCase of testCases) {
+    testSelector(testCase[0], testCase[1]);
+}
+</script>
+<script src=""
+</html>

Modified: trunk/Source/WTF/ChangeLog (181511 => 181512)


--- trunk/Source/WTF/ChangeLog	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/ChangeLog	2015-03-15 19:43:18 UTC (rev 181512)
@@ -1,3 +1,39 @@
+2015-03-15  Benjamin Poulain  <[email protected]>
+
+        Change the exact attribute matching to be ASCII case-insensitive
+        https://bugs.webkit.org/show_bug.cgi?id=142609
+
+        Reviewed by Darin Adler.
+
+        Add support for ASCII case insensitive comparisons to all the string
+        classes.
+
+        The new file StringCommon.h has the common algorithm to avoid repeating
+        the same code with different types.
+
+        * WTF.vcxproj/WTF.vcxproj:
+        * WTF.vcxproj/WTF.vcxproj.filters:
+        * wtf/ASCIICType.h:
+        (WTF::toASCIILower):
+        * wtf/CMakeLists.txt:
+        * wtf/text/AtomicString.h:
+        (WTF::equalIgnoringASCIICase):
+        * wtf/text/StringCommon.h: Added.
+        (WTF::equalIgnoringASCIICase):
+        (WTF::equalIgnoringASCIICaseCommon):
+        * wtf/text/StringImpl.cpp:
+        (WTF::equalIgnoringASCIICase):
+        (WTF::equalIgnoringASCIICaseNonNull):
+        (WTF::StringImpl::utf8Impl):
+        (WTF::StringImpl::defaultWritingDirection): Deleted.
+        (WTF::StringImpl::adopt): Deleted.
+        (WTF::StringImpl::sizeInBytes): Deleted.
+        (WTF::putUTF8Triple): Deleted.
+        (WTF::StringImpl::utf8): Deleted.
+        * wtf/text/StringImpl.h:
+        (WTF::StringImpl::isSubString): Deleted.
+        (WTF::find): Deleted.
+
 2015-03-14  Michael Saboff  <[email protected]>
 
         Disable Yarr JIT for ARMv7k

Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj (181511 => 181512)


--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj	2015-03-15 19:43:18 UTC (rev 181512)
@@ -291,6 +291,7 @@
     <ClInclude Include="..\wtf\text\LChar.h" />
     <ClInclude Include="..\wtf\text\StringBuffer.h" />
     <ClInclude Include="..\wtf\text\StringBuilder.h" />
+    <ClInclude Include="..\wtf\text\StringCommon.h" />
     <ClInclude Include="..\wtf\text\StringConcatenate.h" />
     <ClInclude Include="..\wtf\text\StringHash.h" />
     <ClInclude Include="..\wtf\text\StringImpl.h" />

Modified: trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters (181511 => 181512)


--- trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/WTF.vcxproj/WTF.vcxproj.filters	2015-03-15 19:43:18 UTC (rev 181512)
@@ -327,6 +327,9 @@
     <ClInclude Include="..\wtf\text\StringBuilder.h">
       <Filter>text</Filter>
     </ClInclude>
+    <ClInclude Include="..\wtf\text\StringCommon.h">
+      <Filter>text</Filter>
+    </ClInclude>
     <ClInclude Include="..\wtf\text\StringConcatenate.h">
       <Filter>text</Filter>
     </ClInclude>

Modified: trunk/Source/WTF/WTF.xcodeproj/project.pbxproj (181511 => 181512)


--- trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/WTF.xcodeproj/project.pbxproj	2015-03-15 19:43:18 UTC (rev 181512)
@@ -73,6 +73,7 @@
 		2CDED0EF18115C38004DBA70 /* RunLoopCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CDED0EE18115C38004DBA70 /* RunLoopCF.cpp */; };
 		2CDED0F318115C85004DBA70 /* RunLoop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2CDED0F118115C85004DBA70 /* RunLoop.cpp */; };
 		2CDED0F418115C85004DBA70 /* RunLoop.h in Headers */ = {isa = PBXBuildFile; fileRef = 2CDED0F218115C85004DBA70 /* RunLoop.h */; };
+		430B47891AAAAC1A001223DA /* StringCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 430B47871AAAAC1A001223DA /* StringCommon.h */; };
 		7CBBA07419BB7FDC00BBF025 /* OSObjectPtr.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CBBA07319BB7FDC00BBF025 /* OSObjectPtr.h */; };
 		7CDD7FF8186D291E007433CD /* IteratorAdaptors.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CDD7FF7186D291E007433CD /* IteratorAdaptors.h */; };
 		7CDD7FFA186D2A54007433CD /* IteratorRange.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CDD7FF9186D2A54007433CD /* IteratorRange.h */; };
@@ -357,6 +358,7 @@
 		2CDED0EE18115C38004DBA70 /* RunLoopCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RunLoopCF.cpp; sourceTree = "<group>"; };
 		2CDED0F118115C85004DBA70 /* RunLoop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RunLoop.cpp; sourceTree = "<group>"; };
 		2CDED0F218115C85004DBA70 /* RunLoop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RunLoop.h; sourceTree = "<group>"; };
+		430B47871AAAAC1A001223DA /* StringCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StringCommon.h; sourceTree = "<group>"; };
 		5D247B6214689B8600E78B76 /* libWTF.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libWTF.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		5D247B6E14689C4700E78B76 /* Base.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Base.xcconfig; sourceTree = "<group>"; };
 		5D247B7014689C4700E78B76 /* DebugRelease.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = DebugRelease.xcconfig; sourceTree = "<group>"; };
@@ -949,6 +951,7 @@
 				A8A47323151A825B004123FF /* StringBuffer.h */,
 				A8A47324151A825B004123FF /* StringBuilder.cpp */,
 				A8A47325151A825B004123FF /* StringBuilder.h */,
+				430B47871AAAAC1A001223DA /* StringCommon.h */,
 				A8A47326151A825B004123FF /* StringConcatenate.h */,
 				A8A47327151A825B004123FF /* StringHash.h */,
 				A8A47328151A825B004123FF /* StringImpl.cpp */,
@@ -1196,6 +1199,7 @@
 				83FBA93219DF459700F30ADB /* TypeCasts.h in Headers */,
 				1A6EB1E0187D0BD30030126F /* StringView.h in Headers */,
 				A8A47433151A825B004123FF /* TemporaryChange.h in Headers */,
+				430B47891AAAAC1A001223DA /* StringCommon.h in Headers */,
 				A8A47444151A825B004123FF /* TextPosition.h in Headers */,
 				A8A47447151A825B004123FF /* ThreadFunctionInvocation.h in Headers */,
 				A8A47449151A825B004123FF /* ThreadIdentifierDataPthreads.h in Headers */,

Modified: trunk/Source/WTF/wtf/ASCIICType.h (181511 => 181512)


--- trunk/Source/WTF/wtf/ASCIICType.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/ASCIICType.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -30,6 +30,7 @@
 #define WTF_ASCIICType_h
 
 #include <wtf/Assertions.h>
+#include <wtf/text/LChar.h>
 
 // The behavior of many of the functions in the <ctype.h> header is dependent
 // on the current locale. But in the WebKit project, all uses of those functions
@@ -43,6 +44,25 @@
 
 namespace WTF {
 
+const unsigned char asciiCaseFoldTable[256] = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+    0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+    0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
+    0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+    0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+    0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+    0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+    0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+    0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+    0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
+};
+
 template<typename CharType> inline bool isASCII(CharType c)
 {
     return !(c & ~0x7F);
@@ -116,6 +136,18 @@
     return c | ((c >= 'A' && c <= 'Z') << 5);
 }
 
+template<>
+inline char toASCIILower(char c)
+{
+    return static_cast<char>(asciiCaseFoldTable[static_cast<unsigned char>(c)]);
+}
+
+template<>
+inline LChar toASCIILower(LChar c)
+{
+    return asciiCaseFoldTable[c];
+}
+
 template<typename CharType> inline CharType toASCIILowerUnchecked(CharType character)
 {
     // This function can be used for comparing any input character

Modified: trunk/Source/WTF/wtf/CMakeLists.txt (181511 => 181512)


--- trunk/Source/WTF/wtf/CMakeLists.txt	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/CMakeLists.txt	2015-03-15 19:43:18 UTC (rev 181512)
@@ -129,6 +129,7 @@
     text/IntegerToStringConversion.h
     text/LChar.h
     text/StringBuffer.h
+    text/StringCommon.h
     text/StringHash.h
     text/StringImpl.h
     text/StringView.h

Modified: trunk/Source/WTF/wtf/text/AtomicString.h (181511 => 181512)


--- trunk/Source/WTF/wtf/text/AtomicString.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/text/AtomicString.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -247,6 +247,10 @@
 inline bool equalIgnoringCase(const char* a, const AtomicString& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
 inline bool equalIgnoringCase(const String& a, const AtomicString& b) { return equalIgnoringCase(a.impl(), b.impl()); }
 
+inline bool equalIgnoringASCIICase(const AtomicString& a, const AtomicString& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
+inline bool equalIgnoringASCIICase(const AtomicString& a, const String& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
+inline bool equalIgnoringASCIICase(const String& a, const AtomicString& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
+
 // Define external global variables for the commonly used atomic strings.
 // These are only usable from the main thread.
 #ifndef ATOMICSTRING_HIDE_GLOBALS

Added: trunk/Source/WTF/wtf/text/StringCommon.h (0 => 181512)


--- trunk/Source/WTF/wtf/text/StringCommon.h	                        (rev 0)
+++ trunk/Source/WTF/wtf/text/StringCommon.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StringCommon_h
+#define StringCommon_h
+
+#include <unicode/uchar.h>
+#include <wtf/ASCIICType.h>
+
+namespace WTF {
+
+template<typename CharacterTypeA, typename CharacterTypeB>
+inline bool equalIgnoringASCIICase(const CharacterTypeA* a, const CharacterTypeB* b, unsigned length)
+{
+    for (unsigned i = 0; i < length; ++i) {
+        if (toASCIILower(a[i]) != toASCIILower(b[i]))
+            return false;
+    }
+    return true;
+}
+
+template<typename StringClass>
+bool equalIgnoringASCIICaseCommon(const StringClass& a, const StringClass& b)
+{
+    unsigned length = a.length();
+    if (length != b.length())
+        return false;
+
+    if (a.is8Bit()) {
+        if (b.is8Bit())
+            return equalIgnoringASCIICase(a.characters8(), b.characters8(), length);
+
+        return equalIgnoringASCIICase(a.characters8(), b.characters16(), length);
+    }
+
+    if (b.is8Bit())
+        return equalIgnoringASCIICase(a.characters16(), b.characters8(), length);
+
+    return equalIgnoringASCIICase(a.characters16(), b.characters16(), length);
+}
+
+}
+
+#endif // StringCommon_h

Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (181511 => 181512)


--- trunk/Source/WTF/wtf/text/StringImpl.cpp	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp	2015-03-15 19:43:18 UTC (rev 181512)
@@ -2018,6 +2018,27 @@
     return equal(a, b);
 }
 
+bool equalIgnoringASCIICase(const StringImpl& a, const StringImpl& b)
+{
+    return equalIgnoringASCIICaseCommon(a, b);
+}
+
+bool equalIgnoringASCIICase(const StringImpl* a, const StringImpl*b)
+{
+    if (a == b)
+        return true;
+    if (!a || !b)
+        return false;
+    return equalIgnoringASCIICaseCommon(*a, *b);
+}
+
+bool equalIgnoringASCIICaseNonNull(const StringImpl* a, const StringImpl* b)
+{
+    ASSERT(a);
+    ASSERT(b);
+    return equalIgnoringASCIICaseCommon(*a, *b);
+}
+
 UCharDirection StringImpl::defaultWritingDirection(bool* hasStrongDirectionality)
 {
     for (unsigned i = 0; i < m_length; ++i) {

Modified: trunk/Source/WTF/wtf/text/StringImpl.h (181511 => 181512)


--- trunk/Source/WTF/wtf/text/StringImpl.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/text/StringImpl.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -1132,6 +1132,10 @@
 WTF_EXPORT_STRING_API bool equalIgnoringNullity(StringImpl*, StringImpl*);
 WTF_EXPORT_STRING_API bool equalIgnoringNullity(const UChar*, size_t length, StringImpl*);
 
+WTF_EXPORT_STRING_API bool equalIgnoringASCIICase(const StringImpl&, const StringImpl&);
+WTF_EXPORT_STRING_API bool equalIgnoringASCIICase(const StringImpl*, const StringImpl*);
+WTF_EXPORT_STRING_API bool equalIgnoringASCIICaseNonNull(const StringImpl*, const StringImpl*);
+
 template<typename CharacterType>
 inline size_t find(const CharacterType* characters, unsigned length, CharacterType matchCharacter, unsigned index = 0)
 {
@@ -1374,6 +1378,7 @@
 
 using WTF::StringImpl;
 using WTF::equal;
+using WTF::equalIgnoringASCIICase;
 using WTF::TextCaseSensitivity;
 using WTF::TextCaseSensitive;
 using WTF::TextCaseInsensitive;

Modified: trunk/Source/WTF/wtf/text/StringView.h (181511 => 181512)


--- trunk/Source/WTF/wtf/text/StringView.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/text/StringView.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -31,6 +31,7 @@
 #include <wtf/RetainPtr.h>
 #include <wtf/Vector.h>
 #include <wtf/text/LChar.h>
+#include <wtf/text/StringCommon.h>
 
 // FIXME: Enabling the StringView lifetime checking causes the MSVC build to fail. Figure out why.
 // FIXME: Enable StringView lifetime checking once the underlying assertions have been fixed.
@@ -505,14 +506,7 @@
 
 inline bool equalIgnoringASCIICase(StringView a, StringView b)
 {
-    unsigned aLength = a.length();
-    if (aLength != b.length()) 
-        return false;
-    for (size_t i = 0; i < aLength; ++i) {
-        if (toASCIILower(a[i]) != toASCIILower(b[i]))
-            return false;
-    }
-    return true;
+    return equalIgnoringASCIICaseCommon(a, b);
 }
 
 class StringView::CodePoints {

Modified: trunk/Source/WTF/wtf/text/WTFString.h (181511 => 181512)


--- trunk/Source/WTF/wtf/text/WTFString.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WTF/wtf/text/WTFString.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -492,6 +492,8 @@
 inline bool equalIgnoringCase(const LChar* a, const String& b) { return equalIgnoringCase(a, b.impl()); }
 inline bool equalIgnoringCase(const char* a, const String& b) { return equalIgnoringCase(reinterpret_cast<const LChar*>(a), b.impl()); }
 
+inline bool equalIgnoringASCIICase(const String& a, const String& b) { return equalIgnoringASCIICase(a.impl(), b.impl()); }
+
 inline bool equalPossiblyIgnoringCase(const String& a, const String& b, bool ignoreCase) 
 {
     return ignoreCase ? equalIgnoringCase(a, b) : (a == b);

Modified: trunk/Source/WebCore/ChangeLog (181511 => 181512)


--- trunk/Source/WebCore/ChangeLog	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WebCore/ChangeLog	2015-03-15 19:43:18 UTC (rev 181512)
@@ -1,3 +1,26 @@
+2015-03-15  Benjamin Poulain  <[email protected]>
+
+        Change the exact attribute matching to be ASCII case-insensitive
+        https://bugs.webkit.org/show_bug.cgi?id=142609
+
+        Reviewed by Darin Adler.
+
+        In CSS, testing attribute values should be ASCII case-insensitive,
+        previously we were using full unicode case conversion.
+
+        Test: fast/selectors/attribute-exact-value-match-is-ascii-case-insensitive.html
+
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseKeyframeSelector):
+        The CSS parser has its own fast version for ASCII case insensitive.
+        This code was using the general equalIgnoringASCIICase() which was causing name conflicts,
+        change that to the normal CSS parser version.
+
+        * css/SelectorCheckerTestFunctions.h:
+        (WebCore::equalIgnoringASCIICase): Deleted.
+        * cssjit/SelectorCompiler.cpp:
+        (WebCore::SelectorCompiler::SelectorCodeGenerator::generateElementAttributeValueExactMatching):
+
 2015-03-15  Brent Fulgham  <[email protected]>
 
         scroll snap points do not properly account for zoomed pages

Modified: trunk/Source/WebCore/css/CSSParser.cpp (181511 => 181512)


--- trunk/Source/WebCore/css/CSSParser.cpp	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WebCore/css/CSSParser.cpp	2015-03-15 19:43:18 UTC (rev 181512)
@@ -4774,9 +4774,9 @@
         String cur = strings[i].stripWhiteSpace();
 
         // For now the syntax MUST be 'xxx%' or 'from' or 'to', where xxx is a legal floating point number
-        if (equalIgnoringASCIICase(cur, "from"))
+        if (equalIgnoringCase(cur, "from"))
             key = 0;
-        else if (equalIgnoringASCIICase(cur, "to"))
+        else if (equalIgnoringCase(cur, "to"))
             key = 1;
         else if (cur.endsWith('%')) {
             double k = cur.substring(0, cur.length() - 1).toDouble();

Modified: trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h (181511 => 181512)


--- trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WebCore/css/SelectorCheckerTestFunctions.h	2015-03-15 19:43:18 UTC (rev 181512)
@@ -120,17 +120,6 @@
     return !element->document().page()->focusController().isActive();
 }
 
-ALWAYS_INLINE bool equalIgnoringASCIICase(const String& a, const String& b)
-{
-    if (a.length() != b.length()) 
-        return false;
-    for (size_t i = 0; i < a.length(); ++i) {
-        if (toASCIILower(a[i]) != toASCIILower(b[i]))
-            return false;
-    }
-    return true;
-}
-
 ALWAYS_INLINE bool containslanguageSubtagMatchingRange(StringView language, StringView range, unsigned languageLength, unsigned& position)
 {
     unsigned languageSubtagsStartIndex = position;

Modified: trunk/Source/WebCore/cssjit/SelectorCompiler.cpp (181511 => 181512)


--- trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Source/WebCore/cssjit/SelectorCompiler.cpp	2015-03-15 19:43:18 UTC (rev 181512)
@@ -2934,7 +2934,7 @@
         m_assembler.loadPtr(Assembler::Address(currentAttributeAddress, Attribute::valueMemoryOffset()), valueStringImpl);
 
         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(WTF::equalIgnoringCaseNonNull);
+        functionCall.setFunctionAddress(WTF::equalIgnoringASCIICaseNonNull);
         functionCall.setTwoArguments(valueStringImpl, expectedValueRegister);
         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
 
@@ -2947,7 +2947,7 @@
 
         Assembler::Jump skipCaseInsensitiveComparison = m_assembler.branchPtr(Assembler::Equal, valueStringImpl, expectedValueRegister);
         FunctionCall functionCall(m_assembler, m_registerAllocator, m_stackAllocator, m_functionCalls);
-        functionCall.setFunctionAddress(WTF::equalIgnoringCaseNonNull);
+        functionCall.setFunctionAddress(WTF::equalIgnoringASCIICaseNonNull);
         functionCall.setTwoArguments(valueStringImpl, expectedValueRegister);
         failureCases.append(functionCall.callAndBranchOnBooleanReturnValue(Assembler::Zero));
         skipCaseInsensitiveComparison.link(&m_assembler);

Modified: trunk/Tools/ChangeLog (181511 => 181512)


--- trunk/Tools/ChangeLog	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Tools/ChangeLog	2015-03-15 19:43:18 UTC (rev 181512)
@@ -1,3 +1,13 @@
+2015-03-15  Benjamin Poulain  <[email protected]>
+
+        Change the exact attribute matching to be ASCII case-insensitive
+        https://bugs.webkit.org/show_bug.cgi?id=142609
+
+        Reviewed by Darin Adler.
+
+        * TestWebKitAPI/Tests/WTF/StringImpl.cpp:
+        * TestWebKitAPI/Tests/WTF/StringView.cpp:
+
 2015-03-13  Youenn Fablet  <[email protected]>
 
         WebKit test infrastructure should automate the process of cloning W3C test suite and importing tests from it

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp (181511 => 181512)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/StringImpl.cpp	2015-03-15 19:43:18 UTC (rev 181512)
@@ -99,4 +99,69 @@
     ASSERT_TRUE(equal(testStringImpl.get(), "r555sum555"));
 }
 
+TEST(WTF, StringImplEqualIgnoringASCIICaseBasic)
+{
+    RefPtr<StringImpl> a = StringImpl::createFromLiteral("aBcDeFG");
+    RefPtr<StringImpl> b = StringImpl::createFromLiteral("ABCDEFG");
+    RefPtr<StringImpl> c = StringImpl::createFromLiteral("abcdefg");
+    RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    RefPtr<StringImpl> shorter = StringImpl::createFromLiteral("abcdef");
+
+    // Identity.
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get()));
+
+    // Transitivity.
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(b.get(), c.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get()));
+
+    // Negative cases.
+    ASSERT_FALSE(equalIgnoringASCIICase(a.get(), empty.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(b.get(), empty.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(c.get(), empty.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(a.get(), shorter.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(b.get(), shorter.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(c.get(), shorter.get()));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithNull)
+{
+    RefPtr<StringImpl> reference = StringImpl::createFromLiteral("aBcDeFG");
+    ASSERT_FALSE(equalIgnoringASCIICase(nullptr, reference.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(reference.get(), nullptr));
+    ASSERT_TRUE(equalIgnoringASCIICase(nullptr, nullptr));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithEmpty)
+{
+    RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), b.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(b.get(), a.get()));
+}
+
+TEST(WTF, StringImplEqualIgnoringASCIICaseWithLatin1Characters)
+{
+    RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>("aBcéeFG"));
+    RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>("ABCÉEFG"));
+    RefPtr<StringImpl> c = StringImpl::create(reinterpret_cast<const LChar*>("ABCéEFG"));
+    RefPtr<StringImpl> d = StringImpl::create(reinterpret_cast<const LChar*>("abcéefg"));
+
+    // Identity.
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), a.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(b.get(), b.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(c.get(), c.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(d.get(), d.get()));
+
+    // All combination.
+    ASSERT_FALSE(equalIgnoringASCIICase(a.get(), b.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), c.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(a.get(), d.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(b.get(), c.get()));
+    ASSERT_FALSE(equalIgnoringASCIICase(b.get(), d.get()));
+    ASSERT_TRUE(equalIgnoringASCIICase(c.get(), d.get()));
+}
+
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp (181511 => 181512)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp	2015-03-15 19:30:09 UTC (rev 181511)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/StringView.cpp	2015-03-15 19:43:18 UTC (rev 181512)
@@ -142,4 +142,77 @@
     EXPECT_TRUE(compareLoopIterations(StringView(b.toString()).codeUnits(), {0x0306, 0xD800, 0xDD55, 'h', 'e', 'l', 'o'}));
 }
 
+TEST(WTF, StringViewEqualIgnoringASCIICaseBasic)
+{
+    RefPtr<StringImpl> a = StringImpl::createFromLiteral("aBcDeFG");
+    RefPtr<StringImpl> b = StringImpl::createFromLiteral("ABCDEFG");
+    RefPtr<StringImpl> c = StringImpl::createFromLiteral("abcdefg");
+    RefPtr<StringImpl> empty = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    RefPtr<StringImpl> shorter = StringImpl::createFromLiteral("abcdef");
+
+    StringView stringViewA(*a.get());
+    StringView stringViewB(*b.get());
+    StringView stringViewC(*c.get());
+    StringView emptyStringView(*empty.get());
+    StringView shorterStringView(*shorter.get());
+
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+
+    // Identity.
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+
+    // Transitivity.
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewC));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+
+    // Negative cases.
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, emptyStringView));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, emptyStringView));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, emptyStringView));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, shorterStringView));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, shorterStringView));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewC, shorterStringView));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithEmpty)
+{
+    RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>(""));
+    StringView stringViewA(*a.get());
+    StringView stringViewB(*b.get());
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewA));
+}
+
+TEST(WTF, StringViewEqualIgnoringASCIICaseWithLatin1Characters)
+{
+    RefPtr<StringImpl> a = StringImpl::create(reinterpret_cast<const LChar*>("aBcéeFG"));
+    RefPtr<StringImpl> b = StringImpl::create(reinterpret_cast<const LChar*>("ABCÉEFG"));
+    RefPtr<StringImpl> c = StringImpl::create(reinterpret_cast<const LChar*>("ABCéEFG"));
+    RefPtr<StringImpl> d = StringImpl::create(reinterpret_cast<const LChar*>("abcéefg"));
+    StringView stringViewA(*a.get());
+    StringView stringViewB(*b.get());
+    StringView stringViewC(*c.get());
+    StringView stringViewD(*d.get());
+
+    // Identity.
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewA));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewB, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewC));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewD, stringViewD));
+
+    // All combination.
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewA, stringViewB));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewC));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewA, stringViewD));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewC));
+    ASSERT_FALSE(equalIgnoringASCIICase(stringViewB, stringViewD));
+    ASSERT_TRUE(equalIgnoringASCIICase(stringViewC, stringViewD));
+}
+
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to