Title: [173012] trunk
Revision
173012
Author
[email protected]
Date
2014-08-27 12:16:51 -0700 (Wed, 27 Aug 2014)

Log Message

Updating attributes on HTML elements do not invalidate the style correctly unless the attribute name is lowercase in the stylesheet
https://bugs.webkit.org/show_bug.cgi?id=136270
Source/WebCore:


Patch by Benjamin Poulain <[email protected]> on 2014-08-27
Reviewed by Andreas Kling.

In HTML, WebKit treats every attribute name lowercase to implement case-insensitive matching.
When invalidating style, the StyleResolver was ignoring HTML and always using the XML names.

This patch split the names on RuleFeatureSet in two sets: one for XML, one for HTML.
In StyleResolver, the name used depends on the type of the element being updated.

This patch also adds nodeNeedsStyleRecalc() to Internals to test the optimization and various cases
of style update.

Tests: fast/css/attribute-for-content-property-style-update-html.html
       fast/css/attribute-for-content-property-style-update-xhtml.xhtml
       fast/css/attribute-style-invalidation-optimization-html.html
       fast/css/attribute-style-invalidation-optimization-xhtml.xhtml
       fast/css/attribute-style-update-html.html
       fast/selectors/attribute-style-update-html.html
       fast/selectors/attribute-style-update-svg-in-html.html
       fast/selectors/attribute-style-update-xhtml.xhtml

* css/RuleFeature.cpp:
(WebCore::RuleFeatureSet::collectFeaturesFromSelector):
(WebCore::RuleFeatureSet::add):
(WebCore::RuleFeatureSet::clear):
* css/RuleFeature.h:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::applyProperty):
* css/StyleResolver.h:
(WebCore::StyleResolver::hasSelectorForAttribute):
* dom/Element.cpp:
(WebCore::Element::willModifyAttribute):
* testing/Internals.cpp:
(WebCore::Internals::address):
(WebCore::Internals::nodeNeedsStyleRecalc):
* testing/Internals.h:
* testing/Internals.idl:

LayoutTests:

rdar://problem/16190617

Patch by Benjamin Poulain <[email protected]> on 2014-08-27
Reviewed by Andreas Kling.

The test coverage for attribute update was abysmal. This adds the basic cases for HTML and XML.

* fast/css/attribute-for-content-property-style-update-html-expected.html: Added.
* fast/css/attribute-for-content-property-style-update-html.html: Added.
* fast/css/attribute-for-content-property-style-update-xhtml-expected.html: Added.
* fast/css/attribute-for-content-property-style-update-xhtml.xhtml: Added.
* fast/css/attribute-style-invalidation-optimization-html-expected.txt: Added.
* fast/css/attribute-style-invalidation-optimization-html.html: Added.
* fast/css/attribute-style-invalidation-optimization-xhtml-expected.txt: Added.
* fast/css/attribute-style-invalidation-optimization-xhtml.xhtml: Added.
* fast/css/attribute-style-update-html-expected.html: Added.
* fast/css/attribute-style-update-html.html: Added.
* fast/selectors/attribute-style-update-html-expected.txt: Added.
* fast/selectors/attribute-style-update-html.html: Added.
* fast/selectors/attribute-style-update-svg-in-html-expected.txt: Added.
* fast/selectors/attribute-style-update-svg-in-html.html: Added.
* fast/selectors/attribute-style-update-xhtml-expected.txt: Added.
* fast/selectors/attribute-style-update-xhtml.xhtml: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (173011 => 173012)


--- trunk/LayoutTests/ChangeLog	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/LayoutTests/ChangeLog	2014-08-27 19:16:51 UTC (rev 173012)
@@ -1,3 +1,30 @@
+2014-08-27  Benjamin Poulain  <[email protected]>
+
+        Updating attributes on HTML elements do not invalidate the style correctly unless the attribute name is lowercase in the stylesheet
+        https://bugs.webkit.org/show_bug.cgi?id=136270
+        rdar://problem/16190617
+
+        Reviewed by Andreas Kling.
+
+        The test coverage for attribute update was abysmal. This adds the basic cases for HTML and XML.
+
+        * fast/css/attribute-for-content-property-style-update-html-expected.html: Added.
+        * fast/css/attribute-for-content-property-style-update-html.html: Added.
+        * fast/css/attribute-for-content-property-style-update-xhtml-expected.html: Added.
+        * fast/css/attribute-for-content-property-style-update-xhtml.xhtml: Added.
+        * fast/css/attribute-style-invalidation-optimization-html-expected.txt: Added.
+        * fast/css/attribute-style-invalidation-optimization-html.html: Added.
+        * fast/css/attribute-style-invalidation-optimization-xhtml-expected.txt: Added.
+        * fast/css/attribute-style-invalidation-optimization-xhtml.xhtml: Added.
+        * fast/css/attribute-style-update-html-expected.html: Added.
+        * fast/css/attribute-style-update-html.html: Added.
+        * fast/selectors/attribute-style-update-html-expected.txt: Added.
+        * fast/selectors/attribute-style-update-html.html: Added.
+        * fast/selectors/attribute-style-update-svg-in-html-expected.txt: Added.
+        * fast/selectors/attribute-style-update-svg-in-html.html: Added.
+        * fast/selectors/attribute-style-update-xhtml-expected.txt: Added.
+        * fast/selectors/attribute-style-update-xhtml.xhtml: Added.
+
 2014-08-27  Mihnea Ovidenie  <[email protected]>
 
         [CSS Regions] Move generated content tests into fast/regions/generated-content

