Commit 2faf5583 authored by Rune Lillesveen's avatar Rune Lillesveen Committed by Commit Bot

Centralize invalidation for style attribute changes.

Style attribute changes could affect style matching of other elements
than the one that gets its style attribute modified because of selectors
which have a style attribute selector in the non-right-most compound.
For instance:

  [style] + div

In this case the div will be invalidated by an invalidation set for the
style attribute scheduled in StyleEngine::AttributeChangedForElement().
This method was not invoked for all variants of style attribute
modifications. In particular setting the text for Element.style.

This CL centralizes the invalidation handling to cover all cases.

Bug: 1056151
Change-Id: Iceb70c284e2bb6b209a4243d61f941670eab323e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2078532Reviewed-by: default avatarXiaocheng Hu <xiaochengh@chromium.org>
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
Cr-Commit-Position: refs/heads/master@{#745382}
parent f9be9b0e
...@@ -219,11 +219,6 @@ void AbstractPropertySetCSSStyleDeclaration::SetPropertyInternal( ...@@ -219,11 +219,6 @@ void AbstractPropertySetCSSStyleDeclaration::SetPropertyInternal(
if (!did_change) if (!did_change)
return; return;
Element* parent = ParentElement();
if (parent) {
parent->GetDocument().GetStyleEngine().AttributeChangedForElement(
html_names::kStyleAttr, *parent);
}
mutation_scope.EnqueueMutationRecord(); mutation_scope.EnqueueMutationRecord();
} }
......
...@@ -41,9 +41,6 @@ void InlineCSSStyleDeclaration::DidMutate(MutationType type) { ...@@ -41,9 +41,6 @@ void InlineCSSStyleDeclaration::DidMutate(MutationType type) {
return; return;
parent_element_->ClearMutableInlineStyleIfEmpty(); parent_element_->ClearMutableInlineStyleIfEmpty();
parent_element_->SetNeedsStyleRecalc(
kLocalStyleChange, StyleChangeReasonForTracing::Create(
style_change_reason::kInlineCSSStyleMutated));
parent_element_->InvalidateStyleAttribute(); parent_element_->InvalidateStyleAttribute();
StyleAttributeMutationScope(this).DidInvalidateStyleAttr(); StyleAttributeMutationScope(this).DidInvalidateStyleAttr();
} }
......
...@@ -27,7 +27,6 @@ const char kFrame[] = "Frame"; ...@@ -27,7 +27,6 @@ const char kFrame[] = "Frame";
const char kFullscreen[] = "Fullscreen"; const char kFullscreen[] = "Fullscreen";
const char kInheritedStyleChangeFromParentFrame[] = const char kInheritedStyleChangeFromParentFrame[] =
"InheritedStyleChangeFromParentFrame"; "InheritedStyleChangeFromParentFrame";
const char kInline[] = "Inline";
const char kInlineCSSStyleMutated[] = const char kInlineCSSStyleMutated[] =
"Inline CSS style declaration was mutated"; "Inline CSS style declaration was mutated";
const char kInspector[] = "Inspector"; const char kInspector[] = "Inspector";
......
...@@ -29,7 +29,6 @@ extern const char kFonts[]; ...@@ -29,7 +29,6 @@ extern const char kFonts[];
extern const char kFullscreen[]; extern const char kFullscreen[];
extern const char kFindInvisible[]; extern const char kFindInvisible[];
extern const char kInheritedStyleChangeFromParentFrame[]; extern const char kInheritedStyleChangeFromParentFrame[];
extern const char kInline[];
extern const char kInlineCSSStyleMutated[]; extern const char kInlineCSSStyleMutated[];
extern const char kInspector[]; extern const char kInspector[];
extern const char kInvisibleChange[]; extern const char kInvisibleChange[];
......
...@@ -6206,10 +6206,7 @@ void Element::StyleAttributeChanged( ...@@ -6206,10 +6206,7 @@ void Element::StyleAttributeChanged(
void Element::InlineStyleChanged() { void Element::InlineStyleChanged() {
DCHECK(IsStyledElement()); DCHECK(IsStyledElement());
SetNeedsStyleRecalc(kLocalStyleChange, StyleChangeReasonForTracing::Create( InvalidateStyleAttribute();
style_change_reason::kInline));
DCHECK(GetElementData());
GetElementData()->style_attribute_is_dirty_ = true;
probe::DidInvalidateStyleAttr(this); probe::DidInvalidateStyleAttr(this);
if (MutationObserverInterestGroup* recipients = if (MutationObserverInterestGroup* recipients =
...@@ -6509,4 +6506,14 @@ void Element::SetActive(bool active) { ...@@ -6509,4 +6506,14 @@ void Element::SetActive(bool active) {
GetLayoutObject()->InvalidateIfControlStateChanged(kPressedControlState); GetLayoutObject()->InvalidateIfControlStateChanged(kPressedControlState);
} }
void Element::InvalidateStyleAttribute() {
DCHECK(GetElementData());
GetElementData()->style_attribute_is_dirty_ = true;
SetNeedsStyleRecalc(kLocalStyleChange,
StyleChangeReasonForTracing::Create(
style_change_reason::kInlineCSSStyleMutated));
GetDocument().GetStyleEngine().AttributeChangedForElement(
html_names::kStyleAttr, *this);
}
} // namespace blink } // namespace blink
...@@ -1344,11 +1344,6 @@ inline UniqueElementData& Element::EnsureUniqueElementData() { ...@@ -1344,11 +1344,6 @@ inline UniqueElementData& Element::EnsureUniqueElementData() {
return To<UniqueElementData>(*element_data_); return To<UniqueElementData>(*element_data_);
} }
inline void Element::InvalidateStyleAttribute() {
DCHECK(GetElementData());
GetElementData()->style_attribute_is_dirty_ = true;
}
inline const CSSPropertyValueSet* Element::PresentationAttributeStyle() { inline const CSSPropertyValueSet* Element::PresentationAttributeStyle() {
if (!GetElementData()) if (!GetElementData())
return nullptr; return nullptr;
......
<!doctype html>
<title>CSS Selectors Test: Tests the style attribute used in an attribute selector</title>
<link rel="help" href="https://drafts.csswg.org/selectors/#attribute-selectors">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
#container { font-size: 16px; color: black; }
.test[style] { color: green }
.test[style=""] { font-size: 100px }
.test[style*="text-decoration"] { background-color: lime }
.test[style] + #sibling { color: green; }
.test[style*="text-decoration"] + #sibling { background-color: lime; }
</style>
<div id="container">
<div id="t1" class="test" style></div>
<div id="t2" class="test" style=""></div>
<div id="t3" class="test" style="text-decoration:underline"></div>
<div id="t4" class="test"></div>
<div id="sibling"></div>
</div>
<script>
const no_match_bgcolor = "rgba(0, 0, 0, 0)";
const no_match_color = "rgb(0, 0, 0)";
const no_match_font_size = "16px";
const match_bgcolor = "rgb(0, 255, 0)";
const match_color = "rgb(0, 128, 0)";
const match_font_size = "100px";
test(() => {
assert_equals(getComputedStyle(t1).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t1).color, match_color);
assert_equals(getComputedStyle(t1).fontSize, match_font_size);
}, "Match style attribute with no value");
test(() => {
assert_equals(getComputedStyle(t2).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t2).color, match_color);
assert_equals(getComputedStyle(t2).fontSize, match_font_size);
}, "Match style attribute with empty value");
test(() => {
assert_equals(getComputedStyle(t3).backgroundColor, match_bgcolor);
assert_equals(getComputedStyle(t3).color, match_color);
assert_equals(getComputedStyle(t3).fontSize, no_match_font_size);
}, "Match style attribute with background value");
test(() => {
assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t4).color, no_match_color);
assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
assert_equals(getComputedStyle(sibling).color, no_match_color);
}, "Initially no style attribute to match");
function reset_style(element) {
element.removeAttribute("style");
element.offsetTop;
}
function set_style(element) {
element.setAttribute("style", "text-decoration: underline");
element.offsetTop;
}
test(() => {
reset_style(t4);
t4.setAttribute("style", "text-decoration: underline");
assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
}, "Dynamically change style with Element.setAttribute");
test(() => {
reset_style(t4);
t4.style = "text-decoration: underline";
assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
}, "Dynamically change style with Element.style");
test(() => {
reset_style(t4);
t4.style.textDecoration = "underline";
assert_equals(getComputedStyle(t4).backgroundColor, match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
}, "Dynamically change style with Element.style.property");
test(() => {
set_style(t4);
t4.removeAttribute("style");
assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t4).color, no_match_color);
assert_equals(getComputedStyle(t4).fontSize, no_match_font_size);
assert_equals(getComputedStyle(sibling).color, no_match_color);
assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
}, "Dynamically remove style with Element.removeAttribute");
test(() => {
set_style(t4);
t4.style = "";
assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
}, "Dynamically remove style with Element.style");
test(() => {
set_style(t4);
t4.style.textDecoration = "";
assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
}, "Dynamically remove style with Element.style.property");
test(() => {
set_style(t4);
t4.style.removeProperty("text-decoration");
assert_equals(getComputedStyle(t4).backgroundColor, no_match_bgcolor);
assert_equals(getComputedStyle(t4).color, match_color);
assert_equals(getComputedStyle(t4).fontSize, match_font_size);
assert_equals(getComputedStyle(sibling).color, match_color);
assert_equals(getComputedStyle(sibling).backgroundColor, no_match_bgcolor);
}, "Dynamically remove style with Element.style.removeProperty");
</script>
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