- Revision
- 289098
- Author
- za...@apple.com
- Date
- 2022-02-03 18:24:21 -0800 (Thu, 03 Feb 2022)
Log Message
[RenderTreeBuilder] Clean up column spanners when style change affects containing block
https://bugs.webkit.org/show_bug.cgi?id=236042
<rdar://83975391>
Reviewed by Antti Koivisto.
Source/WebCore:
In addition to removing the leftover spanners after style change, this patch also expands on the type of style changes that may affect the subtree state inside a multicolumn flow.
Test: fast/multicol/leftover-spanner-on-style-change-crash.html
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::styleDidChange):
* rendering/RenderElement.cpp:
(WebCore::RenderElement::setStyle):
(WebCore::RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded):
* rendering/RenderElement.h:
* rendering/updating/RenderTreeBuilder.cpp:
(WebCore::RenderTreeBuilder::normalizeTreeAfterStyleChange):
LayoutTests:
* fast/multicol/leftover-spanner-on-style-change-crash-expected.txt: Added.
* fast/multicol/leftover-spanner-on-style-change-crash.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (289097 => 289098)
--- trunk/LayoutTests/ChangeLog 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/LayoutTests/ChangeLog 2022-02-04 02:24:21 UTC (rev 289098)
@@ -1,3 +1,14 @@
+2022-02-03 Alan Bujtas <za...@apple.com>
+
+ [RenderTreeBuilder] Clean up column spanners when style change affects containing block
+ https://bugs.webkit.org/show_bug.cgi?id=236042
+ <rdar://83975391>
+
+ Reviewed by Antti Koivisto.
+
+ * fast/multicol/leftover-spanner-on-style-change-crash-expected.txt: Added.
+ * fast/multicol/leftover-spanner-on-style-change-crash.html: Added.
+
2022-02-03 Jon Lee <jon...@apple.com>
Unreviewed gardening.
Added: trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash-expected.txt (0 => 289098)
--- trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash-expected.txt 2022-02-04 02:24:21 UTC (rev 289098)
@@ -0,0 +1 @@
+
Added: trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash.html (0 => 289098)
--- trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash.html (rev 0)
+++ trunk/LayoutTests/fast/multicol/leftover-spanner-on-style-change-crash.html 2022-02-04 02:24:21 UTC (rev 289098)
@@ -0,0 +1,31 @@
+<style>
+ html {
+ columns: 1px;
+ }
+ div::before {
+ content: url();
+ }
+ frame {
+ column-span: all;
+ }
+ :first-child {
+ position: absolute;
+ rotate: 0deg;
+ }
+ :read-only {
+ translate: 0;
+ }
+</style>
+<!-- PASS if no crash or assert. -->
+<script>
+ if (window.testRunner)
+ testRunner.dumpAsText();
+ internals.settings.setTextAutosizingEnabled(true);
+ _onload_ = () => {
+ let div0 = document.createElement('div');
+ document.body.appendChild(div0);
+ div0.appendChild(document.createElement('frame'));
+ document.body.offsetTop;
+ document.designMode = 'on';
+ };
+</script>
Modified: trunk/Source/WebCore/ChangeLog (289097 => 289098)
--- trunk/Source/WebCore/ChangeLog 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/Source/WebCore/ChangeLog 2022-02-04 02:24:21 UTC (rev 289098)
@@ -1,3 +1,24 @@
+2022-02-03 Alan Bujtas <za...@apple.com>
+
+ [RenderTreeBuilder] Clean up column spanners when style change affects containing block
+ https://bugs.webkit.org/show_bug.cgi?id=236042
+ <rdar://83975391>
+
+ Reviewed by Antti Koivisto.
+
+ In addition to removing the leftover spanners after style change, this patch also expands on the type of style changes that may affect the subtree state inside a multicolumn flow.
+
+ Test: fast/multicol/leftover-spanner-on-style-change-crash.html
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::styleDidChange):
+ * rendering/RenderElement.cpp:
+ (WebCore::RenderElement::setStyle):
+ (WebCore::RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded):
+ * rendering/RenderElement.h:
+ * rendering/updating/RenderTreeBuilder.cpp:
+ (WebCore::RenderTreeBuilder::normalizeTreeAfterStyleChange):
+
2022-02-03 Tyler Wilcock <tyle...@apple.com>
AXIsolatedTree::updateChildren removes subtrees that should instead be moved
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (289097 => 289098)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2022-02-04 02:24:21 UTC (rev 289098)
@@ -432,11 +432,10 @@
void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
{
- bool hadTransform = hasTransform();
RenderBox::styleDidChange(diff, oldStyle);
- if (hadTransform != hasTransform())
- adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
+ if (oldStyle)
+ adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded(*oldStyle, style());
propagateStyleToAnonymousChildren(PropagateToBlockChildrenOnly);
Modified: trunk/Source/WebCore/rendering/RenderElement.cpp (289097 => 289098)
--- trunk/Source/WebCore/rendering/RenderElement.cpp 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/Source/WebCore/rendering/RenderElement.cpp 2022-02-04 02:24:21 UTC (rev 289098)
@@ -532,10 +532,7 @@
auto oldStyle = m_style.replace(WTFMove(style));
bool detachedFromParent = !parent();
- // Make sure we invalidate the containing block cache for flows when the contianing block context changes
- // so that styleDidChange can safely use RenderBlock::locateEnclosingFragmentedFlow()
- if (oldStyle.position() != m_style.position())
- adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
+ adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded(oldStyle, m_style);
styleDidChange(diff, &oldStyle);
@@ -2214,11 +2211,22 @@
return (imageElement && !imageElement->allowsOrientationOverride()) ? ImageOrientation(ImageOrientation::FromImage) : style().imageOrientation();
}
-void RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded()
+void RenderElement::adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded(const RenderStyle& oldStyle, const RenderStyle& newStyle)
{
if (fragmentedFlowState() == NotInsideFragmentedFlow)
return;
+ // Make sure we invalidate the containing block cache for flows when the contianing block context changes
+ // so that styleDidChange can safely use RenderBlock::locateEnclosingFragmentedFlow()
+ // FIXME: Share some code with RenderElement::canContain*.
+ auto mayNotBeContainingBlockForDescendantsAnymore = oldStyle.position() != m_style.position()
+ || oldStyle.hasTransformRelatedProperty() != m_style.hasTransformRelatedProperty()
+ || oldStyle.willChange() != newStyle.willChange()
+ || oldStyle.containsLayout() != newStyle.containsLayout()
+ || oldStyle.containsSize() != newStyle.containsSize();
+ if (!mayNotBeContainingBlockForDescendantsAnymore)
+ return;
+
// Invalidate the containing block caches.
if (is<RenderBlock>(*this))
downcast<RenderBlock>(*this).resetEnclosingFragmentedFlowAndChildInfoIncludingDescendants();
Modified: trunk/Source/WebCore/rendering/RenderElement.h (289097 => 289098)
--- trunk/Source/WebCore/rendering/RenderElement.h 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/Source/WebCore/rendering/RenderElement.h 2022-02-04 02:24:21 UTC (rev 289098)
@@ -326,7 +326,7 @@
void updateOutlineAutoAncestor(bool hasOutlineAuto);
void removeFromRenderFragmentedFlowIncludingDescendants(bool shouldUpdateState);
- void adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded();
+ void adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded(const RenderStyle& oldStyle, const RenderStyle& newStyle);
bool isVisibleInViewport() const;
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (289097 => 289098)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2022-02-04 02:22:29 UTC (rev 289097)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2022-02-04 02:24:21 UTC (rev 289098)
@@ -671,6 +671,13 @@
multiColumnBuilder().restoreColumnSpannersForContainer(renderer, downcast<RenderMultiColumnFlow>(*enclosingFragmentedFlow));
return;
}
+
+ // Style change may have moved some subtree out of the fragmented flow. Their flow states have already been updated (see adjustFragmentedFlowStateOnContainingBlockChangeIfNeeded)
+ // and here is where we take care of the remaining, spanner tree mutation.
+ for (auto& descendant : descendantsOfType<RenderMultiColumnSpannerPlaceholder>(renderer)) {
+ if (auto* containingBlock = descendant.containingBlock(); containingBlock && containingBlock->enclosingFragmentedFlow() != enclosingFragmentedFlow)
+ multiColumnBuilder().restoreColumnSpannersForContainer(*containingBlock, downcast<RenderMultiColumnFlow>(*enclosingFragmentedFlow));
+ }
}
}