Added: trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html-expected.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html-expected.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+.valid::before {
+    content: "WebKit!"
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling and style update of attributes that are only used by the "content" propery of a rule. HTML should match the attribute regardless of the case.</p>
+    <div id="initial">
+        <target>No attribute</target>
+
+        <target class="valid">CamelCase initial attribute</target>
+        <target class="valid">camelcase initial attribute</target>
+        <target class="valid">CAMELCASE initial attribute</target>
+    </div>
+    <div id="dynamic">
+        <target>No attribute</target>
+
+        <target class="valid">CamelCase initial attribute</target>
+        <target class="valid">camelcase initial attribute</target>
+        <target class="valid">CAMELCASE initial attribute</target>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-html.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+target::before {
+    content: attr(CamelCase)
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling and style update of attributes that are only used by the "content" propery of a rule. HTML should match the attribute regardless of the case.</p>
+    <div id="initial">
+        <target>No attribute</target>
+
+        <target CamelCase="WebKit!">CamelCase initial attribute</target>
+        <target camelcase="WebKit!">camelcase initial attribute</target>
+        <target CAMELCASE="WebKit!">CAMELCASE initial attribute</target>
+    </div>
+    <div id="dynamic">
+        <target>No attribute</target>
+
+        <target>CamelCase initial attribute</target>
+        <target>camelcase initial attribute</target>
+        <target>CAMELCASE initial attribute</target>
+    </div>
+</body>
+<script>
+window.addEventListener("load", function() {
+    forcedLayout = document.documentElement.offsetTop;
+
+    var allDynamicTargets = document.querySelectorAll("#dynamic>target");
+    allDynamicTargets[1].setAttribute("CamelCase", "WebKit!");
+    allDynamicTargets[2].setAttribute("camelcase", "WebKit!");
+    allDynamicTargets[3].setAttribute("CAMELCASE", "WebKit!");
+});
+</script>
+</html>

Added: trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml-expected.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml-expected.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style>
+.valid::before {
+    content: "WebKit!"
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling and style update of attributes that are only used by the "content" propery of a rule.</p>
+    <div id="initial">
+        <target>No attribute</target>
+
+        <target class="valid">CamelCase initial attribute</target>
+        <target>camelcase initial attribute</target>
+        <target>CAMELCASE initial attribute</target>
+    </div>
+    <div id="dynamic">
+        <target>No attribute</target>
+
+        <target class="valid">CamelCase initial attribute</target>
+        <target>camelcase initial attribute</target>
+        <target>CAMELCASE initial attribute</target>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml.xhtml (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml.xhtml	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-for-content-property-style-update-xhtml.xhtml	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<style>
+target::before {
+    content: attr(CamelCase)
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling and style update of attributes that are only used by the "content" propery of a rule.</p>
+    <div id="initial">
+        <target>No attribute</target>
+
+        <target CamelCase="WebKit!">CamelCase initial attribute</target>
+        <target camelcase="WebKit!">camelcase initial attribute</target>
+        <target CAMELCASE="WebKit!">CAMELCASE initial attribute</target>
+    </div>
+    <div id="dynamic">
+        <target>No attribute</target>
+
+        <target>CamelCase initial attribute</target>
+        <target>camelcase initial attribute</target>
+        <target>CAMELCASE initial attribute</target>
+    </div>
+</body>
+<script><![CDATA[
+window.addEventListener("load", function() {
+    forcedLayout = document.documentElement.offsetTop;
+
+    var allDynamicTargets = document.querySelectorAll("#dynamic>target");
+    allDynamicTargets[1].setAttribute("CamelCase", "WebKit!");
+    allDynamicTargets[2].setAttribute("camelcase", "WebKit!");
+    allDynamicTargets[3].setAttribute("CAMELCASE", "WebKit!");
+});
+]]></script>
+</html>

Added: trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html-expected.txt (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html-expected.txt	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,41 @@
+Test that we only invalidate the style when changing an attribute referenced by a stylesheet. This test requires the internals object to work properly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'foo', it is not referenced by any stylesheet and should not cause any invalidation.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'CamelCase'. It is used by the stylesheet and should cause the target to be invalidated.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Removing the attribute should also invalidate the style.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'camelcase'. It is not used as such by the stylesheet, but in HTML attribute names are case-insensitive and we should still invalidate the style.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Removing the attribute should also invalidate the style.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'CAMELCASE'. It is not used as such by the stylesheet, but in HTML attribute names are case-insensitive and we should still invalidate the style.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-html.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+    color: black;
+}
+[CamelCase] {
+    color: pink;
+}
+</style>
+</head>
+<body>
+    <div>
+        <!-- With renderer -->
+        <target></target>
+    </div>
+    <div style="display:none;">
+        <!-- Without renderer -->
+        <target></target>
+    </div>
+</body>
+<script>
+// It is okay to increase the amount of invalidation in this test for correctness if necessary.
+description('Test that we only invalidate the style when changing an attribute referenced by a stylesheet. This test requires the internals object to work properly.');
+
+function shouldNeedStyleRecalc(expected) {
+    var testFunction = expected ? shouldBeTrue : shouldBeFalse;
+    testFunction("window.internals.nodeNeedsStyleRecalc(document.querySelectorAll(\"target\")[0])");
+    testFunction("window.internals.nodeNeedsStyleRecalc(document.querySelectorAll(\"target\")[1])");
+}
+
+function setAttribute(name, value) {
+    var allTargets = document.querySelectorAll("target");
+    allTargets[0].setAttribute(name, value);
+    allTargets[1].setAttribute(name, value);
+}
+
+function removeAttribute(name) {
+    var allTargets = document.querySelectorAll("target");
+    allTargets[0].removeAttribute(name);
+    allTargets[1].removeAttribute(name);
+}
+
+function getStyle() {
+    var allTargets = document.querySelectorAll("target");
+    getComputedStyle(allTargets[0]).color;
+    getComputedStyle(allTargets[1]).color;
+}
+
+// Force a layout to ensure we don't have dirty styles.
+var offsetTop = document.documentElement.offsetTop;
+shouldNeedStyleRecalc(false);
+
+debug("Changing the attribute 'foo', it is not referenced by any stylesheet and should not cause any invalidation.");
+setAttribute("foo", "bar");
+shouldNeedStyleRecalc(false);
+
+debug("Changing the attribute 'CamelCase'. It is used by the stylesheet and should cause the target to be invalidated.");
+setAttribute("CamelCase", "");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false);
+
+debug("Removing the attribute should also invalidate the style.");
+removeAttribute("CamelCase");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false)
+
+debug("Changing the attribute 'camelcase'. It is not used as such by the stylesheet, but in HTML attribute names are case-insensitive and we should still invalidate the style.");
+setAttribute("camelcase", "");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false);
+
+debug("Removing the attribute should also invalidate the style.");
+removeAttribute("CamelCase");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false)
+
+debug("Changing the attribute 'CAMELCASE'. It is not used as such by the stylesheet, but in HTML attribute names are case-insensitive and we should still invalidate the style.");
+setAttribute("CAMELCASE", "");
+shouldNeedStyleRecalc(true);
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml-expected.txt (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml-expected.txt	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,32 @@
+Test that we only invalidate the style when changing an attribute referenced by a stylesheet. This test requires the internals object to work properly.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'foo', it is not referenced by any stylesheet and should not cause any invalidation.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'CamelCase'. It is used by the stylesheet and should cause the target to be invalidated.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Removing the attribute should also invalidate the style.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is true
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is true
+Getting the computed style should for the style to be resolved.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'camelcase'. Since XML attributes are case sensitive, this does not invalidate the style since it is a different attribute.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+Changing the attribute 'CAMELCASE'. Same deal, this is a different attribute.
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[0]) is false
+PASS window.internals.nodeNeedsStyleRecalc(document.querySelectorAll("target")[1]) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml.xhtml (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml.xhtml	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-invalidation-optimization-xhtml.xhtml	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,85 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src=""
+<style>
+* {
+    color: black;
+}
+[CamelCase] {
+    color: pink;
+}
+</style>
+</head>
+<body>
+    <div>
+        <!-- With renderer -->
+        <target></target>
+    </div>
+    <div style="display:none;">
+        <!-- Without renderer -->
+        <target></target>
+    </div>
+</body>
+<script><![CDATA[
+// It is okay to increase the amount of invalidation in this test for correctness if necessary.
+description('Test that we only invalidate the style when changing an attribute referenced by a stylesheet. This test requires the internals object to work properly.');
+
+function shouldNeedStyleRecalc(expected) {
+    var testFunction = expected ? shouldBeTrue : shouldBeFalse;
+    testFunction("window.internals.nodeNeedsStyleRecalc(document.querySelectorAll(\"target\")[0])");
+    testFunction("window.internals.nodeNeedsStyleRecalc(document.querySelectorAll(\"target\")[1])");
+}
+
+function setAttribute(name, value) {
+    var allTargets = document.querySelectorAll("target");
+    allTargets[0].setAttribute(name, value);
+    allTargets[1].setAttribute(name, value);
+}
+
+function removeAttribute(name) {
+    var allTargets = document.querySelectorAll("target");
+    allTargets[0].removeAttribute(name);
+    allTargets[1].removeAttribute(name);
+}
+
+function getStyle() {
+    var allTargets = document.querySelectorAll("target");
+    getComputedStyle(allTargets[0]).color;
+    getComputedStyle(allTargets[1]).color;
+}
+
+// Force a layout to ensure we don't have dirty styles.
+var offsetTop = document.documentElement.offsetTop;
+shouldNeedStyleRecalc(false);
+
+debug("Changing the attribute 'foo', it is not referenced by any stylesheet and should not cause any invalidation.");
+setAttribute("foo", "bar");
+shouldNeedStyleRecalc(false);
+
+debug("Changing the attribute 'CamelCase'. It is used by the stylesheet and should cause the target to be invalidated.");
+setAttribute("CamelCase", "");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false);
+
+debug("Removing the attribute should also invalidate the style.");
+removeAttribute("CamelCase");
+shouldNeedStyleRecalc(true);
+
+debug("Getting the computed style should for the style to be resolved.");
+getStyle();
+shouldNeedStyleRecalc(false)
+
+debug("Changing the attribute 'camelcase'. Since XML attributes are case sensitive, this does not invalidate the style since it is a different attribute.");
+setAttribute("camelcase", "");
+shouldNeedStyleRecalc(false);
+
+debug("Changing the attribute 'CAMELCASE'. Same deal, this is a different attribute.");
+setAttribute("CAMELCASE", "");
+shouldNeedStyleRecalc(false);
+]]></script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/css/attribute-style-update-html-expected.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-update-html-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-update-html-expected.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+}
+.background {
+    background-color: rgb(1, 2, 3);
+}
+.border {
+    border: 1px black solid;
+}
+.color {
+    color: pink;
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling of elements based on their attributes. Since HTML processes attribute as case-insensitive, any case varation should work. This test passes if every triplet looks the same in both series and if it matches the reference.</p>
+    <div>
+        <target>No attribute</target>
+        <target class="background">lowercase initial attribute</target>
+        <target class="background">LOWERCASE initial attribute</target>
+        <target class="background">LowerCase initial attribute</target>
+
+        <target class="border">UPPERCASE initial attribute</target>
+        <target class="border">uppercase initial attribute</target>
+        <target class="border">UpperCase initial attribute</target>
+
+        <target class="color">CamelCase initial attribute</target>
+        <target class="color">camelcase initial attribute</target>
+        <target class="color">CAMELCASE initial attribute</target>
+
+        <target class="background border color">LowerCase UpperCase CAMELCASE initial attributes</target>
+        <target class="background border color">LowerCase UpperCase CAMELCASE initial attributes</target>
+        <target class="background border color">LowerCase UpperCase CAMELCASE initial attributes</target>
+    </div>
+    <div>
+        <target>No attribute</target>
+        <target class="background">lowercase dynamic attribute</target>
+        <target class="background">LOWERCASE dynamic attribute</target>
+        <target class="background">LowerCase dynamic attribute</target>
+
+        <target class="border">UPPERCASE dynamic attribute</target>
+        <target class="border">uppercase dynamic attribute</target>
+        <target class="border">UpperCase dynamic attribute</target>
+
+        <target class="color">CamelCase dynamic attribute</target>
+        <target class="color">camelcase dynamic attribute</target>
+        <target class="color">CAMELCASE dynamic attribute</target>
+
+        <target class="background border color">LowerCase UpperCase CAMELCASE dynamic attributes</target>
+        <target class="background border color">LowerCase UpperCase CAMELCASE dynamic attributes</target>
+        <target class="background border color">LowerCase UpperCase CAMELCASE dynamic attributes</target>
+    </div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/css/attribute-style-update-html.html (0 => 173012)


--- trunk/LayoutTests/fast/css/attribute-style-update-html.html	                        (rev 0)
+++ trunk/LayoutTests/fast/css/attribute-style-update-html.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style>
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+}
+[lowercase] {
+    background-color: rgb(1, 2, 3);
+}
+[UPPERCASE] {
+    border: 1px black solid;
+}
+[CamelCase] {
+    color: pink;
+}
+</style>
+</head>
+<body>
+    <p>This test checks the styling of elements based on their attributes. Since HTML processes attribute as case-insensitive, any case varation should work. This test passes if every triplet looks the same in both series and if it matches the reference.</p>
+    <div id="initial">
+        <target>No attribute</target>
+        <target lowercase>lowercase initial attribute</target>
+        <target LOWERCASE>LOWERCASE initial attribute</target>
+        <target LowerCase>LowerCase initial attribute</target>
+
+        <target UPPERCASE>UPPERCASE initial attribute</target>
+        <target uppercase>uppercase initial attribute</target>
+        <target UpperCase>UpperCase initial attribute</target>
+
+        <target CamelCase>CamelCase initial attribute</target>
+        <target camelcase>camelcase initial attribute</target>
+        <target CAMELCASE>CAMELCASE initial attribute</target>
+
+        <target lowercase UPPERCASE CamelCase>LowerCase UpperCase CAMELCASE initial attributes</target>
+        <target LOWERCASE uppercase camelcase>LowerCase UpperCase CAMELCASE initial attributes</target>
+        <target LowerCase UpperCase CAMELCASE>LowerCase UpperCase CAMELCASE initial attributes</target>
+    </div>
+    <div id="dynamic">
+        <target>No attribute</target>
+        <target>lowercase dynamic attribute</target>
+        <target>LOWERCASE dynamic attribute</target>
+        <target>LowerCase dynamic attribute</target>
+
+        <target>UPPERCASE dynamic attribute</target>
+        <target>uppercase dynamic attribute</target>
+        <target>UpperCase dynamic attribute</target>
+
+        <target>CamelCase dynamic attribute</target>
+        <target>camelcase dynamic attribute</target>
+        <target>CAMELCASE dynamic attribute</target>
+
+        <target>LowerCase UpperCase CAMELCASE dynamic attributes</target>
+        <target>LowerCase UpperCase CAMELCASE dynamic attributes</target>
+        <target>LowerCase UpperCase CAMELCASE dynamic attributes</target>
+    </div>
+</body>
+<script>
+window.addEventListener("load", function() {
+    forcedLayout = document.documentElement.offsetTop;
+
+    var allDynamicTargets = document.querySelectorAll("#dynamic>target");
+    allDynamicTargets[1].setAttribute("lowercase", "");
+    allDynamicTargets[2].setAttribute("LOWERCASE", "");
+    allDynamicTargets[3].setAttribute("LowerCase", "");
+
+    allDynamicTargets[4].setAttribute("UPPERCASE", "");
+    allDynamicTargets[5].setAttribute("uppercase", "");
+    allDynamicTargets[6].setAttribute("UpperCase", "");
+
+    allDynamicTargets[7].setAttribute("CamelCase", "");
+    allDynamicTargets[8].setAttribute("camelcase", "");
+    allDynamicTargets[9].setAttribute("CAMELCASE", "");
+
+    allDynamicTargets[10].setAttribute("lowercase", "");
+    allDynamicTargets[10].setAttribute("UPPERCASE", "");
+    allDynamicTargets[10].setAttribute("CamelCase", "");
+    allDynamicTargets[11].setAttribute("LOWERCASE", "");
+    allDynamicTargets[11].setAttribute("uppercase", "");
+    allDynamicTargets[11].setAttribute("camelcase", "");
+    allDynamicTargets[12].setAttribute("LowerCase", "");
+    allDynamicTargets[12].setAttribute("UpperCase", "");
+    allDynamicTargets[12].setAttribute("CAMELCASE", "");
+});
+</script>
+</html>

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-html-expected.txt (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-html-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-html-expected.txt	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,121 @@
+Test the basic cases of style update for attribute selectors for HTML.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state does not match anything, there are no attributes on the targets.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "lowercase", the background-color should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "lowercase", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "LOWERCASE", the background-color should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "LOWERCASE", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "LowerCase", the background-color should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "UPPERCASE", the fill-opacity should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "UPPERCASE", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "uppercase", the fill-opacity should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "uppercase", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "UpperCase", the fill-opacity should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "CamelCase", the color should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(4, 5, 6)"
+Removing "CamelCase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "camelcase", the color should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(4, 5, 6)"
+Removing "camelcase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "CAMELCASE", the color should match because the document is HTML and has case-insensitive attribute matching.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(4, 5, 6)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-html.html (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-html.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-html.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+}
+[lowercase] {
+    background-color: rgb(1, 2, 3);
+}
+[UPPERCASE] {
+    fill-opacity: 0.5;
+}
+[CamelCase] {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div>
+        <!-- With renderer -->
+        <target></target>
+    </div>
+    <div style="display:none;">
+        <!-- Without renderer -->
+        <target></target>
+    </div>
+</body>
+<script>
+description('Test the basic cases of style update for attribute selectors for HTML.');
+
+var noMatch = 0;
+var matchLowerCase = 1;
+var matchUpperCase = 1 << 1;
+var matchCamelCase = 1 << 2;
+
+function testColor(mask) {
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+function setAttribute(attribute, value) {
+    var allTargets = document.querySelectorAll("target");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].setAttribute(attribute, value);
+}
+
+function removeAttribute(attribute) {
+    var allTargets = document.querySelectorAll("target");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].removeAttribute(attribute);
+}
+
+debug("Initial state does not match anything, there are no attributes on the targets.");
+testColor(noMatch);
+
+debug("Adding \"lowercase\", the background-color should match.");
+setAttribute("lowercase");
+testColor(matchLowerCase);
+
+debug("Removing \"lowercase\", the background-color should no longer match.");
+removeAttribute("lowercase");
+testColor(noMatch);
+
+debug("Adding \"LOWERCASE\", the background-color should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("LOWERCASE");
+testColor(matchLowerCase);
+
+debug("Removing \"LOWERCASE\", the background-color should no longer match.");
+removeAttribute("LOWERCASE");
+testColor(noMatch);
+
+debug("Adding \"LowerCase\", the background-color should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("LOWERCASE");
+testColor(matchLowerCase);
+
+
+debug("Adding \"UPPERCASE\", the fill-opacity should match.");
+setAttribute("UPPERCASE");
+testColor(matchLowerCase | matchUpperCase);
+
+debug("Removing \"UPPERCASE\", the fill-opacity should no longer match.");
+removeAttribute("UPPERCASE");
+testColor(matchLowerCase);
+
+debug("Adding \"uppercase\", the fill-opacity should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("uppercase");
+testColor(matchLowerCase | matchUpperCase);
+
+debug("Removing \"uppercase\", the fill-opacity should no longer match.");
+removeAttribute("uppercase");
+testColor(matchLowerCase);
+
+debug("Adding \"UpperCase\", the fill-opacity should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("UpperCase");
+testColor(matchLowerCase | matchUpperCase);
+
+
+debug("Adding \"CamelCase\", the color should match.");
+setAttribute("CamelCase");
+testColor(matchLowerCase | matchUpperCase | matchCamelCase);
+
+debug("Removing \"CamelCase\", the color should no longer match.");
+removeAttribute("CamelCase");
+testColor(matchLowerCase | matchUpperCase);
+
+debug("Adding \"camelcase\", the color should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("camelcase");
+testColor(matchLowerCase | matchUpperCase | matchCamelCase);
+
+debug("Removing \"camelcase\", the color should no longer match.");
+removeAttribute("camelcase");
+testColor(matchLowerCase | matchUpperCase);
+
+debug("Adding \"CAMELCASE\", the color should match because the document is HTML and has case-insensitive attribute matching.");
+setAttribute("CAMELCASE");
+testColor(matchLowerCase | matchUpperCase | matchCamelCase);
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html-expected.txt (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html-expected.txt	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,121 @@
+Test the basic cases of style update for attribute selectors for SVG inside a HTML document.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state does not match anything, there are no attributes on the targets.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "lowercase", the background-color should match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Removing "lowercase", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "LOWERCASE", the background-color should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Removing "LOWERCASE", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "LowerCase", the background-color should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "UPPERCASE", the fill-opacity should match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Removing "UPPERCASE", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "uppercase", the fill-opacity should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Removing "uppercase", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "UpperCase", the fill-opacity should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "CamelCase", the color should match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(4, 5, 6)"
+Removing "CamelCase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "camelcase", the color should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Removing "camelcase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+Adding "CAMELCASE", the color should not match because SVG elements are XML, their attribute names are case sensitive.
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("rect")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("rect")[1]).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html.html (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html.html	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-svg-in-html.html	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,133 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<style>
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+}
+[lowercase] {
+    background-color: rgb(1, 2, 3);
+}
+[UPPERCASE] {
+    fill-opacity: 0.5;
+}
+[CamelCase] {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div>
+        <!-- With renderer -->
+        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="margin-top:50px">
+            <rect id=rect2 x="0" y="0" width="50" height="50" style="fill:green" />
+        </svg>
+    </div>
+    <div style="display:none;">
+        <!-- Without renderer -->
+        <svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100" style="margin-top:50px">
+            <rect id=rect2 x="0" y="0" width="50" height="50" style="fill:green" />
+        </svg>
+    </div>
+</body>
+<script>
+description('Test the basic cases of style update for attribute selectors for SVG inside a HTML document.');
+
+var noMatch = 0;
+var matchLowerCase = 1;
+var matchUpperCase = 1 << 1;
+var matchCamelCase = 1 << 2;
+
+function testColor(mask) {
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[0]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[1]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[0]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[1]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[0]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("rect")[1]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+function setAttribute(attribute, value) {
+    var allTargets = document.querySelectorAll("rect");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].setAttribute(attribute, value);
+}
+
+function removeAttribute(attribute) {
+    var allTargets = document.querySelectorAll("rect");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].removeAttribute(attribute);
+}
+
+debug("Initial state does not match anything, there are no attributes on the targets.");
+testColor(noMatch);
+
+debug("Adding \"lowercase\", the background-color should match.");
+setAttribute("lowercase");
+testColor(matchLowerCase);
+
+debug("Removing \"lowercase\", the background-color should no longer match.");
+removeAttribute("lowercase");
+testColor(noMatch);
+
+debug("Adding \"LOWERCASE\", the background-color should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("LOWERCASE");
+testColor(noMatch);
+
+debug("Removing \"LOWERCASE\", the background-color should no longer match.");
+removeAttribute("LOWERCASE");
+testColor(noMatch);
+
+debug("Adding \"LowerCase\", the background-color should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("LOWERCASE");
+testColor(noMatch);
+
+
+debug("Adding \"UPPERCASE\", the fill-opacity should match.");
+setAttribute("UPPERCASE");
+testColor(matchUpperCase);
+
+debug("Removing \"UPPERCASE\", the fill-opacity should no longer match.");
+removeAttribute("UPPERCASE");
+testColor(noMatch);
+
+debug("Adding \"uppercase\", the fill-opacity should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("uppercase");
+testColor(noMatch);
+
+debug("Removing \"uppercase\", the fill-opacity should no longer match.");
+removeAttribute("uppercase");
+testColor(noMatch);
+
+debug("Adding \"UpperCase\", the fill-opacity should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("UpperCase");
+testColor(noMatch);
+
+
+debug("Adding \"CamelCase\", the color should match.");
+setAttribute("CamelCase");
+testColor(matchCamelCase);
+
+debug("Removing \"CamelCase\", the color should no longer match.");
+removeAttribute("CamelCase");
+testColor(noMatch);
+
+debug("Adding \"camelcase\", the color should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("camelcase");
+testColor(noMatch);
+
+debug("Removing \"camelcase\", the color should no longer match.");
+removeAttribute("camelcase");
+testColor(noMatch);
+
+debug("Adding \"CAMELCASE\", the color should not match because SVG elements are XML, their attribute names are case sensitive.");
+setAttribute("CAMELCASE");
+testColor(noMatch);
+</script>
+<script src=""
+</html>

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml-expected.txt (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml-expected.txt	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,121 @@
+Test the basic cases of style update for attribute selectors for XHTML. Unlike HTML, XHTML attribute matching is case sensitive.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Initial state does not match anything, there are no attributes on the targets.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "lowercase", the background-color should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(1, 2, 3)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "lowercase", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "LOWERCASE", the background-color should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "LOWERCASE", the background-color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "LowerCase", the background-color should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "UPPERCASE", the fill-opacity should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "0.5"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "UPPERCASE", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "uppercase", the fill-opacity should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "uppercase", the fill-opacity should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "UpperCase", the fill-opacity should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "CamelCase", the color should match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(4, 5, 6)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(4, 5, 6)"
+Removing "CamelCase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "camelcase", the color should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Removing "camelcase", the color should no longer match.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+Adding "CAMELCASE", the color should match because XML uses case-sensitive attributes.
+PASS getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor is "rgb(255, 255, 255)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity is "1"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(0, 0, 0)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(0, 0, 0)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml.xhtml (0 => 173012)


--- trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml.xhtml	                        (rev 0)
+++ trunk/LayoutTests/fast/selectors/attribute-style-update-xhtml.xhtml	2014-08-27 19:16:51 UTC (rev 173012)
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<script src=""
+<style>
+* {
+    background-color: white;
+    color: black;
+    fill-opacity: 1;
+}
+[lowercase] {
+    background-color: rgb(1, 2, 3);
+}
+[UPPERCASE] {
+    fill-opacity: 0.5;
+}
+[CamelCase] {
+    color: rgb(4, 5, 6);
+}
+</style>
+</head>
+<body>
+    <div>
+        <!-- With renderer -->
+        <target></target>
+    </div>
+    <div style="display:none;">
+        <!-- Without renderer -->
+        <target></target>
+    </div>
+</body>
+<script><![CDATA[
+description('Test the basic cases of style update for attribute selectors for XHTML. Unlike HTML, XHTML attribute matching is case sensitive.');
+
+var noMatch = 0;
+var matchLowerCase = 1;
+var matchUpperCase = 1 << 1;
+var matchCamelCase = 1 << 2;
+
+function testColor(mask) {
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).backgroundColor', (mask & matchLowerCase) ? 'rgb(1, 2, 3)' : 'rgb(255, 255, 255)');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).fillOpacity', (mask & matchUpperCase) ? '0.5' : '1');
+
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[0]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+    shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[1]).color', (mask & matchCamelCase) ? 'rgb(4, 5, 6)' : 'rgb(0, 0, 0)');
+}
+
+function setAttribute(attribute, value) {
+    var allTargets = document.querySelectorAll("target");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].setAttribute(attribute, value);
+}
+
+function removeAttribute(attribute) {
+    var allTargets = document.querySelectorAll("target");
+    for (var i = 0; i < allTargets.length; ++i)
+        allTargets[i].removeAttribute(attribute);
+}
+
+debug("Initial state does not match anything, there are no attributes on the targets.");
+testColor(noMatch);
+
+debug("Adding \"lowercase\", the background-color should match.");
+setAttribute("lowercase");
+testColor(matchLowerCase);
+
+debug("Removing \"lowercase\", the background-color should no longer match.");
+removeAttribute("lowercase");
+testColor(noMatch);
+
+debug("Adding \"LOWERCASE\", the background-color should match because XML uses case-sensitive attributes.");
+setAttribute("LOWERCASE");
+testColor(noMatch);
+
+debug("Removing \"LOWERCASE\", the background-color should no longer match.");
+removeAttribute("LOWERCASE");
+testColor(noMatch);
+
+debug("Adding \"LowerCase\", the background-color should match because XML uses case-sensitive attributes.");
+setAttribute("LOWERCASE");
+testColor(noMatch);
+
+
+debug("Adding \"UPPERCASE\", the fill-opacity should match.");
+setAttribute("UPPERCASE");
+testColor(matchUpperCase);
+
+debug("Removing \"UPPERCASE\", the fill-opacity should no longer match.");
+removeAttribute("UPPERCASE");
+testColor(noMatch);
+
+debug("Adding \"uppercase\", the fill-opacity should match because XML uses case-sensitive attributes.");
+setAttribute("uppercase");
+testColor(noMatch);
+
+debug("Removing \"uppercase\", the fill-opacity should no longer match.");
+removeAttribute("uppercase");
+testColor(noMatch);
+
+debug("Adding \"UpperCase\", the fill-opacity should match because XML uses case-sensitive attributes.");
+setAttribute("UpperCase");
+testColor(noMatch);
+
+
+debug("Adding \"CamelCase\", the color should match.");
+setAttribute("CamelCase");
+testColor(matchCamelCase);
+
+debug("Removing \"CamelCase\", the color should no longer match.");
+removeAttribute("CamelCase");
+testColor(noMatch);
+
+debug("Adding \"camelcase\", the color should match because XML uses case-sensitive attributes.");
+setAttribute("camelcase");
+testColor(noMatch);
+
+debug("Removing \"camelcase\", the color should no longer match.");
+removeAttribute("camelcase");
+testColor(noMatch);
+
+debug("Adding \"CAMELCASE\", the color should match because XML uses case-sensitive attributes.");
+setAttribute("CAMELCASE");
+testColor(noMatch);
+]]></script>
+<script src=""
+</html>

Modified: trunk/Source/WebCore/ChangeLog (173011 => 173012)


--- trunk/Source/WebCore/ChangeLog	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/ChangeLog	2014-08-27 19:16:51 UTC (rev 173012)
@@ -1,5 +1,47 @@
 2014-08-27  Benjamin Poulain  <[email protected]>
 
+        Updating attributes on HTML elements do not invalidate the style correctly unless the attribute name is lowercase in the stylesheet
+        https://bugs.webkit.org/show_bug.cgi?id=136270
+
+        Reviewed by Andreas Kling.
+
+        In HTML, WebKit treats every attribute name lowercase to implement case-insensitive matching.
+        When invalidating style, the StyleResolver was ignoring HTML and always using the XML names.
+
+        This patch split the names on RuleFeatureSet in two sets: one for XML, one for HTML.
+        In StyleResolver, the name used depends on the type of the element being updated.
+
+        This patch also adds nodeNeedsStyleRecalc() to Internals to test the optimization and various cases
+        of style update.
+
+        Tests: fast/css/attribute-for-content-property-style-update-html.html
+               fast/css/attribute-for-content-property-style-update-xhtml.xhtml
+               fast/css/attribute-style-invalidation-optimization-html.html
+               fast/css/attribute-style-invalidation-optimization-xhtml.xhtml
+               fast/css/attribute-style-update-html.html
+               fast/selectors/attribute-style-update-html.html
+               fast/selectors/attribute-style-update-svg-in-html.html
+               fast/selectors/attribute-style-update-xhtml.xhtml
+
+        * css/RuleFeature.cpp:
+        (WebCore::RuleFeatureSet::collectFeaturesFromSelector):
+        (WebCore::RuleFeatureSet::add):
+        (WebCore::RuleFeatureSet::clear):
+        * css/RuleFeature.h:
+        * css/StyleResolver.cpp:
+        (WebCore::StyleResolver::applyProperty):
+        * css/StyleResolver.h:
+        (WebCore::StyleResolver::hasSelectorForAttribute):
+        * dom/Element.cpp:
+        (WebCore::Element::willModifyAttribute):
+        * testing/Internals.cpp:
+        (WebCore::Internals::address):
+        (WebCore::Internals::nodeNeedsStyleRecalc):
+        * testing/Internals.h:
+        * testing/Internals.idl:
+
+2014-08-27  Benjamin Poulain  <[email protected]>
+
         Update the CSS Grammar selector names to get closer to the latest terminology
         https://bugs.webkit.org/show_bug.cgi?id=136277
 

Modified: trunk/Source/WebCore/css/RuleFeature.cpp (173011 => 173012)


--- trunk/Source/WebCore/css/RuleFeature.cpp	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/css/RuleFeature.cpp	2014-08-27 19:16:51 UTC (rev 173012)
@@ -39,9 +39,10 @@
         idsInRules.add(selector->value().impl());
     else if (selector->m_match == CSSSelector::Class)
         classesInRules.add(selector->value().impl());
-    else if (selector->isAttributeSelector())
-        attrsInRules.add(selector->attribute().localName().impl());
-    else if (selector->m_match == CSSSelector::PseudoElement) {
+    else if (selector->isAttributeSelector()) {
+        attributeCanonicalLocalNamesInRules.add(selector->attributeCanonicalLocalName().impl());
+        attributeLocalNamesInRules.add(selector->attribute().localName().impl());
+    } else if (selector->m_match == CSSSelector::PseudoElement) {
         switch (selector->pseudoElementType()) {
         case CSSSelector::PseudoElementFirstLine:
             usesFirstLineRules = true;
@@ -61,15 +62,10 @@
 
 void RuleFeatureSet::add(const RuleFeatureSet& other)
 {
-    HashSet<AtomicStringImpl*>::const_iterator end = other.idsInRules.end();
-    for (HashSet<AtomicStringImpl*>::const_iterator it = other.idsInRules.begin(); it != end; ++it)
-        idsInRules.add(*it);
-    end = other.classesInRules.end();
-    for (HashSet<AtomicStringImpl*>::const_iterator it = other.classesInRules.begin(); it != end; ++it)
-        classesInRules.add(*it);
-    end = other.attrsInRules.end();
-    for (HashSet<AtomicStringImpl*>::const_iterator it = other.attrsInRules.begin(); it != end; ++it)
-        attrsInRules.add(*it);
+    idsInRules.add(other.idsInRules.begin(), other.idsInRules.end());
+    classesInRules.add(other.classesInRules.begin(), other.classesInRules.end());
+    attributeCanonicalLocalNamesInRules.add(other.attributeCanonicalLocalNamesInRules.begin(), other.attributeCanonicalLocalNamesInRules.end());
+    attributeLocalNamesInRules.add(other.attributeLocalNamesInRules.begin(), other.attributeLocalNamesInRules.end());
     siblingRules.appendVector(other.siblingRules);
     uncommonAttributeRules.appendVector(other.uncommonAttributeRules);
     usesFirstLineRules = usesFirstLineRules || other.usesFirstLineRules;
@@ -81,7 +77,8 @@
 {
     idsInRules.clear();
     classesInRules.clear();
-    attrsInRules.clear();
+    attributeCanonicalLocalNamesInRules.clear();
+    attributeLocalNamesInRules.clear();
     siblingRules.clear();
     uncommonAttributeRules.clear();
     usesFirstLineRules = false;

Modified: trunk/Source/WebCore/css/RuleFeature.h (173011 => 173012)


--- trunk/Source/WebCore/css/RuleFeature.h	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/css/RuleFeature.h	2014-08-27 19:16:51 UTC (rev 173012)
@@ -58,7 +58,8 @@
 
     HashSet<AtomicStringImpl*> idsInRules;
     HashSet<AtomicStringImpl*> classesInRules;
-    HashSet<AtomicStringImpl*> attrsInRules;
+    HashSet<AtomicStringImpl*> attributeCanonicalLocalNamesInRules;
+    HashSet<AtomicStringImpl*> attributeLocalNamesInRules;
     Vector<RuleFeature> siblingRules;
     Vector<RuleFeature> uncommonAttributeRules;
     bool usesFirstLineRules;

Modified: trunk/Source/WebCore/css/StyleResolver.cpp (173011 => 173012)


--- trunk/Source/WebCore/css/StyleResolver.cpp	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/css/StyleResolver.cpp	2014-08-27 19:16:51 UTC (rev 173012)
@@ -2147,7 +2147,8 @@
                     state.style()->setContent(value.isNull() ? emptyAtom : value.impl(), didSet);
                     didSet = true;
                     // Register the fact that the attribute value affects the style.
-                    m_ruleSets.features().attrsInRules.add(attr.localName().impl());
+                    m_ruleSets.features().attributeCanonicalLocalNamesInRules.add(attr.localName().impl());
+                    m_ruleSets.features().attributeLocalNamesInRules.add(attr.localName().impl());
                 } else if (contentValue->isCounter()) {
                     Counter* counterValue = contentValue->getCounterValue();
                     EListStyleType listStyleType = NoneListStyle;
@@ -2202,7 +2203,8 @@
                 state.style()->setContentAltText(value.isNull() ? emptyAtom : value.impl());
                 didSet = true;
                 // Register the fact that the attribute value affects the style.
-                m_ruleSets.features().attrsInRules.add(attr.localName().impl());
+                m_ruleSets.features().attributeCanonicalLocalNamesInRules.add(attr.localName().impl());
+                m_ruleSets.features().attributeLocalNamesInRules.add(attr.localName().impl());
             }
             if (!didSet)
                 state.style()->setContentAltText(emptyAtom);

Modified: trunk/Source/WebCore/css/StyleResolver.h (173011 => 173012)


--- trunk/Source/WebCore/css/StyleResolver.h	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/css/StyleResolver.h	2014-08-27 19:16:51 UTC (rev 173012)
@@ -214,7 +214,7 @@
 
     bool hasSelectorForId(const AtomicString&) const;
     bool hasSelectorForClass(const AtomicString&) const;
-    bool hasSelectorForAttribute(const AtomicString&) const;
+    bool hasSelectorForAttribute(const Element&, const AtomicString&) const;
 
     CSSFontSelector* fontSelector() const { return m_fontSelector.get(); }
 #if ENABLE(CSS_DEVICE_ADAPTATION)
@@ -547,10 +547,12 @@
     friend bool operator!=(const MatchRanges&, const MatchRanges&);
 };
 
-inline bool StyleResolver::hasSelectorForAttribute(const AtomicString &attributeName) const
+inline bool StyleResolver::hasSelectorForAttribute(const Element& element, const AtomicString &attributeName) const
 {
     ASSERT(!attributeName.isEmpty());
-    return m_ruleSets.features().attrsInRules.contains(attributeName.impl());
+    if (element.isHTMLElement())
+        return m_ruleSets.features().attributeCanonicalLocalNamesInRules.contains(attributeName.impl());
+    return m_ruleSets.features().attributeLocalNamesInRules.contains(attributeName.impl());
 }
 
 inline bool StyleResolver::hasSelectorForClass(const AtomicString& classValue) const

Modified: trunk/Source/WebCore/dom/Element.cpp (173011 => 173012)


--- trunk/Source/WebCore/dom/Element.cpp	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/dom/Element.cpp	2014-08-27 19:16:51 UTC (rev 173012)
@@ -2707,7 +2707,7 @@
 
     if (oldValue != newValue) {
         auto styleResolver = document().styleResolverIfExists();
-        if (styleResolver && styleResolver->hasSelectorForAttribute(name.localName()))
+        if (styleResolver && styleResolver->hasSelectorForAttribute(*this, name.localName()))
             setNeedsStyleRecalc();
     }
 

Modified: trunk/Source/WebCore/testing/Internals.cpp (173011 => 173012)


--- trunk/Source/WebCore/testing/Internals.cpp	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/testing/Internals.cpp	2014-08-27 19:16:51 UTC (rev 173012)
@@ -347,10 +347,17 @@
 
 String Internals::address(Node* node)
 {
-    char buf[32];
-    sprintf(buf, "%p", node);
+    return String::format("%p", node);
+}
 
-    return String(buf);
+bool Internals::nodeNeedsStyleRecalc(Node* node, ExceptionCode& exception)
+{
+    if (!node) {
+        exception = INVALID_ACCESS_ERR;
+        return false;
+    }
+
+    return node->needsStyleRecalc();
 }
 
 String Internals::description(Deprecated::ScriptValue value)

Modified: trunk/Source/WebCore/testing/Internals.h (173011 => 173012)


--- trunk/Source/WebCore/testing/Internals.h	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/testing/Internals.h	2014-08-27 19:16:51 UTC (rev 173012)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Google Inc. All rights reserved.
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -75,6 +75,7 @@
     String elementRenderTreeAsText(Element*, ExceptionCode&);
 
     String address(Node*);
+    bool nodeNeedsStyleRecalc(Node*, ExceptionCode&);
     String description(Deprecated::ScriptValue);
 
     bool isPreloaded(const String& url);
@@ -107,10 +108,6 @@
 
     Node* treeScopeRootNode(Node*, ExceptionCode&);
     Node* parentTreeScope(Node*, ExceptionCode&);
-    bool hasSelectorForIdInShadow(Element* host, const String& idValue, ExceptionCode&);
-    bool hasSelectorForClassInShadow(Element* host, const String& className, ExceptionCode&);
-    bool hasSelectorForAttributeInShadow(Element* host, const String& attributeName, ExceptionCode&);
-    bool hasSelectorForPseudoClassInShadow(Element* host, const String& pseudoClass, ExceptionCode&);
 
     bool attached(Node*, ExceptionCode&);
 

Modified: trunk/Source/WebCore/testing/Internals.idl (173011 => 173012)


--- trunk/Source/WebCore/testing/Internals.idl	2014-08-27 19:15:52 UTC (rev 173011)
+++ trunk/Source/WebCore/testing/Internals.idl	2014-08-27 19:16:51 UTC (rev 173012)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2012 Google Inc. All rights reserved.
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -28,6 +28,7 @@
     NoInterfaceObject,
 ] interface Internals {
     DOMString address(Node node);
+    [RaisesException] boolean nodeNeedsStyleRecalc(Node node);
     DOMString description(any value);
 
     [RaisesException] DOMString elementRenderTreeAsText(Element element);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to