From 36be2a3bba786f938d5f8f9cb9e5ae60cb08fb9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Standa=20Luke=C5=A1?= Date: Fri, 20 Sep 2024 12:05:53 +0200 Subject: [PATCH] capabilities: fix Get of inherited property Seems that we forgot to use the getValue expression which was correctly created (apart from the negated nullable condition) --- ...DotvvmCapabilityProperty.CodeGeneration.cs | 8 +++---- .../DotvvmCapabilityProperty.Helpers.cs | 2 ++ src/Tests/Runtime/CapabilityPropertyTests.cs | 22 +++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.CodeGeneration.cs b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.CodeGeneration.cs index 41e03091c4..a0b7500aad 100644 --- a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.CodeGeneration.cs +++ b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.CodeGeneration.cs @@ -192,19 +192,17 @@ public static (LambdaExpression getter, LambdaExpression setter) CreatePropertyA if (canUseDirectAccess && unwrappedType.IsValueType) { getValue = Call(typeof(Helpers), nameof(Helpers.GetStructValueDirect), new Type[] { unwrappedType }, currentControlParameter, Constant(property)); - if (type.IsNullable()) + if (!type.IsNullable()) getValue = Expression.Property(getValue, "Value"); } else { getValue = Call(currentControlParameter, getValueMethod, Constant(property), Constant(property.IsValueInherited)); + getValue = Convert(getValue, type); } return ( Expression.Lambda( - Expression.Convert( - Expression.Call(currentControlParameter, getValueMethod, Expression.Constant(property), Expression.Constant(false)), - type - ), + getValue, currentControlParameter ), Expression.Lambda( diff --git a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs index 61985c9fa3..ff6f5e2ad8 100644 --- a/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs +++ b/src/Framework/Framework/Binding/DotvvmCapabilityProperty.Helpers.cs @@ -101,6 +101,8 @@ public static void SetValueOrBindingSlow(DotvvmBindableObject c, DotvvmProper public static T? GetStructValueDirect(DotvvmBindableObject c, DotvvmProperty p) where T: struct { + // T being a struct allows us to invert the rather expensive `is IBinding` typecheck in EvalPropertyValue + // to a simpler is T check, as T is a single type checkable with a simple comparison if (c.properties.TryGet(p, out var x)) { if (x is null) diff --git a/src/Tests/Runtime/CapabilityPropertyTests.cs b/src/Tests/Runtime/CapabilityPropertyTests.cs index 801ae39389..eac2acee2a 100644 --- a/src/Tests/Runtime/CapabilityPropertyTests.cs +++ b/src/Tests/Runtime/CapabilityPropertyTests.cs @@ -214,6 +214,28 @@ public void BitMoreComplexCapability_WeirdProperties_GetterAndSetter() Assert.AreEqual(32, controlF2.GetValue("Nullable")); } + [TestMethod] + public void BitMoreComplexCapability_InheritedProperties() + { + var control1 = new TestControlInheritedProps(); + var control2 = new TestControlInheritedProps(); + control1.Children.Add(control2); + + control1.NotNullable = 1; + control1.Nullable = 2; + + Assert.AreEqual(1, control2.NotNullable); + Assert.AreEqual(2, control2.Nullable); + + Assert.AreEqual(1, control1.GetCapability().NotNullable); + Assert.AreEqual(2, control1.GetCapability().Nullable); + Assert.AreEqual(1, control2.GetCapability().NotNullable); + Assert.AreEqual(2, control2.GetCapability().Nullable); + + control2.SetCapability(new BitMoreComplexCapability { NotNullable = 3, Nullable = null }); + Assert.AreEqual(3, control2.NotNullable); + Assert.AreEqual(null, control2.Nullable); + } [DataTestMethod] [DataRow(typeof(TestControl6))]