From d49d43a4a49bf00a4ce504b647df56e6f1787215 Mon Sep 17 00:00:00 2001 From: ldm0 Date: Thu, 10 Sep 2026 00:12:57 +0800 Subject: [PATCH] fix(layout): preserve grid auto sizing before aspect ratio transfer Keep normal distinct from auto at the style boundary and consume the shared Taffy grid sizing contract. Cover alignment, limits, intrinsic sizes, margins, writing modes, and actual child formatting contexts with 288 screenshot geometry checks. --- Cargo.lock | 2 +- Cargo.toml | 2 +- moli-layout/src/positioned.rs | 12 ++- moli-layout/src/style.rs | 16 ++-- .../page_vm/tests/preferred_aspect_ratio.rs | 39 ++++++++++ .../tests/fixtures/grid-item-sizing.html | 78 +++++++++++++++++++ 6 files changed, 138 insertions(+), 11 deletions(-) create mode 100644 moli-renderer-v8/tests/fixtures/grid-item-sizing.html diff --git a/Cargo.lock b/Cargo.lock index 768f9ff50f..8fb5dbc62f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4842,7 +4842,7 @@ dependencies = [ [[package]] name = "taffy" version = "0.13.0" -source = "git+https://github.com/ldm0/taffy?rev=b5a55e2b3b7aa3b71ae9f8dfb124fb018c4a2cf2#b5a55e2b3b7aa3b71ae9f8dfb124fb018c4a2cf2" +source = "git+https://github.com/ldm0/taffy?rev=7d52b6d0d1e33497df83940b6d6ca33f09c947ff#7d52b6d0d1e33497df83940b6d6ca33f09c947ff" dependencies = [ "arrayvec", "serde", diff --git a/Cargo.toml b/Cargo.toml index 9bb265fa61..a33088d3e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,7 +102,7 @@ stylo_atoms = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e937 stylo_dom = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } stylo_static_prefs = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } stylo_traits = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } -taffy = { git = "https://github.com/ldm0/taffy", rev = "b5a55e2b3b7aa3b71ae9f8dfb124fb018c4a2cf2" } +taffy = { git = "https://github.com/ldm0/taffy", rev = "7d52b6d0d1e33497df83940b6d6ca33f09c947ff" } [workspace.lints.clippy] disallowed_methods = "deny" diff --git a/moli-layout/src/positioned.rs b/moli-layout/src/positioned.rs index 55433a394e..00ab90bd91 100644 --- a/moli-layout/src/positioned.rs +++ b/moli-layout/src/positioned.rs @@ -233,10 +233,15 @@ impl FlexCrossAxisStaticContext { } } AlignItemsKeyword::FlexEnd if !wrap_reverse => LogicalStaticEdge::End, - AlignItemsKeyword::FlexStart | AlignItemsKeyword::Stretch if wrap_reverse => { + AlignItemsKeyword::Normal + | AlignItemsKeyword::FlexStart + | AlignItemsKeyword::Stretch + if wrap_reverse => + { LogicalStaticEdge::End } - AlignItemsKeyword::Start + AlignItemsKeyword::Normal + | AlignItemsKeyword::Start | AlignItemsKeyword::FlexStart | AlignItemsKeyword::FlexEnd | AlignItemsKeyword::Baseline @@ -286,7 +291,8 @@ pub(crate) fn grid_static_alignment( LogicalStaticEdge::End } } - AlignItemsKeyword::Start + AlignItemsKeyword::Normal + | AlignItemsKeyword::Start | AlignItemsKeyword::FlexStart | AlignItemsKeyword::Baseline | AlignItemsKeyword::Stretch => LogicalStaticEdge::Start, diff --git a/moli-layout/src/style.rs b/moli-layout/src/style.rs index c48996f8de..f380f61f0b 100644 --- a/moli-layout/src/style.rs +++ b/moli-layout/src/style.rs @@ -2650,16 +2650,18 @@ fn stylo_vertical_align( ) } -/// Preserve the baseline preference at the style boundary. The pinned Blitz -/// converter predates Taffy's last-baseline support and lowers it to `end`. +/// Preserve normal versus auto and both baseline preferences at the style +/// boundary. The pinned Blitz converter predates these Taffy distinctions. /// Both normal-flow and positioned alignment must retain the same CSS value. pub(crate) fn taffy_item_alignment( flags: style::values::specified::align::AlignFlags, ) -> Option { - if flags.value() == style::values::specified::align::AlignFlags::LAST_BASELINE { - Some(taffy::AlignItems::LAST_BASELINE) - } else { - stylo_taffy::convert::item_alignment(flags) + match flags.value() { + style::values::specified::align::AlignFlags::NORMAL => Some(taffy::AlignItems::NORMAL), + style::values::specified::align::AlignFlags::LAST_BASELINE => { + Some(taffy::AlignItems::LAST_BASELINE) + } + _ => stylo_taffy::convert::item_alignment(flags), } } @@ -2681,7 +2683,9 @@ mod alignment_tests { #[test] fn item_alignment_keeps_baseline_preference_and_positional_safety_distinct() { + assert_eq!(taffy_item_alignment(AlignFlags::AUTO), None); for (flags, expected) in [ + (AlignFlags::NORMAL, AlignItems::NORMAL), (AlignFlags::BASELINE, AlignItems::BASELINE), (AlignFlags::LAST_BASELINE, AlignItems::LAST_BASELINE), (AlignFlags::END, AlignItems::END), diff --git a/moli-renderer-v8/src/runtime/page_vm/tests/preferred_aspect_ratio.rs b/moli-renderer-v8/src/runtime/page_vm/tests/preferred_aspect_ratio.rs index 031327dc52..7862dd6606 100644 --- a/moli-renderer-v8/src/runtime/page_vm/tests/preferred_aspect_ratio.rs +++ b/moli-renderer-v8/src/runtime/page_vm/tests/preferred_aspect_ratio.rs @@ -1,5 +1,44 @@ use super::*; +#[tokio::test(flavor = "current_thread")] +async fn screenshot_resolves_grid_stretch_before_ratio_dependent_sizes() { + run_page_vm_async_test(async move { + let loader = crate::network::ResourceRequestClient::new(&FetchConfig::default())?; + let mut page = test_page_vm_with_loader_and_document_url( + &loader, + Vec::new(), + Url::parse("https://example.com/grid-item-sizing.html")?, + ); + page.vm_mut() + .set_layout_policy(moli_page_types::LayoutPolicy::OnDemand); + let fixture = include_str!("../../../../tests/fixtures/grid-item-sizing.html"); + page.vm_mut().eval(&format!( + "document.open();document.write({});document.close()", + serde_json::to_string(fixture)?, + ))?; + page.vm_mut() + .prime_document_lifecycle_processing_and_record_stylesheet_network_results(); + page.vm_mut() + .screenshot_layout_snapshot(moli_layout::PaintViewport::new(1500, 1800, 1.0))? + .expect("grid sizing fixture must retain a layout root"); + let checks: serde_json::Value = serde_json::from_str( + &page + .vm_mut() + .eval("JSON.stringify(collectGridItemSizingChecks())")?, + )?; + let checks = checks.as_array().expect("grid sizing checks"); + assert_eq!(checks.len(), 288); + let failures: Vec<_> = checks + .iter() + .filter(|check| check["actual"] != check["expected"]) + .collect(); + assert!(failures.is_empty(), "grid sizing mismatches: {failures:#?}"); + Ok::<_, anyhow::Error>(()) + }) + .await + .expect("grid automatic sizing fixture should run"); +} + /// WPT abspos-005/012/013 with authored stretch, limits and percentage-basis /// controls across all formatting owners, including inline containing blocks. #[tokio::test(flavor = "current_thread")] diff --git a/moli-renderer-v8/tests/fixtures/grid-item-sizing.html b/moli-renderer-v8/tests/fixtures/grid-item-sizing.html new file mode 100644 index 0000000000..e3caf8e648 --- /dev/null +++ b/moli-renderer-v8/tests/fixtures/grid-item-sizing.html @@ -0,0 +1,78 @@ + + +Grid auto sizing preserves alignment and ratio constraint sources + + + +