CSS rules not being applied when a hidden field is inserted between an...

CSS rules not being applied when a hidden field is inserted between an input[type=checkbox] and a label
https://bugs.webkit.org/show_bug.cgi?id=66887

Patch by Kulanthaivel Palanichamy <kulanthaivel@codeaurora.org> on 2011-09-09
Reviewed by David Hyatt.

Source/WebCore:

Test: fast/css/adjacent-sibling-selector.html

This patch addresses the problem of elements not getting their style recomputed
when they are affected by direct adjacent sibling rules and one of their sibling in
their corresponding rules is modified dynamically.

* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::canShareStyleWithElement):
(WebCore::parentStylePreventsSharing):
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkSelector):
* dom/Element.cpp:
(WebCore::Element::recalcStyle):
(WebCore::checkForSiblingStyleChanges):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::RenderStyle):
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::affectedByDirectAdjacentRules):
(WebCore::InheritedFlags::setAffectedByDirectAdjacentRules):

LayoutTests:

* fast/css/adjacent-sibling-selector-expected.txt: Added.
* fast/css/adjacent-sibling-selector.html: Added.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@94887 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 7febe4d2
2011-09-09 Kulanthaivel Palanichamy <kulanthaivel@codeaurora.org>
CSS rules not being applied when a hidden field is inserted between an input[type=checkbox] and a label
https://bugs.webkit.org/show_bug.cgi?id=66887
Reviewed by David Hyatt.
* fast/css/adjacent-sibling-selector-expected.txt: Added.
* fast/css/adjacent-sibling-selector.html: Added.
2011-09-09 Tom Sepez <tsepez@chromium.org>
Add test cases for xss auditor encoding bugs.
Test for https://bugs.webkit.org/show_bug.cgi?id=66887
Test Result:
PASSED
<!doctype html>
<html>
<head>
<style type="text/css">
div[test=before] + div + span {
color: red;
display: block;
}
div[test=before] + div + span + span {
display: none;
}
div[test=after] + div + span {
display: none;
}
div[test=after] + div + span + span {
color: green;
display: block;
}
</style>
</head>
<body onload="startTest();">
<div id="div1" test="before">Test for <a href="https://bugs.webkit.org/show_bug.cgi?id=66887">https://bugs.webkit.org/show_bug.cgi?id=66887</a></div>
<div id="div2">Test Result:</div>
<span>FAILED</span>
<span>PASSED</span>
<script>
function change() {
var element = document.getElementById('div1');
element.attributes.test.value = "after";
if (window.layoutTestController) {
layoutTestController.notifyDone();
}
}
function startTest() {
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
// Trigger an attribute change after all load processing is done. Doing the change
// here immediately does not exhibit the problem.
setTimeout("change();", 0);
}
</script>
</body>
</html>
2011-09-09 Kulanthaivel Palanichamy <kulanthaivel@codeaurora.org>
CSS rules not being applied when a hidden field is inserted between an input[type=checkbox] and a label
https://bugs.webkit.org/show_bug.cgi?id=66887
Reviewed by David Hyatt.
Test: fast/css/adjacent-sibling-selector.html
This patch addresses the problem of elements not getting their style recomputed
when they are affected by direct adjacent sibling rules and one of their sibling in
their corresponding rules is modified dynamically.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::canShareStyleWithElement):
(WebCore::parentStylePreventsSharing):
* css/SelectorChecker.cpp:
(WebCore::SelectorChecker::checkSelector):
* dom/Element.cpp:
(WebCore::Element::recalcStyle):
(WebCore::checkForSiblingStyleChanges):
* rendering/style/RenderStyle.cpp:
(WebCore::RenderStyle::RenderStyle):
* rendering/style/RenderStyle.h:
(WebCore::InheritedFlags::affectedByDirectAdjacentRules):
(WebCore::InheritedFlags::setAffectedByDirectAdjacentRules):
2011-09-09 Rafael Antognolli <antognolli@profusion.mobi>
Make the EFL port use the correct rendering file.
......@@ -948,6 +948,9 @@ bool CSSStyleSelector::canShareStyleWithElement(Node* node) const
if (style->transitions() || style->animations())
return false;
if (style->affectedByDirectAdjacentRules())
return false;
#if USE(ACCELERATED_COMPOSITING)
// Turn off style sharing for elements that can gain layers for reasons outside of the style system.
// See comments in RenderObject::setStyle().
......@@ -987,8 +990,7 @@ static inline bool parentStylePreventsSharing(const RenderStyle* parentStyle)
{
return parentStyle->childrenAffectedByPositionalRules()
|| parentStyle->childrenAffectedByFirstChildRules()
|| parentStyle->childrenAffectedByLastChildRules()
|| parentStyle->childrenAffectedByDirectAdjacentRules();
|| parentStyle->childrenAffectedByLastChildRules();
}
ALWAYS_INLINE RenderStyle* CSSStyleSelector::locateSharedStyle()
......
......@@ -341,10 +341,10 @@ SelectorChecker::SelectorMatch SelectorChecker::checkSelector(CSSSelector* sel,
}
case CSSSelector::DirectAdjacent:
{
if (!m_isCollectingRulesOnly && e->parentNode() && e->parentNode()->isElementNode()) {
RenderStyle* parentStyle = elementStyle ? elementParentStyle : e->parentNode()->renderStyle();
if (parentStyle)
parentStyle->setChildrenAffectedByDirectAdjacentRules();
if (!m_isCollectingRulesOnly) {
RenderStyle* currentStyle = elementStyle ? elementStyle : e->renderStyle();
if (currentStyle)
currentStyle->setAffectedByDirectAdjacentRules();
}
Node* n = e->previousSibling();
while (n && !n->isElementNode())
......
......@@ -1069,7 +1069,6 @@ void Element::recalcStyle(StyleChange change)
// Ref currentStyle in case it would otherwise be deleted when setRenderStyle() is called.
RefPtr<RenderStyle> currentStyle(renderStyle());
bool hasParentStyle = parentNodeForRenderingAndStyle() ? static_cast<bool>(parentNodeForRenderingAndStyle()->renderStyle()) : false;
bool hasDirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByDirectAdjacentRules();
bool hasIndirectAdjacentRules = currentStyle && currentStyle->childrenAffectedByForwardPositionalRules();
if ((change > NoChange || needsStyleRecalc())) {
......@@ -1111,8 +1110,8 @@ void Element::recalcStyle(StyleChange change)
newStyle->setChildrenAffectedByFirstChildRules();
if (currentStyle->childrenAffectedByLastChildRules())
newStyle->setChildrenAffectedByLastChildRules();
if (currentStyle->childrenAffectedByDirectAdjacentRules())
newStyle->setChildrenAffectedByDirectAdjacentRules();
if (currentStyle->affectedByDirectAdjacentRules())
newStyle->setAffectedByDirectAdjacentRules();
}
if (ch != NoChange || pseudoStyleCacheIsInvalid(currentStyle.get(), newStyle.get()) || (change == Force && renderer() && renderer()->requiresForcedStyleRecalcPropagation())) {
......@@ -1142,7 +1141,7 @@ void Element::recalcStyle(StyleChange change)
// FIXME: This check is good enough for :hover + foo, but it is not good enough for :hover + foo + bar.
// For now we will just worry about the common case, since it's a lot trickier to get the second case right
// without doing way too much re-resolution.
bool forceCheckOfNextElementSibling = false;
bool previousSiblingHadDirectAdjacentRules = false;
bool forceCheckOfAnyElementSibling = false;
for (Node *n = firstChild(); n; n = n->nextSibling()) {
if (n->isTextNode()) {
......@@ -1154,13 +1153,14 @@ void Element::recalcStyle(StyleChange change)
continue;
Element* element = static_cast<Element*>(n);
bool childRulesChanged = element->needsStyleRecalc() && element->styleChangeType() == FullStyleChange;
if ((forceCheckOfNextElementSibling || forceCheckOfAnyElementSibling))
bool childAffectedByDirectAdjacentRules = element->renderStyle() ? element->renderStyle()->affectedByDirectAdjacentRules() : previousSiblingHadDirectAdjacentRules;
if (childAffectedByDirectAdjacentRules || forceCheckOfAnyElementSibling)
element->setNeedsStyleRecalc();
if (change >= Inherit || element->childNeedsStyleRecalc() || element->needsStyleRecalc()) {
parentPusher.push();
element->recalcStyle(change);
}
forceCheckOfNextElementSibling = childRulesChanged && hasDirectAdjacentRules;
previousSiblingHadDirectAdjacentRules = childAffectedByDirectAdjacentRules;
forceCheckOfAnyElementSibling = forceCheckOfAnyElementSibling || (childRulesChanged && hasIndirectAdjacentRules);
}
// FIXME: This does not care about sibling combinators. Will be necessary in XBL2 world.
......@@ -1347,17 +1347,6 @@ static void checkForSiblingStyleChanges(Element* e, RenderStyle* style, bool fin
newLastChild->setNeedsStyleRecalc();
}
// The + selector. We need to invalidate the first element following the insertion point. It is the only possible element
// that could be affected by this DOM change.
if (style->childrenAffectedByDirectAdjacentRules() && afterChange) {
Node* firstElementAfterInsertion = 0;
for (firstElementAfterInsertion = afterChange;
firstElementAfterInsertion && !firstElementAfterInsertion->isElementNode();
firstElementAfterInsertion = firstElementAfterInsertion->nextSibling()) {};
if (firstElementAfterInsertion && firstElementAfterInsertion->attached())
firstElementAfterInsertion->setNeedsStyleRecalc();
}
// Forward positional selectors include the ~ selector, nth-child, nth-of-type, first-of-type and only-of-type.
// Backward positional selectors include nth-last-child, nth-last-of-type, last-of-type and only-of-type.
// We have to invalidate everything following the insertion point in the forward case, and everything before the insertion point in the
......
......@@ -77,11 +77,11 @@ ALWAYS_INLINE RenderStyle::RenderStyle()
, m_emptyState(false)
, m_childrenAffectedByFirstChildRules(false)
, m_childrenAffectedByLastChildRules(false)
, m_childrenAffectedByDirectAdjacentRules(false)
, m_childrenAffectedByForwardPositionalRules(false)
, m_childrenAffectedByBackwardPositionalRules(false)
, m_firstChildState(false)
, m_lastChildState(false)
, m_affectedByDirectAdjacentRules(false)
, m_childIndex(0)
, m_box(defaultStyle()->m_box)
, visual(defaultStyle()->visual)
......@@ -104,11 +104,11 @@ ALWAYS_INLINE RenderStyle::RenderStyle(bool)
, m_emptyState(false)
, m_childrenAffectedByFirstChildRules(false)
, m_childrenAffectedByLastChildRules(false)
, m_childrenAffectedByDirectAdjacentRules(false)
, m_childrenAffectedByForwardPositionalRules(false)
, m_childrenAffectedByBackwardPositionalRules(false)
, m_firstChildState(false)
, m_lastChildState(false)
, m_affectedByDirectAdjacentRules(false)
, m_childIndex(0)
{
setBitDefaults();
......@@ -141,11 +141,11 @@ ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
, m_emptyState(false)
, m_childrenAffectedByFirstChildRules(false)
, m_childrenAffectedByLastChildRules(false)
, m_childrenAffectedByDirectAdjacentRules(false)
, m_childrenAffectedByForwardPositionalRules(false)
, m_childrenAffectedByBackwardPositionalRules(false)
, m_firstChildState(false)
, m_lastChildState(false)
, m_affectedByDirectAdjacentRules(false)
, m_childIndex(0)
, m_box(o.m_box)
, visual(o.visual)
......
......@@ -132,11 +132,11 @@ protected:
// *-child-of-type, we will just give up and re-evaluate whenever children change at all.
bool m_childrenAffectedByFirstChildRules : 1;
bool m_childrenAffectedByLastChildRules : 1;
bool m_childrenAffectedByDirectAdjacentRules : 1;
bool m_childrenAffectedByForwardPositionalRules : 1;
bool m_childrenAffectedByBackwardPositionalRules : 1;
bool m_firstChildState : 1;
bool m_lastChildState : 1;
bool m_affectedByDirectAdjacentRules : 1;
unsigned m_childIndex : 21; // Plenty of bits to cache an index.
// non-inherited attributes
......@@ -1262,6 +1262,9 @@ public:
bool affectedByAttributeSelectors() const { return m_affectedByAttributeSelectors; }
void setAffectedByAttributeSelectors() { m_affectedByAttributeSelectors = true; }
bool affectedByDirectAdjacentRules() const { return m_affectedByDirectAdjacentRules; }
void setAffectedByDirectAdjacentRules() { m_affectedByDirectAdjacentRules = true; }
bool unique() const { return m_unique; }
void setUnique() { m_unique = true; }
......@@ -1274,8 +1277,6 @@ public:
void setChildrenAffectedByFirstChildRules() { m_childrenAffectedByFirstChildRules = true; }
bool childrenAffectedByLastChildRules() const { return m_childrenAffectedByLastChildRules; }
void setChildrenAffectedByLastChildRules() { m_childrenAffectedByLastChildRules = true; }
bool childrenAffectedByDirectAdjacentRules() const { return m_childrenAffectedByDirectAdjacentRules; }
void setChildrenAffectedByDirectAdjacentRules() { m_childrenAffectedByDirectAdjacentRules = true; }
bool childrenAffectedByForwardPositionalRules() const { return m_childrenAffectedByForwardPositionalRules; }
void setChildrenAffectedByForwardPositionalRules() { m_childrenAffectedByForwardPositionalRules = true; }
bool childrenAffectedByBackwardPositionalRules() const { return m_childrenAffectedByBackwardPositionalRules; }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment