Bug 142609 - Change the exact attribute matching to be ASCII case-insensitive
Summary: Change the exact attribute matching to be ASCII case-insensitive
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Benjamin Poulain
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-03-11 21:52 PDT by Benjamin Poulain
Modified: 2015-03-15 22:35 PDT (History)
3 users (show)

See Also:


Attachments
Patch (51.10 KB, patch)
2015-03-11 21:54 PDT, Benjamin Poulain
no flags Details | Formatted Diff | Diff
Patch (51.71 KB, patch)
2015-03-11 22:00 PDT, Benjamin Poulain
no flags Details | Formatted Diff | Diff
Patch (52.27 KB, patch)
2015-03-13 20:52 PDT, Benjamin Poulain
darin: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Benjamin Poulain 2015-03-11 21:52:14 PDT
Change the exact attribute matching to be ASCII case-insensitive
Comment 1 Benjamin Poulain 2015-03-11 21:54:43 PDT
Created attachment 248489 [details]
Patch
Comment 2 Benjamin Poulain 2015-03-11 22:00:53 PDT
Created attachment 248492 [details]
Patch
Comment 3 Darin Adler 2015-03-12 08:38:50 PDT
Comment on attachment 248492 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=248492&action=review

I really like the way you tackled this, but I spotted a few small problems.

I’m going to say review- because of at least some of these problems, like the "return false" where it should say "return true", need to be fixed.

> Source/WTF/wtf/text/StringCommon.h:51
> +    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

I normally prefer capitalized hex.

> Source/WTF/wtf/text/StringCommon.h:55
> +template<typename CharacterTypeA, typename CharacterTypeB>
> +static inline bool equalIgnoringASCIICase(const CharacterTypeA* a, const CharacterTypeB* b, unsigned length)

Any reason you put “static” on this one and not on the other function templates in this file?

> Source/WTF/wtf/text/StringCommon.h:88
> +template<>
> +inline bool equalIgnoringASCIICase(const LChar* a, const LChar* b, unsigned length)
> +{
> +    for (unsigned i = 0; i < length; ++i) {
> +        if (asciiCaseFoldTable[a[i]] != asciiCaseFoldTable[b[i]])
> +            return false;
> +    }
> +    return true;
> +}
> +
> +template<>
> +inline bool equalIgnoringASCIICase(const UChar* a, const LChar* b, unsigned length)
> +{
> +    for (unsigned i = 0; i < length; ++i) {
> +        if (toASCIILower(a[i]) != asciiCaseFoldTable[b[i]])
> +            return false;
> +    }
> +    return true;
> +}
> +
> +template<>
> +inline bool equalIgnoringASCIICase(const LChar* a, const UChar* b, unsigned length)
> +{
> +    return equalIgnoringASCIICase(b, a, length);
> +}

I’m not sure why we put this optimization here instead of putting it in toASCIILower(LChar). If we did that, then we wouldn’t need the three specializations.

> Source/WTF/wtf/text/StringImpl.cpp:300
> +template<typename CharacterType>
> +static bool containsOnlyASCIIAlphaLower(const CharacterType* characters, unsigned length)

This template is added here, but I don’t see any code below using it.

ASCIICType calls this ASCIILower, not ASCIIAlphaLower.

> Source/WTF/wtf/text/StringImpl.cpp:2034
> +    if (&a == &b)
> +        return false;

This should be true, not false. We should cover this in unit tests.

I’m not 100% sure this is an important optimization.

> Source/WTF/wtf/text/StringImpl.cpp:2042
> +    if (a == b)
> +        return true;

I’m not 100% sure this is an important optimization.

> Source/WTF/wtf/text/StringImpl.cpp:2044
> +    if (!a || !b)
> +        return false;

This means that the null string is going to say it’s not equal to the empty string. Is that what we want? I believe our other string equality functions consider the null string equal to the empty string. We should cover this in tests.

> Source/WTF/wtf/text/StringImpl.cpp:2050
> +    ASSERT(a && b);

WebKit coding style is to use multiple assertions instead of &&, since it’s better to see which one failed. I think the style guide document might explicitly mention this.

> Source/WebCore/css/CSSParser.cpp:4759
> -        if (equalIgnoringASCIICase(cur, "from"))
> +        if (equalIgnoringCase(cur, "from"))

Long term this seems like a step in the wrong direction. We can write a more optimal version if we only ignore ASCII case, and don’t try to do arbitrary case folding. Perhaps the problem is that we don’t have an overload that avoids converting the literal into a string object?

> Source/WebCore/css/CSSParser.cpp:4761
> -        else if (equalIgnoringASCIICase(cur, "to"))
> +        else if (equalIgnoringCase(cur, "to"))

Ditto.
Comment 4 Benjamin Poulain 2015-03-13 20:52:49 PDT
Created attachment 248638 [details]
Patch
Comment 5 Benjamin Poulain 2015-03-13 21:08:35 PDT
I could not add a new test because the code is eliminated by the linker since it is not used anywhere.

