diff --git a/internal/compiler/passes/lower_states.rs b/internal/compiler/passes/lower_states.rs index f7a91b335..a9b648bf5 100644 --- a/internal/compiler/passes/lower_states.rs +++ b/internal/compiler/passes/lower_states.rs @@ -204,27 +204,28 @@ enum ExpressionForProperty { fn expression_for_property(element: &ElementRc, name: &str) -> ExpressionForProperty { let mut element_it = Some(element.clone()); let mut in_base = false; - while let Some(element) = element_it { - if let Some(e) = element.borrow().bindings.get(name) { + while let Some(elem) = element_it { + if let Some(e) = elem.borrow().bindings.get(name) { let e = e.borrow(); if !e.two_way_bindings.is_empty() { return ExpressionForProperty::TwoWayBinding; } - if !matches!(e.expression, Expression::Invalid) { + let mut expr = e.expression.clone(); + if !matches!(expr, Expression::Invalid) { if in_base { // Check that the expresison is valid in the new scope let mut has_invalid = false; - e.expression.visit_recursive(&mut |ex| match ex { + expr.visit_recursive_mut(&mut |ex| match ex { Expression::CallbackReference(nr, _) | Expression::PropertyReference(nr) | Expression::FunctionReference(nr, _) => { let e = nr.element(); - if !Rc::ptr_eq(&e, &element) - && Weak::ptr_eq( - &e.borrow().enclosing_component, - &element.borrow().enclosing_component, - ) - { + if Rc::ptr_eq(&e, &elem) { + *nr = NamedReference::new(element, nr.name()); + } else if Weak::ptr_eq( + &e.borrow().enclosing_component, + &elem.borrow().enclosing_component, + ) { has_invalid = true; } } @@ -235,10 +236,10 @@ fn expression_for_property(element: &ElementRc, name: &str) -> ExpressionForProp } } - return ExpressionForProperty::Expression(e.expression.clone()); + return ExpressionForProperty::Expression(expr); } } - element_it = if let ElementType::Component(base) = &element.borrow().base_type { + element_it = if let ElementType::Component(base) = &elem.borrow().base_type { in_base = true; Some(base.root_element.clone()) } else { diff --git a/tests/cases/properties/issue5038_state_in_base.slint b/tests/cases/properties/issue5038_state_in_base.slint new file mode 100644 index 000000000..da0113c4a --- /dev/null +++ b/tests/cases/properties/issue5038_state_in_base.slint @@ -0,0 +1,70 @@ +// Copyright © SixtyFPS GmbH +// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial + +export global Glob { + in-out property cond2; +} + +component Base inherits Rectangle { + in property value; + +} + +export component R1 inherits Base { + + t := TouchArea { } + + ti := TextInput { text: Glob.cond2 ? "a" : "b"; } + + + states [ + xxx when ti.text == "a" : { + value: 1; + } + hover when t.has-hover: { + background: white; + value: 2; + } + ] +} + +export component R2 inherits R1 { } + +export component TestCase inherits Window { + in property cond1; + r2 := R2 { + states [ + s1 when cond1: { + background: white; + value: 3; + } + ] + } + + out property value: r2.value; +} + + +/* +```cpp +auto handle = TestCase::create(); +const TestCase &instance = *handle; +assert_eq(instance.get_value(), 0); +instance.global().set_cond2(true); +assert_eq(instance.get_value(), 1); +instance.set_cond1(true); +assert_eq(instance.get_value(), 3); +``` + + +```rust +let instance = TestCase::new().unwrap(); +assert_eq!(instance.get_value(), 0); +instance.global::>().set_cond2(true); +assert_eq!(instance.get_value(), 1); +instance.set_cond1(true); +assert_eq!(instance.get_value(), 3); +``` + + +*/