From d447cd155d9a8ff8c750d97f77ab3d744cf2caf9 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Thu, 4 Nov 2021 09:46:00 +0100 Subject: [PATCH] Fix missing repeaters in item tree with chained sub-components The parent commit surfaced this issue, as we now rely on visiting all repeaters in the build_item_tree call. --- sixtyfps_compiler/generator.rs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/sixtyfps_compiler/generator.rs b/sixtyfps_compiler/generator.rs index a43fa469a..e22f31384 100644 --- a/sixtyfps_compiler/generator.rs +++ b/sixtyfps_compiler/generator.rs @@ -259,6 +259,38 @@ pub fn build_item_tree( relative_parent_index, parent_item.borrow().item_index.get().map(|x| *x as u32).unwrap_or(parent_index) ); + + // Suppose we have this: + // ``` + // Button := Rectangle { /* some repeater here*/ } + // StandardButton := Button { /* no children */ } + // App := Dialog { StandardButton { /* no children */ }} + // ``` + // The inlining pass ensures that *if* `StandardButton` had children, `Button` would be inlined, but that's not the case here. + // + // We are in the stage of visiting the Dialog's children and we'll end up visiting the Button's Rectangle because visit_item() + // on the StandardButton - a Dialog's child - follows all the way to the Rectangle as native item. We've also determine that + // StandardButton is a sub-component and we'll call visit_children() on it. Now we are here. However as `StandardButton` has no children, + // and therefore we would never recurse into `Button`'s children and thus miss the repeater. That is what this condition attempts to + // detect and chain the children visitation. + if children.is_empty() { + if let Some(nested_subcomponent) = parent_item.borrow().sub_component() { + visit_children( + state, + &nested_subcomponent.root_element.borrow().children, + &nested_subcomponent, + &nested_subcomponent.root_element, + parent_index, + relative_parent_index, + children_offset, + relative_children_offset, + repeater_count, + builder, + ); + return; + } + } + let mut offset = children_offset + children.len() as u32; let mut sub_component_states = VecDeque::new();