(In reply to comment #3)
> > Source/WebCore/css/CSSParser.cpp:4759
> > -        if (equalIgnoringASCIICase(cur, "from"))
> > +        if (equalIgnoringCase(cur, "from"))
> 
> Long term this seems like a step in the wrong direction. We can write a more
> optimal version if we only ignore ASCII case, and don’t try to do arbitrary
> case folding. Perhaps the problem is that we don’t have an overload that
> avoids converting the literal into a string object?
> 
> > Source/WebCore/css/CSSParser.cpp:4761
> > -        else if (equalIgnoringASCIICase(cur, "to"))
> > +        else if (equalIgnoringCase(cur, "to"))
> 
> Ditto.

In CSS Parser, equalIgnoringCase() is the local version taking a string literal. This needs to be fixed too but it is a much bigger change and will be done separately.
Comment 6 Darin Adler 2015-03-15 09:59:06 PDT
Comment on attachment 248638 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=248638&action=review

> Source/WTF/wtf/text/StringCommon.h:53
> +template<>
> +inline bool equalIgnoringASCIICase(const LChar* a, const LChar* b, unsigned length)
> +{
> +    for (unsigned i = 0; i < length; ++i) {
> +        if (toASCIILower(a[i]) != toASCIILower(b[i]))
> +            return false;
> +    }
> +    return true;
> +}

I don’t think this specialization is needed. It’s the same as the general case above, which will be recompiled for LChar, so how does this help?

> Source/WTF/wtf/text/StringImpl.cpp:2024
> +ALWAYS_INLINE bool equalIgnoringASCIICase(const StringImpl& a, const StringImpl& b)
> +{
> +    return equalIgnoringASCIICaseCommon(a, b);
> +}

If this is going to be marked inline, then it needs to be in the header, not the cpp file.
Comment 7 Benjamin Poulain 2015-03-15 12:03:45 PDT
Thanks for the review!

(In reply to comment #6)
> Comment on attachment 248638 [details]
> > Source/WTF/wtf/text/StringImpl.cpp:2024
> > +ALWAYS_INLINE bool equalIgnoringASCIICase(const StringImpl& a, const StringImpl& b)
> > +{
> > +    return equalIgnoringASCIICaseCommon(a, b);
> > +}
> 
> If this is going to be marked inline, then it needs to be in the header, not
> the cpp file.

This is to make this function inline in the context of this compilation unit, but not in the global context. The reason was I needed equalIgnoringASCIICaseNonNull to inline this, but every other caller out-of-line. Since then I introduced equalIgnoringASCIICaseCommon() which makes this inlining completely useless.
Comment 8 Benjamin Poulain 2015-03-15 12:44:01 PDT
Committed r181512: <http://trac.webkit.org/changeset/181512>
Comment 9 Darin Adler 2015-03-15 14:16:55 PDT
Comment on attachment 248638 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=248638&action=review

>>> Source/WTF/wtf/text/StringImpl.cpp:2024
>>> +}
>> 
>> If this is going to be marked inline, then it needs to be in the header, not the cpp file.
> 
> This is to make this function inline in the context of this compilation unit, but not in the global context. The reason was I needed equalIgnoringASCIICaseNonNull to inline this, but every other caller out-of-line. Since then I introduced equalIgnoringASCIICaseCommon() which makes this inlining completely useless.

That may be what you want, but I am surprised it works. I expect a link failure when people try to use this function outside this compilation unit. Instead you’d typically need a separate inlined function and a non-inlined function that calls it.
Comment 10 Alexey Proskuryakov 2015-03-15 22:19:09 PDT
The new test fails on Windows:

@@ -49,161 +49,161 @@
 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
+FAIL document.querySelectorAll('#test-root [data-attribute=WebKit-É i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[data-attribute=webkit-É i]"
-PASS document.querySelectorAll('#test-root [data-attribute=webkit-É i]').length is 3
+FAIL document.querySelectorAll('#test-root [data-attribute=webkit-É i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[data-attribute=WEBKIT-É i]"
-PASS document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]').length is 3
+FAIL document.querySelectorAll('#test-root [data-attribute=WEBKIT-É i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was 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)"
+FAIL document.querySelectorAll('#test-root [data-attribute=WebKit-é i]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [data-attribute=WebKit-é i]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [data-attribute=WebKit-é i]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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)"
+FAIL document.querySelectorAll('#test-root [data-attribute=webkit-é i]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [data-attribute=webkit-é i]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [data-attribute=webkit-é i]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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
+FAIL document.querySelectorAll('#test-root [multiple=WEBKIT-é]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[multiple=WebKit-é]"
-PASS document.querySelectorAll('#test-root [multiple=WebKit-é]').length is 3
+FAIL document.querySelectorAll('#test-root [multiple=WebKit-é]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[multiple=Webkit-é]"
-PASS document.querySelectorAll('#test-root [multiple=Webkit-é]').length is 3
+FAIL document.querySelectorAll('#test-root [multiple=Webkit-é]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was 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)"
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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)"
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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
+FAIL document.querySelectorAll('#test-root [multiple=WEBKIT-é i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[multiple=WebKit-é i]"
-PASS document.querySelectorAll('#test-root [multiple=WebKit-é i]').length is 3
+FAIL document.querySelectorAll('#test-root [multiple=WebKit-é i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 
 Testing "[multiple=Webkit-é i]"
-PASS document.querySelectorAll('#test-root [multiple=Webkit-é i]').length is 3
+FAIL document.querySelectorAll('#test-root [multiple=Webkit-é i]').length should be 3. Was 5.
 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)"
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[3]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[4]).backgroundColor should be rgb(255, 0, 0). Was 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)"
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É i]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É i]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [multiple=webkit-É i]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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)"
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É i]').length should be 2. Was 5.
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É i]')[0].id should be target4. Was target1.
+FAIL document.querySelectorAll('#test-root [multiple=webKit-É i]')[1].id should be target5. Was target2.
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[0]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[1]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
+FAIL getComputedStyle(document.querySelectorAll("#test-root *")[2]).backgroundColor should be rgb(255, 0, 0). Was rgb(10, 100, 200).
 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)"
Comment 11 Benjamin Poulain 2015-03-15 22:35:04 PDT
(In reply to comment #10)
> The new test fails on Windows:

The fix is already in https://bugs.webkit.org/show_bug.cgi?id=142715 but it is waiting for review.