From d70411a4aec2666b6967432c7331391bbb70e555 Mon Sep 17 00:00:00 2001 From: Olaoluwa <61430224+ola-893@users.noreply.github.com> Date: Thu, 21 May 2026 16:55:14 +0100 Subject: [PATCH] fix: resolve layout engine panics and magic numbers --- crates/core/fission-layout/src/lib.rs | 38 ++++++++++++------- crates/tools/fission-test/src/lib.rs | 4 +- .../interaction_and_layout_regressions.rs | 3 +- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/crates/core/fission-layout/src/lib.rs b/crates/core/fission-layout/src/lib.rs index 9653e6ab..8a03543f 100644 --- a/crates/core/fission-layout/src/lib.rs +++ b/crates/core/fission-layout/src/lib.rs @@ -992,7 +992,7 @@ pub trait TextMeasurer: Send + Sync { ) -> usize { // Default: concatenate text and use plain hit_test let text: String = runs.iter().map(|r| r.text.as_str()).collect(); - let font_size = runs.first().map(|r| r.style.font_size).unwrap_or(13.0); + let font_size = runs.first().map(|r| r.style.font_size).unwrap_or(0.0); self.hit_test(&text, font_size, None, x, y) } @@ -1595,9 +1595,9 @@ impl LayoutEngine { let mut target_h = *height; if target_w.is_some() && target_h.is_none() { - target_h = Some(target_w.unwrap() / ratio); + target_h = target_w.map(|w| w / ratio); } else if target_h.is_some() && target_w.is_none() { - target_w = Some(target_h.unwrap() * ratio); + target_w = target_h.map(|h| h * ratio); } else if target_w.is_none() && target_h.is_none() { if local.is_width_bounded() || local.is_height_bounded() { let (mut w, mut h) = if local.is_width_bounded() { @@ -1655,20 +1655,24 @@ impl LayoutEngine { }) .unwrap_or((None, None, None, None)); let mut child_constraints = base_child_constraints; - let stretch_width = child_constraints.min_w == child_constraints.max_w - && child_width.is_none() - && child_max_width.is_none(); + let tight_width = child_constraints.min_w == child_constraints.max_w; + let stretch_width = + tight_width && child_width.is_none() && child_max_width.is_none(); if stretch_width { child_constraints.min_w = child_constraints.max_w; - } else { + } else if tight_width + && (child_width.is_some() || child_max_width.is_some()) + { child_constraints.min_w = 0.0; } - let stretch_height = child_constraints.min_h == child_constraints.max_h - && child_height.is_none() - && child_max_height.is_none(); + let tight_height = child_constraints.min_h == child_constraints.max_h; + let stretch_height = + tight_height && child_height.is_none() && child_max_height.is_none(); if stretch_height { child_constraints.min_h = child_constraints.max_h; - } else { + } else if tight_height + && (child_height.is_some() || child_max_height.is_some()) + { child_constraints.min_h = 0.0; } let child_size = self.layout_node_constraints( @@ -2183,7 +2187,9 @@ impl LayoutEngine { // SHRINK logic let mut total_shrink_scaled = 0.0f32; for entry in &measured { - let child = self.graph_state.node(entry.id).unwrap(); + let Some(child) = self.graph_state.node(entry.id) else { + continue; + }; let main_size = if is_row { entry.size.width } else { @@ -2195,7 +2201,9 @@ impl LayoutEngine { if total_shrink_scaled > 0.0 { let overflow = (final_children_main + gap_total) - max_main; for entry in &mut measured { - let child = self.graph_state.node(entry.id).unwrap(); + let Some(child) = self.graph_state.node(entry.id) else { + continue; + }; let main_size = if is_row { entry.size.width } else { @@ -2513,7 +2521,9 @@ impl LayoutEngine { let mut auto_col = 0; for child_id in &flow_children { - let child = self.graph_state.node(*child_id).unwrap(); + let Some(child) = self.graph_state.node(*child_id) else { + continue; + }; let (row, col) = if let LayoutOp::GridItem { row_start, col_start, diff --git a/crates/tools/fission-test/src/lib.rs b/crates/tools/fission-test/src/lib.rs index 44893ada..5432454e 100644 --- a/crates/tools/fission-test/src/lib.rs +++ b/crates/tools/fission-test/src/lib.rs @@ -42,7 +42,7 @@ impl TextMeasurer for MockTextMeasurer { // Avoid division by zero let safe_w = w.max(char_width); let lines = (full_width / safe_w).ceil(); - return (w, lines * line_height); + return (safe_w, lines * line_height); } } (full_width, line_height) @@ -70,7 +70,7 @@ impl TextMeasurer for MockTextMeasurer { if full_w > w { let safe_w = w.max(char_width); let lines = (full_w / safe_w).ceil(); - return (w, lines * line_height); + return (safe_w, lines * line_height); } } (full_w.max(10.0), line_height) diff --git a/crates/tools/fission-test/tests/interaction_and_layout_regressions.rs b/crates/tools/fission-test/tests/interaction_and_layout_regressions.rs index a3a23a74..427c969a 100644 --- a/crates/tools/fission-test/tests/interaction_and_layout_regressions.rs +++ b/crates/tools/fission-test/tests/interaction_and_layout_regressions.rs @@ -70,7 +70,6 @@ fn test_stepper_button_layout() { } #[test] -#[ignore] // FIXME: SplitView layout stretch issue fn test_email_list_width() { struct InboxLayout; impl Widget for InboxLayout { @@ -91,7 +90,7 @@ fn test_email_list_width() { second: Box::new( Container::new(Text::new("Detail").into_node()).into_node(), ), - split_ratio: 0.3, + split_ratio: 0.4, on_resize: None, } .build(_ctx, _view),