From c7502a99f05b1806e2f01b7790227919e382a555 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 14 Apr 2025 11:00:32 -0700 Subject: [PATCH] layout: Floor the max-content size by the min-content size (#36518) It's typically a given that the min-content size can't exceed the max-content size. However, it was possible to break that assumption when an inline formatting context had contents with a negative outer size (due to margins). This could lead to assert failures. This patch avoids the problem by flooring the max-content size to not be smaller than the min-content size. Note there is no interoperability: https://github.com/w3c/csswg-drafts/issues/12076 Testing: adding new reftest and crashtest Fixes: #36481 Signed-off-by: Oriol Brufau --- components/layout_2020/flow/inline/mod.rs | 10 ++++- tests/wpt/meta/MANIFEST.json | 20 ++++++++++ .../min-content-le-max-content.tentative.html | 37 +++++++++++++++++++ ...ell-contents-with-negative-outer-size.html | 6 +++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 tests/wpt/tests/css/css-sizing/min-content-le-max-content.tentative.html create mode 100644 tests/wpt/tests/css/css-tables/crashtests/cell-contents-with-negative-outer-size.html diff --git a/components/layout_2020/flow/inline/mod.rs b/components/layout_2020/flow/inline/mod.rs index a93956e8472..1f686120c32 100644 --- a/components/layout_2020/flow/inline/mod.rs +++ b/components/layout_2020/flow/inline/mod.rs @@ -2285,10 +2285,16 @@ impl<'layout_data> ContentSizesComputation<'layout_data> { for inline_item in inline_formatting_context.inline_items.iter() { self.process_item(&inline_item.borrow(), inline_formatting_context); } - self.forced_line_break(); + + // We might get a max-content size which is smaller than the min-content size, + // due to negative margins. So we need to adjust to avoid problems down the line. + // This is being discussed in . + let mut sizes = self.paragraph; + sizes.max_content.max_assign(sizes.min_content); + InlineContentSizesResult { - sizes: self.paragraph, + sizes, depends_on_block_constraints: self.depends_on_block_constraints, } } diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json index 73a9eb8e479..04b454ad1df 100644 --- a/tests/wpt/meta/MANIFEST.json +++ b/tests/wpt/meta/MANIFEST.json @@ -4901,6 +4901,13 @@ {} ] ], + "cell-contents-with-negative-outer-size.html": [ + "c9cd275ad9e07fa33fa4c8ac363b891562628614", + [ + null, + {} + ] + ], "col_span_dynamic_crash.html": [ "67630066fad440e64f901512622cbaabdc4af370", [ @@ -249543,6 +249550,19 @@ {} ] ], + "min-content-le-max-content.tentative.html": [ + "81bc6969d50cd57e33b0268bc26bec6ec42ea6a9", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "min-content-min-width-000.html": [ "9dff1b973477b15b1118787e4ad5d213abfb6809", [ diff --git a/tests/wpt/tests/css/css-sizing/min-content-le-max-content.tentative.html b/tests/wpt/tests/css/css-sizing/min-content-le-max-content.tentative.html new file mode 100644 index 00000000000..81bc6969d50 --- /dev/null +++ b/tests/wpt/tests/css/css-sizing/min-content-le-max-content.tentative.html @@ -0,0 +1,37 @@ + + +min-content ≤ max-content + + + + + + + + +

Test passes if there is a filled green square and no red.

+
+
+ + +
+
+ + +
+
diff --git a/tests/wpt/tests/css/css-tables/crashtests/cell-contents-with-negative-outer-size.html b/tests/wpt/tests/css/css-tables/crashtests/cell-contents-with-negative-outer-size.html new file mode 100644 index 00000000000..c9cd275ad9e --- /dev/null +++ b/tests/wpt/tests/css/css-tables/crashtests/cell-contents-with-negative-outer-size.html @@ -0,0 +1,6 @@ + + + + + +
a