diff --git a/sixtyfps_compiler/expression_tree.rs b/sixtyfps_compiler/expression_tree.rs index a2e2f4d41..0f5d712b3 100644 --- a/sixtyfps_compiler/expression_tree.rs +++ b/sixtyfps_compiler/expression_tree.rs @@ -1120,37 +1120,42 @@ impl BindingExpression { /// Merge the other into this one. Normally, &self is kept intact (has priority), unless two ways binding are /// involved then they need to be merged. /// Also the animation is taken if the other don't have one - pub fn merge_with(&mut self, other: &Self) { + /// + /// Returns true if the other expression was taken + pub fn merge_with(&mut self, other: &Self) -> bool { fn maybe_merge_two_ways( binding: &mut Expression, priority: &mut i32, original: &BindingExpression, - ) { + ) -> bool { match (binding, &original.expression) { (Expression::TwoWayBinding(_, Some(ref mut x)), _) => { - maybe_merge_two_ways(&mut *x, priority, original); + maybe_merge_two_ways(&mut *x, priority, original) } (Expression::TwoWayBinding(_, x), o) => { - *priority = original.priority + 1; + *priority = original.priority; *x = Some(Box::new(o.clone())); + true } (ref mut x, Expression::TwoWayBinding(nr, _)) => { let n = Expression::TwoWayBinding(nr.clone(), Some(Box::new(std::mem::take(*x)))); - **x = n + **x = n; + false } - _ => *priority += 1, + _ => false, } } - if matches!(self.expression, Expression::Invalid) { - self.priority = other.priority + 1; - self.expression = other.expression.clone(); - } else { - maybe_merge_two_ways(&mut self.expression, &mut self.priority, other); - } if self.animation.is_none() { self.animation = other.animation.clone(); } + if matches!(self.expression, Expression::Invalid) { + self.priority = other.priority; + self.expression = other.expression.clone(); + true + } else { + maybe_merge_two_ways(&mut self.expression, &mut self.priority, other) + } } } diff --git a/sixtyfps_compiler/passes/inlining.rs b/sixtyfps_compiler/passes/inlining.rs index bf86b3cc2..758a60a3b 100644 --- a/sixtyfps_compiler/passes/inlining.rs +++ b/sixtyfps_compiler/passes/inlining.rs @@ -114,7 +114,9 @@ fn inline_element( entry.insert(val.clone()).priority += 1; } std::collections::btree_map::Entry::Occupied(mut entry) => { - entry.get_mut().merge_with(val); + if entry.get_mut().merge_with(val) { + entry.get_mut().priority += 1; + } } } } diff --git a/tests/cases/bindings/two_way_priority.60 b/tests/cases/bindings/two_way_priority.60 index fa534851b..92e1c2d84 100644 --- a/tests/cases/bindings/two_way_priority.60 +++ b/tests/cases/bindings/two_way_priority.60 @@ -8,6 +8,13 @@ Please contact info@sixtyfps.io for more information. LICENSE END */ +export OpacityTwoWay := Rectangle { + property sub_opacity <=> rect.opacity; + rect := Rectangle { + opacity: 0.75; + } +} + export Compo := Rectangle { property foo <=> self.bar; property bar: 120; @@ -18,8 +25,16 @@ TestCase := Window { compo1 := Compo {} compo2 := Compo { foo: compo1.foo + 10; } + Rectangle { + otw := OpacityTwoWay { sub_opacity: 0.5; } + otw2 := OpacityTwoWay { sub_opacity: 0.5; } + } + property compo0_foo: compo0.foo; property compo2_foo: compo2.foo; + property otw_opacity <=> otw.sub_opacity; + + property test: compo0_foo == 140 && compo2_foo == 130 && otw_opacity == 0.5 && otw2.sub_opacity == 0.5; } /* @@ -28,6 +43,7 @@ TestCase := Window { let instance = TestCase::new(); assert_eq!(instance.get_compo0_foo(), 140); assert_eq!(instance.get_compo2_foo(), 130); +assert_eq!(instance.get_otw_opacity(), 0.5); ``` @@ -37,6 +53,7 @@ auto handle = TestCase::create(); const TestCase &instance = *handle; assert_eq(instance.get_compo0_foo(), 140); assert_eq(instance.get_compo2_foo(), 130); +assert_eq(instance.get_otw_opacity(), 0.5); ``` @@ -44,6 +61,7 @@ assert_eq(instance.get_compo2_foo(), 130); let instance = new sixtyfps.TestCase({}); assert.equal(instance.compo0_foo, 140); assert.equal(instance.compo2_foo, 130); +assert.equal(instance.otw_opacity, 0.5); ``` */