[FlexNG] MinBlockSizeShouldEncompassIntrinsicSize update
Update the MinBlockSizeShouldEncompassIntrinsicSize() definition to
more accurately handle flex items during fragmentation. Credit to
ikilpatrick@ for figuring out the correct logic.
A couple of row specific tests were updated to match the new behavior,
and a bunch of column specific tests were added to check various
combinations of use cases.
Bug: 660611
Change-Id: I1d9dded7189ab2d7b0c8c3e60c7f24e9c711212b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3600998
Commit-Queue: Alison Maher <almaher@microsoft.com>
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
Cr-Commit-Position: refs/heads/main@{#996810}
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
index 4731f89..088053a 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -162,29 +162,6 @@
return AxisEdge::kStart;
}
-// We are interested in cases where the flex item *may* expand due to
-// fragmentation (lines pushed down by a fragmentation line, etc).
-bool MinBlockSizeShouldEncompassIntrinsicSize(const NGFlexItem& item) {
- // If this item has (any) descendant that is percentage based, we can end
- // up in a situation where we'll constantly try and expand the row. E.g.
- // <div style="display: flex;">
- // <div style="min-height: 100px;">
- // <div style="height: 200%;"></div>
- // </div>
- // </div>
- if (item.has_descendant_that_depends_on_percentage_block_size)
- return false;
-
- if (item.ng_input_node.IsMonolithic())
- return false;
-
- // TODO(almaher): Figure out which cases this should be true. (Should this
- // only be true when min-block-size is auto in the case of |is_column_|?)
- // Also, should this be the same in the case of a row flex container?
- const auto& item_style = item.ng_input_node.Style();
- return item_style.LogicalHeight().IsAutoOrContentOrIntrinsic();
-}
-
} // namespace
void NGFlexLayoutAlgorithm::HandleOutOfFlowPositionedItems(
@@ -2405,6 +2382,57 @@
return algorithm_with_row_cross_sizes.Layout();
}
+// We are interested in cases where the flex item *may* expand due to
+// fragmentation (lines pushed down by a fragmentation line, etc).
+bool NGFlexLayoutAlgorithm::MinBlockSizeShouldEncompassIntrinsicSize(
+ const NGFlexItem& item) const {
+ // If this item has (any) descendant that is percentage based, we can end
+ // up in a situation where we'll constantly try and expand the row. E.g.
+ // <div style="display: flex;">
+ // <div style="min-height: 100px;">
+ // <div style="height: 200%;"></div>
+ // </div>
+ // </div>
+ if (item.has_descendant_that_depends_on_percentage_block_size)
+ return false;
+
+ if (item.ng_input_node.IsMonolithic())
+ return false;
+
+ const auto& item_style = item.ng_input_node.Style();
+
+ // NOTE: We currently assume that writing-mode roots are monolithic, but
+ // this may change in the future.
+ DCHECK_EQ(ConstraintSpace().GetWritingDirection().GetWritingMode(),
+ item_style.GetWritingMode());
+
+ if (is_column_) {
+ bool can_shrink = item_style.ResolvedFlexShrink(Style()) != 0.f &&
+ !Style().LogicalHeight().IsAutoOrContentOrIntrinsic();
+
+ // Only allow growth if the item can't shrink and the flex-basis is
+ // content-based.
+ if (!IsUsedFlexBasisDefinite(item.ng_input_node) && !can_shrink)
+ return true;
+
+ // Only allow growth if the item's block-size is auto and either the item
+ // can't shrink or its min-height is auto.
+ if (item_style.LogicalHeight().IsAutoOrContentOrIntrinsic() &&
+ (!can_shrink || algorithm_.ShouldApplyMinSizeAutoForChild(
+ *item.ng_input_node.GetLayoutBox())))
+ return true;
+ } else {
+ // Don't grow if the item's block-size should be the same as its container.
+ if (WillChildCrossSizeBeContainerCrossSize(item.ng_input_node))
+ return false;
+
+ // Only allow growth if the item's cross size is auto.
+ if (DoesItemCrossSizeComputeToAuto(item.ng_input_node))
+ return true;
+ }
+ return false;
+}
+
#if DCHECK_IS_ON()
void NGFlexLayoutAlgorithm::CheckFlexLines(
HeapVector<NGFlexLine>& flex_line_outputs) const {
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
index 5278b1f..abc4629 100644
--- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
+++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -17,6 +17,7 @@
class NGBlockBreakToken;
class NGBoxFragment;
struct DevtoolsFlexInfo;
+struct NGFlexItem;
class CORE_EXPORT NGFlexLayoutAlgorithm
: public NGLayoutAlgorithm<NGBlockNode,
@@ -174,6 +175,10 @@
// cross-size adjustments.
const NGLayoutResult* RelayoutWithNewRowSizes();
+ // Used to determine when to allow an item to expand as a result of
+ // fragmentation.
+ bool MinBlockSizeShouldEncompassIntrinsicSize(const NGFlexItem& item) const;
+
#if DCHECK_IS_ON()
void CheckFlexLines(HeapVector<NGFlexLine>& flex_line_outputs) const;
#endif
diff --git a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
index 6b305c8..b78a6f0 100644
--- a/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
+++ b/third_party/blink/web_tests/FlagExpectations/disable-layout-ng
@@ -158,6 +158,8 @@
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-039.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-040.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-047.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-007.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-008.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/multi-line-row-flex-fragmentation-010.html [ Failure ]
@@ -216,6 +218,8 @@
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-044.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-045.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-046.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html [ Failure ]
+crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-014.html [ Failure ]
crbug.com/660611 external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-015.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html
new file mode 100644
index 0000000..8280041
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-048.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item that shrinks *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column; flex-wrap: wrap; height: 200px;">
+ <div style="background: green; flex-basis: fit-content; height: 10px; width: 25px;">
+ <div style="contain: size; width: 25px; height: 50px;"></div>
+ <div style="contain: size; width: 25px; height: 100px;"></div>
+ </div>
+ <div style="background: green; width: 25px; height: 50px;"></div>
+ <div style="background: green; flex-basis: min-content; height: 10px; width: 25px;">
+ <div style="contain: size; width: 25px; height: 50px;"></div>
+ <div style="contain: size; width: 25px; height: 100px;"></div>
+ </div>
+ <div style="background: green; width: 25px; height: 50px;"></div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html
new file mode 100644
index 0000000..0ede74a
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/multi-line-column-flex-fragmentation-049.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with an indefinite flex-basis expands if the
+ container hieght is auto.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: content; height: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html
new file mode 100644
index 0000000..ae683e93
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-050.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with an indefinite flex-basis expands if the
+ container height is auto.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: content; height: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html
new file mode 100644
index 0000000..9fc2a6e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-051.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with a definite flex-basis *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: 10px; height: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ <div style="background: green; width: 50px; height: 190px;"></div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html
new file mode 100644
index 0000000..faa0d130
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-052.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with an definite flex-basis but an indefinite height expands.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html
new file mode 100644
index 0000000..524870e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-053.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item that can't shrink and has a definite flex-basis, an
+ indefinite height, and a non-auto min-height *doesn't* expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column; height: 100px;">
+ <div style="background: green; flex-basis: 10px; min-height: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ <div style="background: green; width: 50px; height: 190px;"></div>
+ </div>
+ <div style="background: green; width: 50px; height: 100px;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html
new file mode 100644
index 0000000..60c130e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-054.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with an definite flex-basis, an indefinite height, and
+ a non-auto min-height does expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: 10px; min-height: 10px;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html
new file mode 100644
index 0000000..2958e616
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-column-flex-fragmentation-055.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>
+ Tests that a flex-item with an definite flex-basis, an indefinite height, and
+ can't shrink does expand.
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
+<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 style="width: 100px; height: 100px; columns: 2; column-gap: 0; background: red;">
+ <div style="display: flex; flex-direction: column;">
+ <div style="background: green; flex-basis: 10px; justify-self: flex-start;">
+ <div style="contain: size; width: 50px; height: 50px;"></div>
+ <div style="contain: size; width: 50px; height: 100px;"></div>
+ </div>
+ </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
index 562cb61..dfade0f 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-008.html
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<title>
- Tests that a flex-item with a fixed block-size container grows due to fragmentation.
+ Tests that a flex-item with a fixed block-size container *doesn't* grow due to fragmentation
+ if stretched.
</title>
<link rel="help" href="https://drafts.csswg.org/css-flexbox-1/#pagination">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht">
@@ -12,4 +13,5 @@
<div style="display: inline-block; width: 50px; height: 100px;"></div>
</div>
</div>
+ <div style="background: green; width: 50px; height: 100px;"></div>
</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
index b51c7883..8dbaa692 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-break/flexbox/single-line-row-flex-fragmentation-009.html
@@ -8,7 +8,7 @@
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="width: 100px; height: 100px; columns: 2; column-gap: 0; column-fill: auto; background: red;">
<div style="display: flex; background: green;">
- <div style="display: flex;">
+ <div style="display: flex; align-self: flex-start;">
<div style="line-height: 0;">
<div style="display: inline-block; width: 50px; height: 50px;"></div>
<div style="display: inline-block; width: 50px; height: 100px;"></div>