From 210e9b89c7b6440c8c4a305def8a1d903cc7be18 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sat, 31 Jan 2026 16:27:04 +0000 Subject: [PATCH 1/7] Use simple cache key equality check --- src/tree/cache.rs | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/src/tree/cache.rs b/src/tree/cache.rs index cff245d5e..44423b3d8 100644 --- a/src/tree/cache.rs +++ b/src/tree/cache.rs @@ -117,35 +117,14 @@ impl Cache { match run_mode { RunMode::PerformLayout => self .final_layout_entry - .filter(|entry| { - let cached_size = entry.content.size; - (known_dimensions.width == entry.known_dimensions.width - || known_dimensions.width == Some(cached_size.width)) - && (known_dimensions.height == entry.known_dimensions.height - || known_dimensions.height == Some(cached_size.height)) - && (known_dimensions.width.is_some() - || entry.available_space.width.is_roughly_equal(available_space.width)) - && (known_dimensions.height.is_some() - || entry.available_space.height.is_roughly_equal(available_space.height)) - }) + .filter(|entry| known_dimensions == entry.known_dimensions && available_space == entry.available_space) .map(|e| e.content), RunMode::ComputeSize => { - for entry in self.measure_entries.iter().flatten() { - let cached_size = entry.content; - - if (known_dimensions.width == entry.known_dimensions.width - || known_dimensions.width == Some(cached_size.width)) - && (known_dimensions.height == entry.known_dimensions.height - || known_dimensions.height == Some(cached_size.height)) - && (known_dimensions.width.is_some() - || entry.available_space.width.is_roughly_equal(available_space.width)) - && (known_dimensions.height.is_some() - || entry.available_space.height.is_roughly_equal(available_space.height)) - { - return Some(LayoutOutput::from_outer_size(cached_size)); - } + let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); + let entry = &self.measure_entries[cache_slot]?; + if known_dimensions == entry.known_dimensions && available_space == entry.available_space { + return Some(LayoutOutput::from_outer_size(entry.content)); } - None } RunMode::PerformHiddenLayout => None, From f52c2047d5c29cfda74b30b9210457b585a7d914 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sat, 31 Jan 2026 16:39:06 +0000 Subject: [PATCH 2/7] Remove is_roughly_equal and sys::abs functions Signed-off-by: Nico Burns --- src/style/available_space.rs | 13 ------------- src/util/sys.rs | 26 -------------------------- 2 files changed, 39 deletions(-) diff --git a/src/style/available_space.rs b/src/style/available_space.rs index 844037e0a..29e8c7c6b 100644 --- a/src/style/available_space.rs +++ b/src/style/available_space.rs @@ -1,7 +1,6 @@ //! Style type for representing available space as a sizing constraint use crate::{ prelude::{FromLength, TaffyMaxContent, TaffyMinContent, TaffyZero}, - sys::abs, Size, }; @@ -103,18 +102,6 @@ impl AvailableSpace { AvailableSpace::Definite(available_space) => available_space - used_space, } } - - /// Compare equality with another AvailableSpace, treating definite values - /// that are within f32::EPSILON of each other as equal - pub fn is_roughly_equal(self, other: AvailableSpace) -> bool { - use AvailableSpace::*; - match (self, other) { - (Definite(a), Definite(b)) => abs(a - b) < f32::EPSILON, - (MinContent, MinContent) => true, - (MaxContent, MaxContent) => true, - _ => false, - } - } } impl From for AvailableSpace { diff --git a/src/util/sys.rs b/src/util/sys.rs index f665190a8..0cbe99925 100644 --- a/src/util/sys.rs +++ b/src/util/sys.rs @@ -74,13 +74,6 @@ mod std { value.floor() } - /// Computes the absolute value - #[must_use] - #[inline(always)] - pub(crate) fn abs(value: f32) -> f32 { - value.abs() - } - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -150,9 +143,6 @@ mod alloc { /// Rounds down to the nearest whole number pub(crate) use super::polyfill::floor; - /// Computes the absolute value - pub(crate) use super::polyfill::abs; - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -211,9 +201,6 @@ mod core { /// Rounds to the nearest whole number pub(crate) use super::polyfill::round; - /// Computes the absolute value - pub(crate) use super::polyfill::abs; - /// Returns the largest of two f32 values #[inline(always)] pub(crate) fn f32_max(a: f32, b: f32) -> f32 { @@ -285,17 +272,4 @@ mod polyfill { value - f } } - - /// Computes the absolute value - #[must_use] - #[inline(always)] - pub(crate) fn abs(value: f32) -> f32 { - if value.is_sign_positive() { - return value; - } else if value.is_sign_negative() { - return -value; - } else { - f32::NAN - } - } } From d1d04363952ab83201ff0dcb59103fdda6c90610 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sat, 31 Jan 2026 17:33:18 +0000 Subject: [PATCH 3/7] Update measure count tests Signed-off-by: Nico Burns --- tests/caching.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/caching.rs b/tests/caching.rs index c93423982..b14f7e6ae 100644 --- a/tests/caching.rs +++ b/tests/caching.rs @@ -18,7 +18,7 @@ mod caching { taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, test_measure_function).unwrap(); - assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 4); + assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 7); } #[test] @@ -35,6 +35,6 @@ mod caching { } taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, test_measure_function).unwrap(); - assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 4); + assert_eq!(taffy.get_node_context_mut(leaf).unwrap().count, 7); } } From ae6af6f9addb3643846227550c899bd4ee53274c Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 1 Feb 2026 01:23:26 +0000 Subject: [PATCH 4/7] Add parent_size to cache key Signed-off-by: Nico Burns --- examples/custom_tree_owned_partial.rs | 12 ++++++++++-- examples/custom_tree_owned_unsafe.rs | 12 ++++++++++-- examples/custom_tree_vec.rs | 12 ++++++++++-- src/compute/mod.rs | 6 +++--- src/tree/cache.rs | 19 +++++++++++++++---- src/tree/taffy_tree.rs | 18 ++++++++++++++---- src/tree/traits.rs | 2 ++ 7 files changed, 64 insertions(+), 17 deletions(-) diff --git a/examples/custom_tree_owned_partial.rs b/examples/custom_tree_owned_partial.rs index e69b26eb5..0d747adb6 100644 --- a/examples/custom_tree_owned_partial.rs +++ b/examples/custom_tree_owned_partial.rs @@ -192,9 +192,10 @@ impl CacheTree for Node { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode) } fn cache_store( @@ -202,10 +203,17 @@ impl CacheTree for Node { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, layout_output: taffy::LayoutOutput, ) { - self.node_from_id_mut(node_id).cache.store(known_dimensions, available_space, run_mode, layout_output) + self.node_from_id_mut(node_id).cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/examples/custom_tree_owned_unsafe.rs b/examples/custom_tree_owned_unsafe.rs index d0138ba95..579f59bef 100644 --- a/examples/custom_tree_owned_unsafe.rs +++ b/examples/custom_tree_owned_unsafe.rs @@ -190,9 +190,10 @@ impl CacheTree for StatelessLayoutTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, ) -> Option { - unsafe { node_from_id(node_id) }.cache.get(known_dimensions, available_space, run_mode) + unsafe { node_from_id(node_id) }.cache.get(known_dimensions, available_space, parent_size, run_mode) } fn cache_store( @@ -200,10 +201,17 @@ impl CacheTree for StatelessLayoutTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, layout_output: taffy::LayoutOutput, ) { - unsafe { node_from_id_mut(node_id) }.cache.store(known_dimensions, available_space, run_mode, layout_output) + unsafe { node_from_id_mut(node_id) }.cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/examples/custom_tree_vec.rs b/examples/custom_tree_vec.rs index 5659bd174..ea2d128df 100644 --- a/examples/custom_tree_vec.rs +++ b/examples/custom_tree_vec.rs @@ -198,9 +198,10 @@ impl CacheTree for Tree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode) } fn cache_store( @@ -208,10 +209,17 @@ impl CacheTree for Tree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: taffy::RunMode, layout_output: taffy::LayoutOutput, ) { - self.node_from_id_mut(node_id).cache.store(known_dimensions, available_space, run_mode, layout_output) + self.node_from_id_mut(node_id).cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/src/compute/mod.rs b/src/compute/mod.rs index 9a13a2ee5..ec8a7e070 100644 --- a/src/compute/mod.rs +++ b/src/compute/mod.rs @@ -174,10 +174,10 @@ where ComputeFunction: FnOnce(&mut Tree, NodeId, LayoutInput) -> LayoutOutput, { debug_push_node!(node); - let LayoutInput { known_dimensions, available_space, run_mode, .. } = inputs; + let LayoutInput { known_dimensions, available_space, run_mode, parent_size, .. } = inputs; // First we check if we have a cached result for the given input - let cache_entry = tree.cache_get(node, known_dimensions, available_space, run_mode); + let cache_entry = tree.cache_get(node, known_dimensions, available_space, parent_size, run_mode); if let Some(cached_size_and_baselines) = cache_entry { debug_log_node!(known_dimensions, inputs.parent_size, available_space, run_mode, inputs.sizing_mode); debug_log!("RESULT (CACHED)", dbg:cached_size_and_baselines.size); @@ -190,7 +190,7 @@ where let computed_size_and_baselines = compute_uncached(tree, node, inputs); // Cache result - tree.cache_store(node, known_dimensions, available_space, run_mode, computed_size_and_baselines); + tree.cache_store(node, known_dimensions, available_space, parent_size, run_mode, computed_size_and_baselines); debug_log!("RESULT", dbg:computed_size_and_baselines.size); debug_pop_node!(); diff --git a/src/tree/cache.rs b/src/tree/cache.rs index 44423b3d8..28ad282da 100644 --- a/src/tree/cache.rs +++ b/src/tree/cache.rs @@ -14,6 +14,8 @@ pub(crate) struct CacheEntry { known_dimensions: Size>, /// The initial cached size of the parent's node available_space: Size, + /// The initial cached size of the parent's node + parent_size: Size>, /// The cached size and baselines of the item content: T, } @@ -112,17 +114,24 @@ impl Cache { &self, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, ) -> Option { match run_mode { RunMode::PerformLayout => self .final_layout_entry - .filter(|entry| known_dimensions == entry.known_dimensions && available_space == entry.available_space) + .filter(|entry| { + known_dimensions == entry.known_dimensions + && available_space == entry.available_space + && parent_size == entry.parent_size + }) .map(|e| e.content), RunMode::ComputeSize => { let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); let entry = &self.measure_entries[cache_slot]?; - if known_dimensions == entry.known_dimensions && available_space == entry.available_space { + if known_dimensions == entry.known_dimensions && available_space == entry.available_space + // && parent_size == entry.parent_size + { return Some(LayoutOutput::from_outer_size(entry.content)); } None @@ -136,19 +145,21 @@ impl Cache { &mut self, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, layout_output: LayoutOutput, ) { match run_mode { RunMode::PerformLayout => { self.is_empty = false; - self.final_layout_entry = Some(CacheEntry { known_dimensions, available_space, content: layout_output }) + self.final_layout_entry = + Some(CacheEntry { known_dimensions, available_space, parent_size, content: layout_output }) } RunMode::ComputeSize => { self.is_empty = false; let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); self.measure_entries[cache_slot] = - Some(CacheEntry { known_dimensions, available_space, content: layout_output.size }); + Some(CacheEntry { known_dimensions, available_space, parent_size, content: layout_output.size }); } RunMode::PerformHiddenLayout => {} } diff --git a/src/tree/taffy_tree.rs b/src/tree/taffy_tree.rs index 785e97fa5..c4f8e66f1 100644 --- a/src/tree/taffy_tree.rs +++ b/src/tree/taffy_tree.rs @@ -215,9 +215,10 @@ impl CacheTree for TaffyTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, ) -> Option { - self.nodes[node_id.into()].cache.get(known_dimensions, available_space, run_mode) + self.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode) } fn cache_store( @@ -225,10 +226,11 @@ impl CacheTree for TaffyTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, layout_output: LayoutOutput, ) { - self.nodes[node_id.into()].cache.store(known_dimensions, available_space, run_mode, layout_output) + self.nodes[node_id.into()].cache.store(known_dimensions, available_space, parent_size, run_mode, layout_output) } fn cache_clear(&mut self, node_id: NodeId) { @@ -432,9 +434,10 @@ where node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, ) -> Option { - self.taffy.nodes[node_id.into()].cache.get(known_dimensions, available_space, run_mode) + self.taffy.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode) } fn cache_store( @@ -442,10 +445,17 @@ where node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, layout_output: LayoutOutput, ) { - self.taffy.nodes[node_id.into()].cache.store(known_dimensions, available_space, run_mode, layout_output) + self.taffy.nodes[node_id.into()].cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { diff --git a/src/tree/traits.rs b/src/tree/traits.rs index 194110ef5..48b31cad9 100644 --- a/src/tree/traits.rs +++ b/src/tree/traits.rs @@ -210,6 +210,7 @@ pub trait CacheTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, ) -> Option; @@ -219,6 +220,7 @@ pub trait CacheTree { node_id: NodeId, known_dimensions: Size>, available_space: Size, + parent_size: Size>, run_mode: RunMode, layout_output: LayoutOutput, ); From a932f6d96140152a388214d9e797bf54b940b5b6 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 1 Feb 2026 03:35:30 +0000 Subject: [PATCH 5/7] Add sizing_mode to cache key Signed-off-by: Nico Burns --- examples/custom_tree_owned_partial.rs | 7 ++++-- examples/custom_tree_owned_unsafe.rs | 13 +++++++++-- examples/custom_tree_vec.rs | 7 ++++-- src/compute/mod.rs | 14 +++++++++--- src/tree/cache.rs | 31 +++++++++++++++++++++------ src/tree/taffy_tree.rs | 26 +++++++++++++++++++--- src/tree/traits.rs | 2 ++ 7 files changed, 82 insertions(+), 18 deletions(-) diff --git a/examples/custom_tree_owned_partial.rs b/examples/custom_tree_owned_partial.rs index 0d747adb6..e4084e4ad 100644 --- a/examples/custom_tree_owned_partial.rs +++ b/examples/custom_tree_owned_partial.rs @@ -13,7 +13,7 @@ use common::image::{image_measure_function, ImageContext}; use common::text::{text_measure_function, FontMetrics, TextContext, WritingMode, LOREM_IPSUM}; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, Cache, CacheTree, Layout, Style, + prelude::*, Cache, CacheTree, Layout, SizingMode, Style, }; #[derive(Debug, Copy, Clone)] @@ -194,8 +194,9 @@ impl CacheTree for Node { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -205,6 +206,7 @@ impl CacheTree for Node { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { self.node_from_id_mut(node_id).cache.store( @@ -212,6 +214,7 @@ impl CacheTree for Node { available_space, parent_size, run_mode, + sizing_mode, layout_output, ) } diff --git a/examples/custom_tree_owned_unsafe.rs b/examples/custom_tree_owned_unsafe.rs index 579f59bef..ba0e20318 100644 --- a/examples/custom_tree_owned_unsafe.rs +++ b/examples/custom_tree_owned_unsafe.rs @@ -9,7 +9,7 @@ use taffy::tree::Cache; use taffy::util::print_tree; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, round_layout, CacheTree, + prelude::*, round_layout, CacheTree, SizingMode, }; #[derive(Debug, Copy, Clone)] @@ -192,8 +192,15 @@ impl CacheTree for StatelessLayoutTree { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - unsafe { node_from_id(node_id) }.cache.get(known_dimensions, available_space, parent_size, run_mode) + unsafe { node_from_id(node_id) }.cache.get( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + ) } fn cache_store( @@ -203,6 +210,7 @@ impl CacheTree for StatelessLayoutTree { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { unsafe { node_from_id_mut(node_id) }.cache.store( @@ -210,6 +218,7 @@ impl CacheTree for StatelessLayoutTree { available_space, parent_size, run_mode, + sizing_mode, layout_output, ) } diff --git a/examples/custom_tree_vec.rs b/examples/custom_tree_vec.rs index ea2d128df..ccb2cf8c4 100644 --- a/examples/custom_tree_vec.rs +++ b/examples/custom_tree_vec.rs @@ -7,7 +7,7 @@ use common::text::{text_measure_function, FontMetrics, TextContext, WritingMode, use taffy::util::print_tree; use taffy::{ compute_cached_layout, compute_flexbox_layout, compute_grid_layout, compute_leaf_layout, compute_root_layout, - prelude::*, round_layout, Cache, CacheTree, + prelude::*, round_layout, Cache, CacheTree, SizingMode, }; #[derive(Debug, Copy, Clone)] @@ -200,8 +200,9 @@ impl CacheTree for Tree { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, ) -> Option { - self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode) + self.node_from_id(node_id).cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -211,6 +212,7 @@ impl CacheTree for Tree { available_space: Size, parent_size: Size>, run_mode: taffy::RunMode, + sizing_mode: SizingMode, layout_output: taffy::LayoutOutput, ) { self.node_from_id_mut(node_id).cache.store( @@ -218,6 +220,7 @@ impl CacheTree for Tree { available_space, parent_size, run_mode, + sizing_mode, layout_output, ) } diff --git a/src/compute/mod.rs b/src/compute/mod.rs index ec8a7e070..b0455d236 100644 --- a/src/compute/mod.rs +++ b/src/compute/mod.rs @@ -174,10 +174,10 @@ where ComputeFunction: FnOnce(&mut Tree, NodeId, LayoutInput) -> LayoutOutput, { debug_push_node!(node); - let LayoutInput { known_dimensions, available_space, run_mode, parent_size, .. } = inputs; + let LayoutInput { known_dimensions, available_space, run_mode, parent_size, sizing_mode, .. } = inputs; // First we check if we have a cached result for the given input - let cache_entry = tree.cache_get(node, known_dimensions, available_space, parent_size, run_mode); + let cache_entry = tree.cache_get(node, known_dimensions, available_space, parent_size, run_mode, sizing_mode); if let Some(cached_size_and_baselines) = cache_entry { debug_log_node!(known_dimensions, inputs.parent_size, available_space, run_mode, inputs.sizing_mode); debug_log!("RESULT (CACHED)", dbg:cached_size_and_baselines.size); @@ -190,7 +190,15 @@ where let computed_size_and_baselines = compute_uncached(tree, node, inputs); // Cache result - tree.cache_store(node, known_dimensions, available_space, parent_size, run_mode, computed_size_and_baselines); + tree.cache_store( + node, + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + computed_size_and_baselines, + ); debug_log!("RESULT", dbg:computed_size_and_baselines.size); debug_pop_node!(); diff --git a/src/tree/cache.rs b/src/tree/cache.rs index 28ad282da..2b866d7a4 100644 --- a/src/tree/cache.rs +++ b/src/tree/cache.rs @@ -3,6 +3,8 @@ use crate::geometry::Size; use crate::style::AvailableSpace; use crate::tree::{LayoutOutput, RunMode}; +use super::SizingMode; + /// The number of cache entries for each node in the tree const CACHE_SIZE: usize = 9; @@ -16,6 +18,8 @@ pub(crate) struct CacheEntry { available_space: Size, /// The initial cached size of the parent's node parent_size: Size>, + /// The sizing mode + sizing_mode: SizingMode, /// The cached size and baselines of the item content: T, } @@ -116,6 +120,7 @@ impl Cache { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { match run_mode { RunMode::PerformLayout => self @@ -124,13 +129,16 @@ impl Cache { known_dimensions == entry.known_dimensions && available_space == entry.available_space && parent_size == entry.parent_size + && sizing_mode == entry.sizing_mode }) .map(|e| e.content), RunMode::ComputeSize => { let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); let entry = &self.measure_entries[cache_slot]?; - if known_dimensions == entry.known_dimensions && available_space == entry.available_space - // && parent_size == entry.parent_size + if known_dimensions == entry.known_dimensions + && available_space == entry.available_space + // && parent_size == entry.parent_size + && sizing_mode == entry.sizing_mode { return Some(LayoutOutput::from_outer_size(entry.content)); } @@ -147,19 +155,30 @@ impl Cache { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { match run_mode { RunMode::PerformLayout => { self.is_empty = false; - self.final_layout_entry = - Some(CacheEntry { known_dimensions, available_space, parent_size, content: layout_output }) + self.final_layout_entry = Some(CacheEntry { + known_dimensions, + available_space, + parent_size, + sizing_mode, + content: layout_output, + }) } RunMode::ComputeSize => { self.is_empty = false; let cache_slot = Self::compute_cache_slot(known_dimensions, available_space); - self.measure_entries[cache_slot] = - Some(CacheEntry { known_dimensions, available_space, parent_size, content: layout_output.size }); + self.measure_entries[cache_slot] = Some(CacheEntry { + known_dimensions, + available_space, + parent_size, + sizing_mode, + content: layout_output.size, + }); } RunMode::PerformHiddenLayout => {} } diff --git a/src/tree/taffy_tree.rs b/src/tree/taffy_tree.rs index c4f8e66f1..b2fd2b78d 100644 --- a/src/tree/taffy_tree.rs +++ b/src/tree/taffy_tree.rs @@ -34,6 +34,8 @@ use crate::compute::grid::DetailedGridInfo; #[cfg(feature = "detailed_layout_info")] use crate::tree::layout::DetailedLayoutInfo; +use super::SizingMode; + /// The error Taffy generates on invalid operations pub type TaffyResult = Result; @@ -217,8 +219,9 @@ impl CacheTree for TaffyTree { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { - self.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode) + self.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode, sizing_mode) } fn cache_store( @@ -228,9 +231,17 @@ impl CacheTree for TaffyTree { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { - self.nodes[node_id.into()].cache.store(known_dimensions, available_space, parent_size, run_mode, layout_output) + self.nodes[node_id.into()].cache.store( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + layout_output, + ) } fn cache_clear(&mut self, node_id: NodeId) { @@ -436,8 +447,15 @@ where available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option { - self.taffy.nodes[node_id.into()].cache.get(known_dimensions, available_space, parent_size, run_mode) + self.taffy.nodes[node_id.into()].cache.get( + known_dimensions, + available_space, + parent_size, + run_mode, + sizing_mode, + ) } fn cache_store( @@ -447,6 +465,7 @@ where available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ) { self.taffy.nodes[node_id.into()].cache.store( @@ -454,6 +473,7 @@ where available_space, parent_size, run_mode, + sizing_mode, layout_output, ) } diff --git a/src/tree/traits.rs b/src/tree/traits.rs index 48b31cad9..0710f9e89 100644 --- a/src/tree/traits.rs +++ b/src/tree/traits.rs @@ -212,6 +212,7 @@ pub trait CacheTree { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, ) -> Option; /// Store a computed size in the cache @@ -222,6 +223,7 @@ pub trait CacheTree { available_space: Size, parent_size: Size>, run_mode: RunMode, + sizing_mode: SizingMode, layout_output: LayoutOutput, ); From 6156dfddc7613b91170cc4448112ab0d8e434154 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 1 Feb 2026 03:41:15 +0000 Subject: [PATCH 6/7] Consistently use ContentSize in Flexbox --- src/compute/flexbox.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs index 2cf25ae4b..df1292b8a 100644 --- a/src/compute/flexbox.rs +++ b/src/compute/flexbox.rs @@ -1060,7 +1060,8 @@ fn determine_container_main_size( child_known_dimensions, constants.node_inner_size, child_available_space, - SizingMode::InherentSize, + // FIXME: apply "InherentSize" differences manually + SizingMode::ContentSize, dir.main_axis(), Line::FALSE, ) + item.margin.main_axis_sum(constants.dir); From 725027a7599bea3ef27614c64ede9f45ba95724e Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Sun, 1 Feb 2026 12:52:05 +0000 Subject: [PATCH 7/7] Switch back to inherent size --- src/compute/flexbox.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs index df1292b8a..f46a26c13 100644 --- a/src/compute/flexbox.rs +++ b/src/compute/flexbox.rs @@ -1061,7 +1061,7 @@ fn determine_container_main_size( constants.node_inner_size, child_available_space, // FIXME: apply "InherentSize" differences manually - SizingMode::ContentSize, + SizingMode::InherentSize, dir.main_axis(), Line::FALSE, ) + item.margin.main_axis_sum(constants.dir);