Store new ComputedStyle object if style did not change.
The comparison of ComputedStyle does not take additional flags into
account. For instance, the AffectedBy* flags used for updating pseudo
classes like :hover. We used to call SetStyleInternal, but this was
removed because the previous comment said it was because of style
sharing which is now removed.
The display:contents case (768406) never worked because the code path
for StoreNonLayoutObjectComputedStyle() was always skipped when
computed style compared to be equal.
Bug: 768406, 767832
Change-Id: Iac4708e3cd3a6451d99c1bb2bb69efb74289b8eb
Reviewed-on: https://chromium-review.googlesource.com/681755
Reviewed-by: nainar <[email protected]>
Commit-Queue: Rune Lillesveen <[email protected]>
Cr-Commit-Position: refs/heads/master@{#504285}
diff --git a/third_party/WebKit/LayoutTests/fast/dynamic/hover-after-affected-by-change.html b/third_party/WebKit/LayoutTests/fast/dynamic/hover-after-affected-by-change.html
new file mode 100644
index 0000000..7269908a
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/dynamic/hover-after-affected-by-change.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<style>
+ .affected:hover { color: green }
+ #hoveredContents { display: contents }
+</style>
+<div id="hovered">Hover me - should become green</div>
+<div id="hoveredContents">
+ <div id="hovered2">Hover me - should become green</div>
+</div>
+<script>
+ function mouseMoveTo(element) {
+ return new Promise((resolve, reject) => {
+ chrome.gpuBenchmarking.pointerActionSequence([{source: "mouse",
+ actions: [{ name: "pointerMove",
+ x: element.offsetLeft + 1,
+ y: element.offsetTop + 1 }]}],
+ resolve);
+ });
+ }
+
+ test(() => {
+ hovered.offsetTop;
+ hovered.className = "affected";
+ hoveredContents.className = "affected";
+ }, "Change selector matching causes different AffectedByHover flags.");
+
+ test(() => {
+ assert_exists(window, "chrome", "This test requires window.chrome.");
+ assert_exists(window.chrome, "gpuBenchmarking",
+ "This test requires chrome.gpuBenchmarking.");
+ }, "Preconditions.");
+
+ test(() => {
+ assert_equals(getComputedStyle(hovered).color, "rgb(0, 0, 0)");
+ mouseMoveTo(hovered).then(() => {
+ assert_equals(getComputedStyle(hovered).color, "rgb(0, 128, 0)");
+ });
+ }, "Check that :hover rule is applied.");
+
+ test(() => {
+ assert_equals(getComputedStyle(hoveredContents).color, "rgb(0, 0, 0)");
+ mouseMoveTo(hovered2).then(() => {
+ assert_equals(getComputedStyle(hoveredContents).color, "rgb(0, 128, 0)");
+ });
+ }, "Check that :hover rule is applied to display:contents element.");
+</script>
diff --git a/third_party/WebKit/Source/core/dom/Element.cpp b/third_party/WebKit/Source/core/dom/Element.cpp
index 876cdb5..3247b52 100644
--- a/third_party/WebKit/Source/core/dom/Element.cpp
+++ b/third_party/WebKit/Source/core/dom/Element.cpp
@@ -2148,15 +2148,21 @@
if (local_change != kNoChange)
UpdateCallbackSelectors(old_style.Get(), new_style.Get());
- if (local_change != kNoChange) {
- if (LayoutObject* layout_object = this->GetLayoutObject()) {
+ if (LayoutObject* layout_object = this->GetLayoutObject()) {
+ // kNoChange may means that the computed style didn't change, but there are
+ // additional flags in ComputedStyle which may have changed. For instance,
+ // the AffectedBy* flags. We don't need to go through the visual
+ // invalidation diffing in that case, but we replace the old ComputedStyle
+ // object with the new one to ensure the mentioned flags are up to date.
+ if (local_change == kNoChange)
+ layout_object->SetStyleInternal(new_style.Get());
+ else
layout_object->SetStyle(new_style.Get());
- } else {
- if (ShouldStoreNonLayoutObjectComputedStyle(*new_style))
- StoreNonLayoutObjectComputedStyle(new_style);
- else if (HasRareData())
- GetElementRareData()->ClearComputedStyle();
- }
+ } else {
+ if (ShouldStoreNonLayoutObjectComputedStyle(*new_style))
+ StoreNonLayoutObjectComputedStyle(new_style);
+ else if (HasRareData())
+ GetElementRareData()->ClearComputedStyle();
}
if (GetStyleChangeType() >= kSubtreeStyleChange)