From ede8a90a58fd04038fa072ed4c80c6d5611c3aaf Mon Sep 17 00:00:00 2001 From: ldm0 Date: Wed, 9 Sep 2026 04:45:31 +0800 Subject: [PATCH] fix(layout): preserve flex baseline semantics across logical flows Use typed alphabetic/central baseline context from Stylo and preserve sideways writing modes at the Taffy boundary. Pin Taffy's independent baseline-sharing groups, physical first/last baseline export, and stretch fallback fix. Add 324 Chromium-backed geometry and pixel checks, retaining static-margin and reversed-inset regressions. Required fmt, workspace Clippy and all 17184 Nextest tests pass; focused release WPT comparison improves 35 to 47 of 96 cases without pass-to-fail regressions. --- Cargo.lock | 24 ++-- Cargo.toml | 16 +-- moli-layout/src/style.rs | 6 + moli-layout/src/taffy_tree.rs | 20 +++ ...ex_static_position.rs => flex_geometry.rs} | 16 ++- .../src/runtime/page_vm/tests/mod.rs | 2 +- .../tests/fixtures/flex-baseline-flows.html | 134 ++++++++++++++++++ 7 files changed, 196 insertions(+), 22 deletions(-) rename moli-renderer-v8/src/runtime/page_vm/tests/{flex_static_position.rs => flex_geometry.rs} (86%) create mode 100644 moli-renderer-v8/tests/fixtures/flex-baseline-flows.html diff --git a/Cargo.lock b/Cargo.lock index 02210ccde9..9d95b93fdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4266,7 +4266,7 @@ dependencies = [ [[package]] name = "selectors" version = "0.40.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "bitflags", "cssparser", @@ -4398,7 +4398,7 @@ dependencies = [ [[package]] name = "servo_arc" version = "0.4.3" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "serde", "stable_deref_trait", @@ -4645,7 +4645,7 @@ dependencies = [ [[package]] name = "stylo" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "app_units", "arrayvec", @@ -4701,7 +4701,7 @@ dependencies = [ [[package]] name = "stylo_atoms" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "string_cache", "string_cache_codegen", @@ -4710,7 +4710,7 @@ dependencies = [ [[package]] name = "stylo_derive" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "darling", "proc-macro2", @@ -4722,7 +4722,7 @@ dependencies = [ [[package]] name = "stylo_dom" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "bitflags", "stylo_malloc_size_of", @@ -4731,7 +4731,7 @@ dependencies = [ [[package]] name = "stylo_malloc_size_of" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "app_units", "cssparser", @@ -4748,7 +4748,7 @@ dependencies = [ [[package]] name = "stylo_static_prefs" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "toml", ] @@ -4766,7 +4766,7 @@ dependencies = [ [[package]] name = "stylo_traits" version = "0.20.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "app_units", "bitflags", @@ -4842,7 +4842,7 @@ dependencies = [ [[package]] name = "taffy" version = "0.13.0" -source = "git+https://github.com/ldm0/taffy?rev=082327a5cb0d2ee1fed4c0ac5f339e1c1a51b576#082327a5cb0d2ee1fed4c0ac5f339e1c1a51b576" +source = "git+https://github.com/ldm0/taffy?rev=4922df49ff9eba488de9c5c44d3c4a1cf54876f9#4922df49ff9eba488de9c5c44d3c4a1cf54876f9" dependencies = [ "arrayvec", "serde", @@ -5053,7 +5053,7 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "to_shmem" version = "0.5.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "cssparser", "servo_arc", @@ -5066,7 +5066,7 @@ dependencies = [ [[package]] name = "to_shmem_derive" version = "0.1.0" -source = "git+https://github.com/ldm0/stylo?rev=e6cdff0a2eb7e51a313dabe8dc48a13a08314493#e6cdff0a2eb7e51a313dabe8dc48a13a08314493" +source = "git+https://github.com/ldm0/stylo?rev=cfa170da90c467e93786ec0fa5526bd83f201933#cfa170da90c467e93786ec0fa5526bd83f201933" dependencies = [ "darling", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index 1fa9498189..11b66a1cbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,14 +95,14 @@ curl-sys = { git = "https://github.com/ldm0/curl-rust", branch = "moli" } cookie = { git = "https://github.com/ldm0/cookie-rs", branch = "priority" } v8 = { path = "vendor/v8-152.2.0" } deno_v8 = { path = "vendor/deno_v8-0.3.0" } -selectors = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -servo_arc = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -stylo = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -stylo_atoms = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -stylo_dom = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -stylo_static_prefs = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -stylo_traits = { git = "https://github.com/ldm0/stylo", rev = "e6cdff0a2eb7e51a313dabe8dc48a13a08314493" } -taffy = { git = "https://github.com/ldm0/taffy", rev = "082327a5cb0d2ee1fed4c0ac5f339e1c1a51b576" } +selectors = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } +servo_arc = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } +stylo = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } +stylo_atoms = { git = "https://github.com/ldm0/stylo", rev = "cfa170da90c467e93786ec0fa5526bd83f201933" } +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 = "4922df49ff9eba488de9c5c44d3c4a1cf54876f9" } [workspace.lints.clippy] disallowed_methods = "deny" diff --git a/moli-layout/src/style.rs b/moli-layout/src/style.rs index 155247f3c8..f7d69d82f8 100644 --- a/moli-layout/src/style.rs +++ b/moli-layout/src/style.rs @@ -137,6 +137,8 @@ pub(crate) enum LayoutWritingMode { HorizontalTb, VerticalRl, VerticalLr, + SidewaysRl, + SidewaysLr, } impl LayoutWritingMode { @@ -145,6 +147,8 @@ impl LayoutWritingMode { StyloWritingMode::HorizontalTb => Self::HorizontalTb, StyloWritingMode::VerticalRl => Self::VerticalRl, StyloWritingMode::VerticalLr => Self::VerticalLr, + StyloWritingMode::SidewaysRl => Self::SidewaysRl, + StyloWritingMode::SidewaysLr => Self::SidewaysLr, } } @@ -158,6 +162,8 @@ impl LayoutWritingMode { Self::HorizontalTb => taffy::WritingMode::HorizontalTb, Self::VerticalRl => taffy::WritingMode::VerticalRl, Self::VerticalLr => taffy::WritingMode::VerticalLr, + Self::SidewaysRl => taffy::WritingMode::SidewaysRl, + Self::SidewaysLr => taffy::WritingMode::SidewaysLr, } } } diff --git a/moli-layout/src/taffy_tree.rs b/moli-layout/src/taffy_tree.rs index 2b0e25be5c..3f68ad9ac4 100644 --- a/moli-layout/src/taffy_tree.rs +++ b/moli-layout/src/taffy_tree.rs @@ -1501,6 +1501,26 @@ where } } + fn get_baseline_type(&self, node_id: NodeId) -> taffy::BaselineType { + if self.is_viewport_taffy_node(node_id) { + return taffy::BaselineType::Alphabetic; + } + let style = &self.boxes[LayoutBoxId::from_taffy(node_id).index()].style; + style.stylo_computed_values().map_or_else( + || taffy::BaselineType::for_writing_mode(style.writing_mode()), + |computed| { + // Stylo's writing direction includes text-orientation as well + // as writing-mode. Sideways text uses an alphabetic baseline; + // upright vertical text uses a central baseline, like Blink. + if computed.writing_mode.is_text_vertical() { + taffy::BaselineType::Central + } else { + taffy::BaselineType::Alphabetic + } + }, + ) + } + fn get_scrollbar_insets(&self, node_id: NodeId) -> taffy::Rect { if self.is_viewport_taffy_node(node_id) { // The synthetic viewport expresses its gutters as non-painted diff --git a/moli-renderer-v8/src/runtime/page_vm/tests/flex_static_position.rs b/moli-renderer-v8/src/runtime/page_vm/tests/flex_geometry.rs similarity index 86% rename from moli-renderer-v8/src/runtime/page_vm/tests/flex_static_position.rs rename to moli-renderer-v8/src/runtime/page_vm/tests/flex_geometry.rs index 0caeec4cd7..ce51d00267 100644 --- a/moli-renderer-v8/src/runtime/page_vm/tests/flex_static_position.rs +++ b/moli-renderer-v8/src/runtime/page_vm/tests/flex_geometry.rs @@ -1,5 +1,16 @@ use super::*; +#[tokio::test(flavor = "current_thread")] +async fn screenshot_resolves_flex_baselines_across_logical_flows() { + assert_flex_geometry_fixture( + include_str!("../../../../tests/fixtures/flex-baseline-flows.html"), + "collectFlexBaselineChecks()", + 324, + 1980, + ) + .await; +} + #[tokio::test(flavor = "current_thread")] async fn screenshot_resolves_flex_static_margin_boxes_across_containing_blocks() { assert_flex_geometry_fixture( @@ -74,9 +85,12 @@ async fn assert_flex_geometry_fixture( let x = check["pixel"][0].as_f64().expect("pixel x") as usize; let y = check["pixel"][1].as_f64().expect("pixel y") as usize; let offset = (y * image.width as usize + x) * 4; + let color: [u8; 4] = check.get("color").map_or([31, 127, 63, 255], |color| { + std::array::from_fn(|index| color[index].as_u64().expect("color channel") as u8) + }); assert_eq!( &image.rgba[offset..offset + 4], - &[31, 127, 63, 255], + &color, "{} paint", check["id"] ); diff --git a/moli-renderer-v8/src/runtime/page_vm/tests/mod.rs b/moli-renderer-v8/src/runtime/page_vm/tests/mod.rs index adb0bec30a..90eea3d4af 100644 --- a/moli-renderer-v8/src/runtime/page_vm/tests/mod.rs +++ b/moli-renderer-v8/src/runtime/page_vm/tests/mod.rs @@ -124,7 +124,7 @@ mod element_toggle_event; mod fetch_xhr; mod file_entry_file_callback; mod file_system_directory_reader; -mod flex_static_position; +mod flex_geometry; mod grid_item_box_generation; mod grid_item_paint_order; mod grid_resolved_track_values; diff --git a/moli-renderer-v8/tests/fixtures/flex-baseline-flows.html b/moli-renderer-v8/tests/fixtures/flex-baseline-flows.html new file mode 100644 index 0000000000..6f805f057d --- /dev/null +++ b/moli-renderer-v8/tests/fixtures/flex-baseline-flows.html @@ -0,0 +1,134 @@ + + +Flex baseline synthesis across logical flows + + + +