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);