From c0ea5135737a0a072e9d5a8a201e33335b9962b7 Mon Sep 17 00:00:00 2001 From: Manodasan Wignarajah Date: Sun, 30 Jun 2024 16:25:43 -0700 Subject: [PATCH] Fix boxing of types (#1646) * Fix issue where unboxing of Type failed due to missing type mapping * Add ABI type also to custom type mapping to allow helper type lookup to work in collection scenarios * Fix size regression --- src/Tests/FunctionalTests/Collections/Program.cs | 9 ++++++++- src/Tests/TestComponentCSharp/Class.cpp | 15 +++++++++++++++ src/Tests/TestComponentCSharp/Class.h | 4 ++++ .../TestComponentCSharp/TestComponentCSharp.idl | 3 +++ src/Tests/UnitTest/TestComponentCSharp_Tests.cs | 14 ++++++++++++++ src/WinRT.Runtime/GuidGenerator.cs | 5 +++++ src/WinRT.Runtime/Projections.cs | 2 ++ 7 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/Tests/FunctionalTests/Collections/Program.cs b/src/Tests/FunctionalTests/Collections/Program.cs index c06150117..50c5121ea 100644 --- a/src/Tests/FunctionalTests/Collections/Program.cs +++ b/src/Tests/FunctionalTests/Collections/Program.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using test_component_derived.Nested; @@ -69,6 +70,12 @@ return 101; } +var types = Class.ListOfTypes; +if (types.Count != 2 || types[0] != typeof(Class)) +{ + return 101; +} + var cancellationDictionary = new Dictionary(); instance.BindableIterableProperty = cancellationDictionary; if (cancellationDictionary != instance.BindableIterableProperty) diff --git a/src/Tests/TestComponentCSharp/Class.cpp b/src/Tests/TestComponentCSharp/Class.cpp index 41e298251..16e7c0af3 100644 --- a/src/Tests/TestComponentCSharp/Class.cpp +++ b/src/Tests/TestComponentCSharp/Class.cpp @@ -1589,6 +1589,11 @@ namespace winrt::TestComponentCSharp::implementation return winrt::unbox_value(obj); } + Windows::UI::Xaml::Interop::TypeName Class::UnboxType(WF::IInspectable const& obj) + { + return winrt::unbox_value(obj); + } + com_array Class::UnboxInt32Array(WF::IInspectable const& obj) { return obj.as>().Value(); @@ -1633,6 +1638,16 @@ namespace winrt::TestComponentCSharp::implementation return winrt::xaml_typename(); } + WF::IInspectable Class::BoxedType() + { + return winrt::box_value(winrt::xaml_typename()); + } + + IVector Class::ListOfTypes() + { + return single_threaded_vector({ winrt::xaml_typename(), winrt::xaml_typename>() }); + } + bool Class::VerifyTypeIsInt32Type(TypeName const& type_name) { return winrt::xaml_typename() == type_name; diff --git a/src/Tests/TestComponentCSharp/Class.h b/src/Tests/TestComponentCSharp/Class.h index 65748b4f7..573d32ac2 100644 --- a/src/Tests/TestComponentCSharp/Class.h +++ b/src/Tests/TestComponentCSharp/Class.h @@ -374,6 +374,7 @@ namespace winrt::TestComponentCSharp::implementation static hstring UnboxString(IInspectable const& obj); static EnumValue UnboxEnum(IInspectable const& obj); static TestComponentCSharp::ProvideInt UnboxDelegate(IInspectable const& obj); + static Windows::UI::Xaml::Interop::TypeName UnboxType(IInspectable const& obj); static com_array UnboxInt32Array(IInspectable const& obj); static com_array UnboxBooleanArray(IInspectable const& obj); static com_array UnboxStringArray(IInspectable const& obj); @@ -384,6 +385,9 @@ namespace winrt::TestComponentCSharp::implementation static Windows::UI::Xaml::Interop::TypeName Int32Type(); static Windows::UI::Xaml::Interop::TypeName ReferenceInt32Type(); static Windows::UI::Xaml::Interop::TypeName ThisClassType(); + static Windows::Foundation::IInspectable BoxedType(); + static Windows::Foundation::Collections::IVector ListOfTypes(); + static bool VerifyTypeIsInt32Type(Windows::UI::Xaml::Interop::TypeName const& type_name); static bool VerifyTypeIsReferenceInt32Type(Windows::UI::Xaml::Interop::TypeName const& type_name); static bool VerifyTypeIsThisClassType(Windows::UI::Xaml::Interop::TypeName const& type_name); diff --git a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl index f20f560a3..eea90c305 100644 --- a/src/Tests/TestComponentCSharp/TestComponentCSharp.idl +++ b/src/Tests/TestComponentCSharp/TestComponentCSharp.idl @@ -406,6 +406,7 @@ namespace TestComponentCSharp static String UnboxString(Object obj); static ProvideInt UnboxDelegate(Object obj); static EnumValue UnboxEnum(Object obj); + static Windows.UI.Xaml.Interop.TypeName UnboxType(Object obj); static Int32[] UnboxInt32Array(Object obj); static Boolean[] UnboxBooleanArray(Object obj); static String[] UnboxStringArray(Object obj); @@ -420,6 +421,8 @@ namespace TestComponentCSharp static Windows.UI.Xaml.Interop.TypeName Int32Type { get; }; static Windows.UI.Xaml.Interop.TypeName ThisClassType { get; }; static Windows.UI.Xaml.Interop.TypeName ReferenceInt32Type { get; }; + static Object BoxedType{ get; }; + static Windows.Foundation.Collections.IVector ListOfTypes{ get; }; static Boolean VerifyTypeIsInt32Type(Windows.UI.Xaml.Interop.TypeName type); static Boolean VerifyTypeIsThisClassType(Windows.UI.Xaml.Interop.TypeName type); diff --git a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs index 7e708cdf0..6732e4277 100644 --- a/src/Tests/UnitTest/TestComponentCSharp_Tests.cs +++ b/src/Tests/UnitTest/TestComponentCSharp_Tests.cs @@ -2574,6 +2574,11 @@ public void TestValueBoxing() EnumValue enumValue = EnumValue.Two; Assert.Equal(enumValue, Class.UnboxEnum(enumValue)); + + var type = typeof(EnumValue); + Assert.Equal(type, Class.UnboxType(type)); + + Assert.Equal(typeof(Class), Class.BoxedType); } [Fact] @@ -2599,6 +2604,15 @@ public void TestArrayUnboxing() Assert.Equal(i, (IEnumerable)obj); } + [Fact] + public void TestListOfTypes() + { + var types = Class.ListOfTypes; + Assert.Equal(2, types.Count); + Assert.Equal(typeof(Class), types[0]); + Assert.Equal(typeof(int?), types[1]); + } + [Fact] public void PrimitiveTypeInfo() { diff --git a/src/WinRT.Runtime/GuidGenerator.cs b/src/WinRT.Runtime/GuidGenerator.cs index b8514f537..0e9687c66 100644 --- a/src/WinRT.Runtime/GuidGenerator.cs +++ b/src/WinRT.Runtime/GuidGenerator.cs @@ -125,6 +125,11 @@ public static string GetSignature( return "string"; } + if (type == typeof(Type)) + { + return ABI.System.Type.GetGuidSignature(); + } + if (type.IsGenericType) { #if NET diff --git a/src/WinRT.Runtime/Projections.cs b/src/WinRT.Runtime/Projections.cs index 21e992799..cff2da2fb 100644 --- a/src/WinRT.Runtime/Projections.cs +++ b/src/WinRT.Runtime/Projections.cs @@ -44,7 +44,9 @@ static Projections() RegisterCustomAbiTypeMappingNoLock(typeof(char), typeof(ABI.System.Char), "Char"); // Also always register Type, since it's "free" (no associated ABI type to root) + // given Type is special-cased in all relevant areas including Marshaler. CustomTypeToAbiTypeNameMappings.Add(typeof(Type), "Windows.UI.Xaml.Interop.TypeName"); + CustomAbiTypeNameToTypeMappings.Add("Windows.UI.Xaml.Interop.TypeName", typeof(Type)); #if NET // If default mappings are disabled, we avoid rooting everything by default.