diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs index d1314c8dfbc..81364d10487 100644 --- a/components/layout_2020/flexbox/layout.rs +++ b/components/layout_2020/flexbox/layout.rs @@ -62,9 +62,7 @@ struct FlexContext<'a> { /// A flex item with some intermediate results struct FlexItem<'a> { box_: &'a FlexItemBox, - content_cross_size: Size, - content_min_size: FlexRelativeVec2, - content_max_size: FlexRelativeVec2>, + content_cross_sizes: Sizes, padding: FlexRelativeSides, border: FlexRelativeSides, margin: FlexRelativeSides, @@ -84,6 +82,14 @@ struct FlexItem<'a> { /// hypothetical_main_size: Au, + /// The used min main size of the flex item. + /// + content_min_main_size: Au, + + /// The used max main size of the flex item. + /// + content_max_main_size: Option, + /// This is `align-self`, defaulting to `align-items` if `auto` align_self: AlignItems, @@ -1222,9 +1228,10 @@ impl<'a> FlexItem<'a> { Self { box_, - content_cross_size: flex_relative_content_box_size.cross, - content_min_size: flex_relative_content_min_size, - content_max_size: flex_relative_content_max_size, + content_cross_sizes: match config.flex_axis { + FlexAxis::Row => content_box_sizes.block, + FlexAxis::Column => content_box_sizes.inline, + }, padding, border, margin, @@ -1232,6 +1239,8 @@ impl<'a> FlexItem<'a> { flex_base_size, flex_base_size_is_definite, hypothetical_main_size, + content_min_main_size: flex_relative_content_min_size.main, + content_max_main_size: flex_relative_content_max_size.main, align_self, depends_on_block_constraints, preferred_aspect_ratio, @@ -1242,7 +1251,7 @@ impl<'a> FlexItem<'a> { // Note this returns false for a `stretch` size, because that stretches to the // containing block, not to the flex line. // To be discussed in https://github.com/w3c/csswg-drafts/issues/11784. - self.content_cross_size.is_initial() && + self.content_cross_sizes.preferred.is_initial() && item_with_auto_cross_size_stretches_to_line_size(self.align_self, &self.margin) } } @@ -1562,8 +1571,8 @@ impl InitialFlexLineLayout<'_> { let violation = |item: &FlexibleLengthResolutionItem| { let size = item.target_main_size.get(); let clamped = size.clamp_between_extremums( - item.item.content_min_size.main, - item.item.content_max_size.main, + item.item.content_min_main_size, + item.item.content_max_main_size, ); clamped - size }; @@ -1588,7 +1597,7 @@ impl InitialFlexLineLayout<'_> { // it’s a min violation.” for item in items.iter() { if violation(item) > Au::zero() { - item.target_main_size.set(item.item.content_min_size.main); + item.target_main_size.set(item.item.content_min_main_size); item.frozen.set(true); frozen_count += 1; } @@ -1601,7 +1610,7 @@ impl InitialFlexLineLayout<'_> { // it’s a max violation.” for item in items.iter() { if violation(item) < Au::zero() { - let Some(max_size) = item.item.content_max_size.main else { + let Some(max_size) = item.item.content_max_main_size else { unreachable!() }; item.target_main_size.set(max_size); @@ -1697,9 +1706,21 @@ impl InitialFlexLineLayout<'_> { for item in self.items.iter_mut() { let stretches = item.item.stretches_to_line(); let used_cross_size = if stretches { - (final_line_cross_size - item.item.pbm_auto_is_zero.cross).clamp_between_extremums( - item.item.content_min_size.cross, - item.item.content_max_size.cross, + let (axis, content_size) = match flex_context.config.flex_axis { + FlexAxis::Row => (Direction::Block, item.layout_result.content_size.block), + FlexAxis::Column => (Direction::Inline, item.layout_result.content_size.inline), + }; + item.item.content_cross_sizes.resolve( + axis, + Size::Stretch, + Au::zero(), + Some(final_line_cross_size - item.item.pbm_auto_is_zero.cross), + || content_size.into(), + // Tables have a special sizing in the block axis in that handles collapsed rows, + // but it would prevent stretching. So we only recognize tables in the inline axis. + // The interaction of collapsed table tracks and the flexbox algorithms is unclear, + // see https://github.com/w3c/csswg-drafts/issues/11408. + item.item.is_table() && axis == Direction::Inline, ) } else { item.layout_result.hypothetical_cross_size @@ -1909,11 +1930,10 @@ impl FlexItem<'_> { .block .to_definite() .map(|size| Au::zero().max(size - self.pbm_auto_is_zero.cross)); - SizeConstraint::new( - self.content_cross_size - .maybe_resolve_extrinsic(stretch_size), - self.content_min_size.cross, - self.content_max_size.cross, + self.content_cross_sizes.resolve_extrinsic( + Size::FitContent, + Au::zero(), + stretch_size, ) }, }; @@ -1931,7 +1951,7 @@ impl FlexItem<'_> { }; let stretch_size = Au::zero().max(containing_block.size.inline - self.pbm_auto_is_zero.cross); - let content_size = LazyCell::new(|| { + let get_content_size = || { let constraint_space = ConstraintSpace::new( SizeConstraint::Definite(used_main_size), item_writing_mode, @@ -1940,13 +1960,15 @@ impl FlexItem<'_> { independent_formatting_context .inline_content_sizes(flex_context.layout_context, &constraint_space) .sizes - }); - self.content_cross_size - .resolve_for_preferred(automatic_size, Some(stretch_size), &content_size) - .clamp_between_extremums( - self.content_min_size.cross, - self.content_max_size.cross, - ) + }; + self.content_cross_sizes.resolve( + Direction::Inline, + automatic_size, + Au::zero(), + Some(stretch_size), + get_content_size, + self.is_table(), + ) }); // The main size of a flex item is considered to be definite if its flex basis is definite // or the flex container has a definite main size. @@ -1968,8 +1990,16 @@ impl FlexItem<'_> { let item_style = independent_formatting_context.style(); match &independent_formatting_context.contents { IndependentFormattingContextContents::Replaced(replaced) => { - let min_size = flex_axis.vec2_to_flow_relative(self.content_min_size); - let max_size = flex_axis.vec2_to_flow_relative(self.content_max_size); + let min_size = flex_axis.vec2_to_flow_relative(FlexRelativeVec2 { + main: Size::Numeric(self.content_min_main_size), + cross: self.content_cross_sizes.min, + }); + let max_size = flex_axis.vec2_to_flow_relative(FlexRelativeVec2 { + main: self + .content_max_main_size + .map_or(Size::Initial, Size::Numeric), + cross: self.content_cross_sizes.max, + }); let size = replaced.used_size_as_if_inline_element_from_content_box_sizes( containing_block, item_style, @@ -1979,13 +2009,13 @@ impl FlexItem<'_> { block_size .to_definite() .map_or(Size::Initial, Size::Numeric), - Size::Numeric(min_size.block), - max_size.block.map_or(Size::Initial, Size::Numeric), + min_size.block, + max_size.block, ), inline: &Sizes::new( Size::Numeric(inline_size), - Size::Numeric(min_size.inline), - max_size.inline.map_or(Size::Initial, Size::Numeric), + min_size.inline, + max_size.inline, ), }, Size::FitContent.into(), @@ -2043,13 +2073,14 @@ impl FlexItem<'_> { .block .to_definite() .map(|size| Au::zero().max(size - self.pbm_auto_is_zero.cross)); - let content_size = LazyCell::new(|| content_block_size.into()); - self.content_cross_size - .resolve_for_preferred(Size::FitContent, stretch_size, &content_size) - .clamp_between_extremums( - self.content_min_size.cross, - self.content_max_size.cross, - ) + self.content_cross_sizes.resolve( + Direction::Block, + Size::FitContent, + Au::zero(), + stretch_size, + || content_block_size.into(), + self.is_table(), + ) }; let item_as_containing_block = ContainingBlock { @@ -2278,6 +2309,14 @@ impl FlexItem<'_> { }; outer_cross_start + margin.cross_start + self.border.cross_start + self.padding.cross_start } + + #[inline] + fn is_table(&self) -> bool { + match &self.box_.independent_formatting_context.contents { + IndependentFormattingContextContents::NonReplaced(content) => content.is_table(), + IndependentFormattingContextContents::Replaced(_) => false, + } + } } impl FlexItemBox { diff --git a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-001.html.ini b/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-001.html.ini index 0e701728602..2904196c0f7 100644 --- a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-001.html.ini +++ b/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-001.html.ini @@ -53,24 +53,6 @@ [.test 27] expected: FAIL - [.test 31] - expected: FAIL - - [.test 32] - expected: FAIL - - [.test 33] - expected: FAIL - - [.test 34] - expected: FAIL - - [.test 35] - expected: FAIL - - [.test 36] - expected: FAIL - [.test 40] expected: FAIL @@ -88,39 +70,3 @@ [.test 45] expected: FAIL - - [.test 49] - expected: FAIL - - [.test 50] - expected: FAIL - - [.test 51] - expected: FAIL - - [.test 52] - expected: FAIL - - [.test 53] - expected: FAIL - - [.test 54] - expected: FAIL - - [.test 69] - expected: FAIL - - [.test 70] - expected: FAIL - - [.test 71] - expected: FAIL - - [.test 72] - expected: FAIL - - [.test 73] - expected: FAIL - - [.test 74] - expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-002.html.ini b/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-002.html.ini index 25aae054dbb..46801b288c1 100644 --- a/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-002.html.ini +++ b/tests/wpt/meta/css/css-sizing/keyword-sizes-on-flex-item-002.html.ini @@ -1,58 +1,4 @@ [keyword-sizes-on-flex-item-002.html] - [.test 10] - expected: FAIL - - [.test 11] - expected: FAIL - - [.test 12] - expected: FAIL - - [.test 13] - expected: FAIL - - [.test 14] - expected: FAIL - - [.test 15] - expected: FAIL - - [.test 16] - expected: FAIL - - [.test 17] - expected: FAIL - - [.test 18] - expected: FAIL - - [.test 19] - expected: FAIL - - [.test 20] - expected: FAIL - - [.test 21] - expected: FAIL - - [.test 22] - expected: FAIL - - [.test 23] - expected: FAIL - - [.test 24] - expected: FAIL - - [.test 25] - expected: FAIL - - [.test 26] - expected: FAIL - - [.test 27] - expected: FAIL - [.test 31] expected: FAIL @@ -71,24 +17,6 @@ [.test 36] expected: FAIL - [.test 40] - expected: FAIL - - [.test 41] - expected: FAIL - - [.test 42] - expected: FAIL - - [.test 43] - expected: FAIL - - [.test 44] - expected: FAIL - - [.test 45] - expected: FAIL - [.test 49] expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/stretch/stretch-max-block-size-001.html.ini b/tests/wpt/meta/css/css-sizing/stretch/stretch-max-block-size-001.html.ini index 71b6ee86c40..3bd7768ed11 100644 --- a/tests/wpt/meta/css/css-sizing/stretch/stretch-max-block-size-001.html.ini +++ b/tests/wpt/meta/css/css-sizing/stretch/stretch-max-block-size-001.html.ini @@ -2,24 +2,12 @@ [[data-expected-height\] 8] expected: FAIL - [[data-expected-height\] 19] - expected: FAIL - - [[data-expected-height\] 21] - expected: FAIL - [[data-expected-height\] 22] expected: FAIL [[data-expected-height\]:not([skip-second-pass\]) 31] expected: FAIL - [[data-expected-height\]:not([skip-second-pass\]) 42] - expected: FAIL - - [[data-expected-height\]:not([skip-second-pass\]) 44] - expected: FAIL - [[data-expected-height\]:not([skip-second-pass\]) 45] expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/stretch/stretch-max-inline-size-001.html.ini b/tests/wpt/meta/css/css-sizing/stretch/stretch-max-inline-size-001.html.ini index bc982d6c609..ab96bc9fd84 100644 --- a/tests/wpt/meta/css/css-sizing/stretch/stretch-max-inline-size-001.html.ini +++ b/tests/wpt/meta/css/css-sizing/stretch/stretch-max-inline-size-001.html.ini @@ -2,24 +2,12 @@ [[data-expected-width\] 8] expected: FAIL - [[data-expected-width\] 20] - expected: FAIL - - [[data-expected-width\] 21] - expected: FAIL - [[data-expected-width\] 22] expected: FAIL [[data-expected-width\]:not([skip-second-pass\]) 31] expected: FAIL - [[data-expected-width\]:not([skip-second-pass\]) 43] - expected: FAIL - - [[data-expected-width\]:not([skip-second-pass\]) 44] - expected: FAIL - [[data-expected-width\]:not([skip-second-pass\]) 45] expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/stretch/stretch-min-block-size-001.html.ini b/tests/wpt/meta/css/css-sizing/stretch/stretch-min-block-size-001.html.ini index 294a25e4bd6..93d44c91b04 100644 --- a/tests/wpt/meta/css/css-sizing/stretch/stretch-min-block-size-001.html.ini +++ b/tests/wpt/meta/css/css-sizing/stretch/stretch-min-block-size-001.html.ini @@ -2,29 +2,17 @@ [[data-expected-height\] 8] expected: FAIL - [[data-expected-height\] 19] - expected: FAIL - [[data-expected-height\] 20] expected: FAIL - [[data-expected-height\] 21] - expected: FAIL - [[data-expected-height\] 22] expected: FAIL [[data-expected-height\] 31] expected: FAIL - [[data-expected-height\] 42] - expected: FAIL - [[data-expected-height\] 43] expected: FAIL - [[data-expected-height\] 44] - expected: FAIL - [[data-expected-height\] 45] expected: FAIL diff --git a/tests/wpt/meta/css/css-sizing/stretch/stretch-min-inline-size-001.html.ini b/tests/wpt/meta/css/css-sizing/stretch/stretch-min-inline-size-001.html.ini index bf576c14464..2162a706abd 100644 --- a/tests/wpt/meta/css/css-sizing/stretch/stretch-min-inline-size-001.html.ini +++ b/tests/wpt/meta/css/css-sizing/stretch/stretch-min-inline-size-001.html.ini @@ -5,12 +5,6 @@ [[data-expected-width\] 19] expected: FAIL - [[data-expected-width\] 20] - expected: FAIL - - [[data-expected-width\] 21] - expected: FAIL - [[data-expected-width\] 22] expected: FAIL @@ -20,11 +14,5 @@ [[data-expected-width\] 42] expected: FAIL - [[data-expected-width\] 43] - expected: FAIL - - [[data-expected-width\] 44] - expected: FAIL - [[data-expected-width\] 45] expected: FAIL