Diff
Modified: trunk/LayoutTests/ChangeLog (275066 => 275067)
--- trunk/LayoutTests/ChangeLog 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/LayoutTests/ChangeLog 2021-03-26 00:09:23 UTC (rev 275067)
@@ -1,3 +1,14 @@
+2021-03-25 Zalan Bujtas <[email protected]>
+
+ [RenederTreeBuilder] Do not try to normalize the tree while destroying the multicolumn flow
+ https://bugs.webkit.org/show_bug.cgi?id=223722
+ <rdar://75731256>
+
+ Reviewed by Simon Fraser.
+
+ * fast/multicol/crash-while-destroying-the-column-context-expected.txt: Added.
+ * fast/multicol/crash-while-destroying-the-column-context.html: Added.
+
2021-03-25 Andres Gonzalez <[email protected]>
AX: Consider implementing @aria-details.
Added: trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context-expected.txt (0 => 275067)
--- trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context-expected.txt (rev 0)
+++ trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context-expected.txt 2021-03-26 00:09:23 UTC (rev 275067)
@@ -0,0 +1 @@
+
Added: trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context.html (0 => 275067)
--- trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context.html (rev 0)
+++ trunk/LayoutTests/fast/multicol/crash-while-destroying-the-column-context.html 2021-03-26 00:09:23 UTC (rev 275067)
@@ -0,0 +1,28 @@
+<style>
+ body {
+ writing-mode: vertical-rl;
+ block-size: 0;
+ }
+ div {
+ column-span: all;
+ }
+ :nth-child(2) {
+ float: left;
+ }
+ :read-only {
+ overflow-y: -webkit-paged-y;
+ }
+</style>
+<script>
+ if (window.testRunner)
+ testRunner.dumpAsText();
+ _onload_ = () => {
+ document.documentElement.appendChild(document.createElement('span'));
+ document.documentElement.appendChild(document.createElement('div'));
+ document.body.appendChild(document.createElement('div'));
+ document.execCommand('SelectAll');
+ document.designMode = 'on';
+ document.execCommand('InsertHorizontalRule');
+ };
+</script>
+PASS if no crash or assert.
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (275066 => 275067)
--- trunk/Source/WebCore/ChangeLog 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/ChangeLog 2021-03-26 00:09:23 UTC (rev 275067)
@@ -1,3 +1,28 @@
+2021-03-25 Zalan Bujtas <[email protected]>
+
+ [RenderTreeBuilder] Do not try to normalize the tree while destroying the multicolumn flow
+ https://bugs.webkit.org/show_bug.cgi?id=223722
+ <rdar://75731256>
+
+ Reviewed by Simon Fraser.
+
+ Test: fast/multicol/crash-while-destroying-the-column-context.html
+
+ This patch ensures that we don't start moving around parts of the fragmented flow subtree (e.g. collapsing anonymous blocks) while
+ trying place the spanner renderers back to their original positions as part of the "we don't need multicolumn context anymore".
+ (e.g spanner placeholder is removed -> triggers anon block collapsing -> moves subtrees around inside the multicolumn subtree -> insertion happens -> spanner placeholder gets re-validated)
+
+ * rendering/updating/RenderTreeBuilder.cpp:
+ (WebCore::RenderTreeBuilder::destroy):
+ * rendering/updating/RenderTreeBuilder.h:
+ * rendering/updating/RenderTreeBuilderBlock.cpp:
+ (WebCore::RenderTreeBuilder::Block::detach):
+ * rendering/updating/RenderTreeBuilderMultiColumn.cpp:
+ (WebCore::RenderTreeBuilder::MultiColumn::destroyFragmentedFlow):
+ (WebCore::RenderTreeBuilder::MultiColumn::handleSpannerRemoval):
+ (WebCore::RenderTreeBuilder::MultiColumn::multiColumnRelativeWillBeRemoved):
+ * rendering/updating/RenderTreeBuilderMultiColumn.h:
+
2021-03-25 Andres Gonzalez <[email protected]>
AX: Consider implementing @aria-details.
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp (275066 => 275067)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.cpp 2021-03-26 00:09:23 UTC (rev 275067)
@@ -164,11 +164,11 @@
s_current = m_previous;
}
-void RenderTreeBuilder::destroy(RenderObject& renderer)
+void RenderTreeBuilder::destroy(RenderObject& renderer, CanCollapseAnonymousBlock canCollapseAnonymousBlock)
{
RELEASE_ASSERT(RenderTreeMutationDisallowedScope::isMutationAllowed());
ASSERT(renderer.parent());
- auto toDestroy = detach(*renderer.parent(), renderer);
+ auto toDestroy = detach(*renderer.parent(), renderer, canCollapseAnonymousBlock);
#if ENABLE(FULLSCREEN_API)
if (is<RenderFullScreen>(renderer))
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h (275066 => 275067)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilder.h 2021-03-26 00:09:23 UTC (rev 275067)
@@ -48,7 +48,7 @@
enum class CanCollapseAnonymousBlock { No, Yes };
RenderPtr<RenderObject> detach(RenderElement&, RenderObject&, CanCollapseAnonymousBlock = CanCollapseAnonymousBlock::Yes) WARN_UNUSED_RETURN;
- void destroy(RenderObject& renderer);
+ void destroy(RenderObject& renderer, CanCollapseAnonymousBlock = CanCollapseAnonymousBlock::Yes);
// NormalizeAfterInsertion::Yes ensures that the destination subtree is consistent after the insertion (anonymous wrappers etc).
enum class NormalizeAfterInsertion { No, Yes };
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp (275066 => 275067)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderBlock.cpp 2021-03-26 00:09:23 UTC (rev 275067)
@@ -381,7 +381,7 @@
if (!parent.renderTreeBeingDestroyed()) {
auto* fragmentedFlow = parent.multiColumnFlow();
if (fragmentedFlow && fragmentedFlow != &child)
- m_builder.multiColumnBuilder().multiColumnRelativeWillBeRemoved(*fragmentedFlow, child);
+ m_builder.multiColumnBuilder().multiColumnRelativeWillBeRemoved(*fragmentedFlow, child, canCollapseAnonymousBlock);
}
return detach(static_cast<RenderBlock&>(parent), child, canCollapseAnonymousBlock);
}
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp (275066 => 275067)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.cpp 2021-03-26 00:09:23 UTC (rev 275067)
@@ -215,7 +215,7 @@
spannerOriginalParent = &flow;
// Detaching the spanner takes care of removing the placeholder (and merges the RenderMultiColumnSets).
auto* spanner = placeholder->spanner();
- parentAndSpannerList.append(std::make_pair(spannerOriginalParent, m_builder.detach(*spanner->parent(), *spanner)));
+ parentAndSpannerList.append(std::make_pair(spannerOriginalParent, m_builder.detach(*spanner->parent(), *spanner, CanCollapseAnonymousBlock::No)));
}
while (auto* columnSet = multiColumnFlow.firstMultiColumnSet())
m_builder.destroy(*columnSet);
@@ -389,11 +389,11 @@
return nextDescendant;
}
-void RenderTreeBuilder::MultiColumn::handleSpannerRemoval(RenderMultiColumnFlow& flow, RenderObject& spanner)
+void RenderTreeBuilder::MultiColumn::handleSpannerRemoval(RenderMultiColumnFlow& flow, RenderObject& spanner, RenderTreeBuilder::CanCollapseAnonymousBlock canCollapseAnonymousBlock)
{
// The placeholder may already have been removed, but if it hasn't, do so now.
if (auto placeholder = flow.spannerMap().take(&downcast<RenderBox>(spanner)))
- m_builder.destroy(*placeholder);
+ m_builder.destroy(*placeholder, canCollapseAnonymousBlock);
if (auto* next = spanner.nextSibling()) {
if (auto* previous = spanner.previousSibling()) {
@@ -406,7 +406,7 @@
}
}
-void RenderTreeBuilder::MultiColumn::multiColumnRelativeWillBeRemoved(RenderMultiColumnFlow& flow, RenderObject& relative)
+void RenderTreeBuilder::MultiColumn::multiColumnRelativeWillBeRemoved(RenderMultiColumnFlow& flow, RenderObject& relative, RenderTreeBuilder::CanCollapseAnonymousBlock canCollapseAnonymousBlock)
{
flow.invalidateFragments();
if (is<RenderMultiColumnSpannerPlaceholder>(relative)) {
@@ -421,7 +421,7 @@
if (relative.parent() != flow.parent())
return; // not a valid spanner.
- handleSpannerRemoval(flow, relative);
+ handleSpannerRemoval(flow, relative, canCollapseAnonymousBlock);
}
// Note that we might end up with empty column sets if all column content is removed. That's no
// big deal though (and locating them would be expensive), and they will be found and re-used if
Modified: trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h (275066 => 275067)
--- trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h 2021-03-25 23:35:20 UTC (rev 275066)
+++ trunk/Source/WebCore/rendering/updating/RenderTreeBuilderMultiColumn.h 2021-03-26 00:09:23 UTC (rev 275067)
@@ -44,7 +44,7 @@
RenderObject* resolveMovedChild(RenderFragmentedFlow& enclosingFragmentedFlow, RenderObject* beforeChild);
void restoreColumnSpannersForContainer(const RenderElement& container, RenderMultiColumnFlow&);
void multiColumnDescendantInserted(RenderMultiColumnFlow&, RenderObject& newDescendant);
- void multiColumnRelativeWillBeRemoved(RenderMultiColumnFlow&, RenderObject& relative);
+ void multiColumnRelativeWillBeRemoved(RenderMultiColumnFlow&, RenderObject& relative, RenderTreeBuilder::CanCollapseAnonymousBlock);
static RenderObject* adjustBeforeChildForMultiColumnSpannerIfNeeded(RenderObject& beforeChild);
private:
@@ -51,7 +51,7 @@
void createFragmentedFlow(RenderBlockFlow&);
void destroyFragmentedFlow(RenderBlockFlow&);
RenderObject* processPossibleSpannerDescendant(RenderMultiColumnFlow&, RenderObject*& subtreeRoot, RenderObject& descendant);
- void handleSpannerRemoval(RenderMultiColumnFlow&, RenderObject& spanner);
+ void handleSpannerRemoval(RenderMultiColumnFlow&, RenderObject& spanner, RenderTreeBuilder::CanCollapseAnonymousBlock);
RenderTreeBuilder& m_builder;
};