Bug 1809764 Part 2 - Ignore "break-inside:avoid" for content in a nested top-of-page multicol in last balancing reflow. r=emilio

The only difference between multicol-nested-030.html and
multicol-nested-031.html is the `column-fill` property on the outer column.

WARNING: loading 030.html and 031.html without this patch can trap Firefox in
infinite loops.

Differential Revision: https://phabricator.services.mozilla.com/D169005
This commit is contained in:
Ting-Yu Lin 2023-02-07 07:44:12 +00:00
Родитель edb1fd49bf
Коммит 7e902d0c04
7 изменённых файлов: 62 добавлений и 5 удалений

Просмотреть файл

@ -627,7 +627,26 @@ nsColumnSetFrame::ColumnBalanceData nsColumnSetFrame::ReflowColumns(
LogicalSize kidCBSize(wm, availSize.ISize(wm), computedBSize);
ReflowInput kidReflowInput(PresContext(), aReflowInput, child, availSize,
Some(kidCBSize));
kidReflowInput.mFlags.mIsTopOfPage = !aConfig.mIsBalancing;
kidReflowInput.mFlags.mIsTopOfPage = [&]() {
const bool isNestedMulticol =
aReflowInput.mParentReflowInput->mFrame->HasAnyStateBits(
NS_FRAME_HAS_MULTI_COLUMN_ANCESTOR);
if (isNestedMulticol) {
if (aReflowInput.mFlags.mIsTopOfPage) {
// If this is the last balancing reflow in a nested multicol, we
// want to force fit content to avoid infinite loops.
return !aConfig.mIsBalancing || aConfig.mIsLastBalancingReflow;
}
// If we are a nested multicol and not at the top of page, we
// shouldn't force fit content. This is because our
// ColumnSetWrapperFrame can be pushed to next page/column and
// reflowed again with a potentially larger available block-size.
return false;
}
// We are a top-level multicol. Force fit the content only if we are not
// balancing columns.
return !aConfig.mIsBalancing;
}();
kidReflowInput.mFlags.mTableIsSplittable = false;
kidReflowInput.mFlags.mIsColumnBalancing = aConfig.mIsBalancing;
kidReflowInput.mBreakType = ReflowInput::BreakType::Column;
@ -1149,6 +1168,7 @@ void nsColumnSetFrame::FindBestBalanceBSize(const ReflowInput& aReflowInput,
// balancing. Otherwise we'd have to split, and it's not clear what we'd
// do with that.
COLUMN_SET_LOG("%s: Last attempt to call ReflowColumns", __func__);
aConfig.mIsLastBalancingReflow = true;
const bool forceUnboundedLastColumn =
aReflowInput.mParentReflowInput->AvailableBSize() ==
NS_UNCONSTRAINEDSIZE;

Просмотреть файл

@ -108,6 +108,10 @@ class nsColumnSetFrame final : public nsContainerFrame {
// sequentially.
bool mForceAuto = false;
// A boolean indicates whether or not we are in the last attempt to reflow
// columns. We set it to true at the end of FindBestBalanceBSize().
bool mIsLastBalancingReflow = false;
// The last known column block-size that was 'feasible'. A column bSize is
// feasible if all child content fits within the specified bSize.
nscoord mKnownFeasibleBSize = NS_UNCONSTRAINEDSIZE;

Просмотреть файл

@ -1,2 +0,0 @@
[multicol-nested-013.html]
expected: FAIL

Просмотреть файл

@ -0,0 +1,7 @@
[multicol-nested-015.html]
# Before bug 1809764, we pass this test by accident. We don't support
# widow/orphan, and lack a granular control over choosing break points between
# "break-before:avoid" on the inner column or "break-inside:avoid" elements
# within the inner column. After bug 1809764, we choose to honor the
# "break-inside:avoid" on element in the inner column.
expected: FAIL

Просмотреть файл

@ -1,2 +0,0 @@
[multicol-nested-022.html]
expected: FAIL

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test: Test break-inside:avoid block in a nested multi-column shouldn't causean infinite loop</title>
<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#the-multi-column-model">
<link rel="help" href="https://drafts.csswg.org/css-break-3/#break-within">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="outer" style="columns: 2; column-gap: 0; width: 100px; height: 100px;">
<div id="inner" style="columns: 2; column-gap: 0;">
<div style="height: 400px; break-inside: avoid; background: green"></div>
</div>
</div>

Просмотреть файл

@ -0,0 +1,15 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Multi-column Layout Test: Test break-inside:avoid block in a nested multi-column shouldn't causean infinite loop</title>
<link rel="author" title="Ting-Yu Lin" href="mailto:tlin@mozilla.com">
<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
<link rel="help" href="https://drafts.csswg.org/css-multicol-1/#the-multi-column-model">
<link rel="help" href="https://drafts.csswg.org/css-break-3/#break-within">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="outer" style="columns: 2; column-gap: 0; column-fill: auto; width: 100px; height: 100px;">
<div id="inner" style="columns: 2; column-gap: 0;">
<div style="height: 400px; break-inside: avoid; background: green"></div>
</div>
</div>