https://bugs.webkit.org/show_bug.cgi?id=149189
Patch by Benjamin Poulain <bpoulain@apple.com> on 2015-09-15
Reviewed by Antti Koivisto.
Source/WebCore:
Style::resolveTree() made the assumption that inline style changes only affect
descendants and should not participate in "StyleRecalcAffectsNextSiblingElementStyle".
That was wrong. If the inline style change through CSSOM, it can cause the creation
of a style attribute, which is observable through "StyleRecalcAffectsNextSiblingElementStyle".
This patch removes the incorrect assumption. Style invalidation is always propagated now.
Tests: fast/css/style-attribute-invalidation-propagates-to-counted-siblings.html
fast/css/style-attribute-invalidation-propagates-to-direct-siblings.html
fast/css/style-attribute-invalidation-propagates-to-indirect-siblings.html
* css/PropertySetCSSStyleDeclaration.cpp:
(WebCore::InlineCSSStyleDeclaration::didMutate): Deleted.
* dom/StyledElement.cpp:
(WebCore::StyledElement::inlineStyleChanged):
* dom/StyledElement.h:
(WebCore::StyledElement::invalidateStyleAttribute):
Clean up inline-style invalidation a tiny bit.
* style/StyleResolveTree.cpp:
(WebCore::Style::resolveTree):
Fix the bug.
LayoutTests:
* fast/css/style-attribute-invalidation-propagates-to-counted-siblings-expected.txt: Added.
* fast/css/style-attribute-invalidation-propagates-to-counted-siblings.html: Added.
* fast/css/style-attribute-invalidation-propagates-to-direct-siblings-expected.txt: Added.
* fast/css/style-attribute-invalidation-propagates-to-direct-siblings.html: Added.
* fast/css/style-attribute-invalidation-propagates-to-indirect-siblings-expected.txt: Added.
* fast/css/style-attribute-invalidation-propagates-to-indirect-siblings.html: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@189836
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2015-09-15 Benjamin Poulain <bpoulain@apple.com>
+
+ Style invalidation affecting siblings does not work with inline-style changes
+ https://bugs.webkit.org/show_bug.cgi?id=149189
+
+ Reviewed by Antti Koivisto.
+
+ * fast/css/style-attribute-invalidation-propagates-to-counted-siblings-expected.txt: Added.
+ * fast/css/style-attribute-invalidation-propagates-to-counted-siblings.html: Added.
+ * fast/css/style-attribute-invalidation-propagates-to-direct-siblings-expected.txt: Added.
+ * fast/css/style-attribute-invalidation-propagates-to-direct-siblings.html: Added.
+ * fast/css/style-attribute-invalidation-propagates-to-indirect-siblings-expected.txt: Added.
+ * fast/css/style-attribute-invalidation-propagates-to-indirect-siblings.html: Added.
+
2015-09-15 Myles C. Maxfield <mmaxfield@apple.com>
Nested isolates can cause an infinite loop when laying out bidi runs
--- /dev/null
+Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+target {
+ color: black;
+}
+target:nth-child(2 of target, trigger[style]) {
+ color: pink;
+}
+</style>
+</head>
+<body>
+ <div>
+ <!-- With renderer -->
+ <trigger></trigger>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <target></target>
+ </div>
+ <div style="display:none;">
+ <!-- Without renderer -->
+ <trigger></trigger>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <target></target>
+ </div>
+</body>
+<script>
+
+description('Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.');
+
+function testTargetColor(expectedColor) {
+ let allTargets = document.querySelectorAll("target");
+ for (let i = 0; i < allTargets.length; ++i) {
+ shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[' + i + ']).color', expectedColor);
+ }
+}
+
+testTargetColor('rgb(0, 0, 0)');
+
+// Set a style through CSS OM.
+function setPropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.cursor = "auto";
+ }
+}
+setPropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+
+// If we remove the attribute, we should be back to normal.
+function removeStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].removeAttribute("style");
+ }
+}
+removeStyleAttribute();
+testTargetColor('rgb(0, 0, 0)');
+
+// Setting the style through a style attribute directly.
+function setStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].setAttribute("style", "alt: \"WebKit!\"");
+ }
+}
+setStyleAttribute();
+testTargetColor('rgb(255, 192, 203)');
+
+// Removing the property on the style attribute through CSSOM.
+// This leaves an empty style attribute.
+function removePropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.removeProperty("alt");
+ }
+}
+removePropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
--- /dev/null
+Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+target {
+ color: black;
+}
+trigger[style] + target {
+ color: pink;
+}
+</style>
+</head>
+<body>
+ <div>
+ <!-- With renderer -->
+ <trigger></trigger>
+ <target></target>
+ </div>
+ <div style="display:none;">
+ <!-- Without renderer -->
+ <trigger></trigger>
+ <target></target>
+ </div>
+</body>
+<script>
+
+description('Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.');
+
+function testTargetColor(expectedColor) {
+ let allTargets = document.querySelectorAll("target");
+ for (let i = 0; i < allTargets.length; ++i) {
+ shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[' + i + ']).color', expectedColor);
+ }
+}
+
+testTargetColor('rgb(0, 0, 0)');
+
+// Set a style through CSS OM.
+function setPropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.cursor = "auto";
+ }
+}
+setPropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+
+// If we remove the attribute, we should be back to normal.
+function removeStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].removeAttribute("style");
+ }
+}
+removeStyleAttribute();
+testTargetColor('rgb(0, 0, 0)');
+
+// Setting the style through a style attribute directly.
+function setStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].setAttribute("style", "alt: \"WebKit!\"");
+ }
+}
+setStyleAttribute();
+testTargetColor('rgb(255, 192, 203)');
+
+// Removing the property on the style attribute through CSSOM.
+// This leaves an empty style attribute.
+function removePropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.removeProperty("alt");
+ }
+}
+removePropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
--- /dev/null
+Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+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 getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[0]).color is "rgb(255, 192, 203)"
+PASS getComputedStyle(document.querySelectorAll("target")[1]).color is "rgb(255, 192, 203)"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
--- /dev/null
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+<style>
+target {
+ color: black;
+}
+trigger[style] ~ target {
+ color: pink;
+}
+</style>
+</head>
+<body>
+ <div>
+ <!-- With renderer -->
+ <trigger></trigger>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <target></target>
+ </div>
+ <div style="display:none;">
+ <!-- Without renderer -->
+ <trigger></trigger>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <padding></padding>
+ <target></target>
+ </div>
+</body>
+<script>
+
+description('Test that style invalidation through inline-style propagates correctly to siblings when a combinator requires it.');
+
+function testTargetColor(expectedColor) {
+ let allTargets = document.querySelectorAll("target");
+ for (let i = 0; i < allTargets.length; ++i) {
+ shouldBeEqualToString('getComputedStyle(document.querySelectorAll("target")[' + i + ']).color', expectedColor);
+ }
+}
+
+testTargetColor('rgb(0, 0, 0)');
+
+// Set a style through CSS OM.
+function setPropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.cursor = "auto";
+ }
+}
+setPropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+
+// If we remove the attribute, we should be back to normal.
+function removeStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].removeAttribute("style");
+ }
+}
+removeStyleAttribute();
+testTargetColor('rgb(0, 0, 0)');
+
+// Setting the style through a style attribute directly.
+function setStyleAttribute() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].setAttribute("style", "alt: \"WebKit!\"");
+ }
+}
+setStyleAttribute();
+testTargetColor('rgb(255, 192, 203)');
+
+// Removing the property on the style attribute through CSSOM.
+// This leaves an empty style attribute.
+function removePropertyWithCSSOM() {
+ let allTriggers = document.querySelectorAll("trigger");
+ for (let i = 0; i < allTriggers.length; ++i) {
+ allTriggers[i].style.removeProperty("alt");
+ }
+}
+removePropertyWithCSSOM()
+testTargetColor('rgb(255, 192, 203)');
+</script>
+<script src="../../resources/js-test-post.js"></script>
+</html>
+2015-09-15 Benjamin Poulain <bpoulain@apple.com>
+
+ Style invalidation affecting siblings does not work with inline-style changes
+ https://bugs.webkit.org/show_bug.cgi?id=149189
+
+ Reviewed by Antti Koivisto.
+
+ Style::resolveTree() made the assumption that inline style changes only affect
+ descendants and should not participate in "StyleRecalcAffectsNextSiblingElementStyle".
+ That was wrong. If the inline style change through CSSOM, it can cause the creation
+ of a style attribute, which is observable through "StyleRecalcAffectsNextSiblingElementStyle".
+
+ This patch removes the incorrect assumption. Style invalidation is always propagated now.
+
+ Tests: fast/css/style-attribute-invalidation-propagates-to-counted-siblings.html
+ fast/css/style-attribute-invalidation-propagates-to-direct-siblings.html
+ fast/css/style-attribute-invalidation-propagates-to-indirect-siblings.html
+
+ * css/PropertySetCSSStyleDeclaration.cpp:
+ (WebCore::InlineCSSStyleDeclaration::didMutate): Deleted.
+ * dom/StyledElement.cpp:
+ (WebCore::StyledElement::inlineStyleChanged):
+ * dom/StyledElement.h:
+ (WebCore::StyledElement::invalidateStyleAttribute):
+ Clean up inline-style invalidation a tiny bit.
+
+ * style/StyleResolveTree.cpp:
+ (WebCore::Style::resolveTree):
+ Fix the bug.
+
2015-09-15 Joseph Pecoraro <pecoraro@apple.com>
Web Inspector: Paused Debugger prevents page reload
if (!m_parentElement)
return;
- m_parentElement->setNeedsStyleRecalc(InlineStyleChange);
m_parentElement->invalidateStyleAttribute();
StyleAttributeMutationScope(this).didInvalidateStyleAttr();
}
void StyledElement::inlineStyleChanged()
{
- setNeedsStyleRecalc(InlineStyleChange);
- ASSERT(elementData());
- elementData()->setStyleAttributeIsDirty(true);
+ invalidateStyleAttribute();
InspectorInstrumentation::didInvalidateStyleAttr(document(), *this);
}
{
ASSERT(elementData());
elementData()->setStyleAttributeIsDirty(true);
+ setNeedsStyleRecalc(InlineStyleChange);
}
inline const StyleProperties* StyledElement::presentationAttributeStyle()
if (childElement.styleIsAffectedByPreviousSibling())
childElement.setNeedsStyleRecalc();
elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
- } else if (childElement.styleChangeType() >= FullStyleChange)
+ } else if (childElement.needsStyleRecalc())
elementNeedingStyleRecalcAffectsNextSiblingElementStyle = childElement.affectsNextSiblingElementStyle();
if (change >= Inherit || childElement.childNeedsStyleRecalc() || childElement.needsStyleRecalc()) {
parentPusher.push();