Don't schedule wholeSubtreeInvalid sets.

The StyleInvalidator asserts if we scheduled such sets. Mark element
for SubtreeStyleChange instead.

R=esprehn@chromium.org,ericwilligers@chromium.org
BUG=624607

Review-Url: https://codereview.chromium.org/2106063007
Cr-Commit-Position: refs/heads/master@{#403663}
diff --git a/third_party/WebKit/LayoutTests/fast/css/invalidation/sibling-mutation-assert.html b/third_party/WebKit/LayoutTests/fast/css/invalidation/sibling-mutation-assert.html
new file mode 100644
index 0000000..e1aeae4
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/fast/css/invalidation/sibling-mutation-assert.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src="../../../resources/testharness.js"></script>
+<script src="../../../resources/testharnessreport.js"></script>
+<style>
+    #a + #b * { color: pink }
+</style>
+<p>Should not assert/crash.</p>
+<div id="p">
+    <div id="b">
+        <div></div>
+    </div>
+</div>
+<script>
+    test(() => {
+        p.offsetTop;
+        var a = document.createElement("div");
+        a.id = "a";
+        p.insertBefore(a, b);
+        assert_true(true, "Reached end of insert without triggering assert.");
+    }, "Scheduling sibling set with wholeSubtreeInvalid should not cause asserts.");
+</script>
diff --git a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
index b28c9cd..bdd72536 100644
--- a/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
+++ b/third_party/WebKit/Source/core/css/invalidation/StyleInvalidator.cpp
@@ -96,16 +96,25 @@
 
     PendingInvalidations& pendingInvalidations = ensurePendingInvalidations(schedulingParent);
 
+    schedulingParent.setNeedsStyleInvalidation();
+
     for (auto& invalidationSet : invalidationLists.siblings) {
+        if (invalidationSet->wholeSubtreeInvalid()) {
+            schedulingParent.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
+            return;
+        }
         if (invalidationSet->invalidatesSelf() && !pendingInvalidations.descendants().contains(invalidationSet))
             pendingInvalidations.descendants().append(invalidationSet);
 
         if (DescendantInvalidationSet* descendants = toSiblingInvalidationSet(*invalidationSet).siblingDescendants()) {
+            if (descendants->wholeSubtreeInvalid()) {
+                schedulingParent.setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::StyleInvalidator));
+                return;
+            }
             if (!pendingInvalidations.descendants().contains(descendants))
                 pendingInvalidations.descendants().append(descendants);
         }
     }
-    schedulingParent.setNeedsStyleInvalidation();
 }
 
 void StyleInvalidator::clearInvalidation(ContainerNode& node)