diff --git a/build/AzurePipelineTemplates/CsWinRT-FunctionalTest-Steps.yml b/build/AzurePipelineTemplates/CsWinRT-FunctionalTest-Steps.yml
index 5ae79362d0..b742f26954 100644
--- a/build/AzurePipelineTemplates/CsWinRT-FunctionalTest-Steps.yml
+++ b/build/AzurePipelineTemplates/CsWinRT-FunctionalTest-Steps.yml
@@ -62,20 +62,20 @@ steps:
TargetFolder: $(StagingFolder)\FunctionalTests\${{ functionalTest }}\
- task: MSBuild@1
- displayName: Publish ${{ functionalTest }} for AOT (net8.0)
+ displayName: Publish ${{ functionalTest }} for AOT (net9.0)
condition: and(succeeded(), and(eq(variables['BuildConfiguration'], 'release'), eq(variables['BuildPlatform'], 'x64')))
inputs:
solution: $(Build.SourcesDirectory)\src\Tests\FunctionalTests\${{ functionalTest }}\${{ functionalTest }}.csproj
- msbuildArguments: /t:publish /p:CIBuildReason=CI,RuntimeIdentifier=win-$(BuildPlatform),TargetFramework=net8.0,solutiondir=$(Build.SourcesDirectory)\src\,VersionNumber=$(VersionNumber),VersionString=$(Build.BuildNumber),AssemblyVersionNumber=$(WinRT.Runtime.AssemblyVersion),GenerateTestProjection=true,AllowedReferenceRelatedFileExtensions=".xml;.pri;.dll.config;.exe.config"
+ msbuildArguments: /t:publish /p:CIBuildReason=CI,RuntimeIdentifier=win-$(BuildPlatform),TargetFramework=net9.0,solutiondir=$(Build.SourcesDirectory)\src\,VersionNumber=$(VersionNumber),VersionString=$(Build.BuildNumber),AssemblyVersionNumber=$(WinRT.Runtime.AssemblyVersion),GenerateTestProjection=true,AllowedReferenceRelatedFileExtensions=".xml;.pri;.dll.config;.exe.config"
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
- task: CmdLine@2
- displayName: Run ${{ functionalTest }} for AOT (net8.0)
+ displayName: Run ${{ functionalTest }} for AOT (net9.0)
condition: and(succeeded(), and(eq(variables['BuildConfiguration'], 'release'), eq(variables['BuildPlatform'], 'x64')))
continueOnError: True
inputs:
- workingDirectory: $(Build.SourcesDirectory)\src\Tests\FunctionalTests\${{ functionalTest }}\bin\$(BuildConfiguration)\net8.0\win-$(BuildPlatform)\publish
+ workingDirectory: $(Build.SourcesDirectory)\src\Tests\FunctionalTests\${{ functionalTest }}\bin\$(BuildConfiguration)\net9.0\win-$(BuildPlatform)\publish
script: |
dir
echo Running ${{ functionalTest }}.exe
@@ -86,8 +86,8 @@ steps:
exit /b 0
- task: CopyFiles@2
- displayName: Copy ${{ functionalTest }} for AOT (net8.0)
+ displayName: Copy ${{ functionalTest }} for AOT (net9.0)
condition: and(eq(variables['_PublishFunctionalTests'], 'true'), and(eq(variables['BuildConfiguration'], 'release'), eq(variables['BuildPlatform'], 'x64')))
inputs:
- SourceFolder: $(Build.SourcesDirectory)\src\Tests\FunctionalTests\${{ functionalTest }}\bin\$(BuildConfiguration)\net8.0\win-$(BuildPlatform)\publish
+ SourceFolder: $(Build.SourcesDirectory)\src\Tests\FunctionalTests\${{ functionalTest }}\bin\$(BuildConfiguration)\net9.0\win-$(BuildPlatform)\publish
TargetFolder: $(StagingFolder)\FunctionalTests\${{ functionalTest }}\
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 59c8ce0679..6becbb3232 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -35,7 +35,7 @@
net8.0;net9.0
net8.0-windows10.0.19041.0
net8.0-windows10.0.19041.0
- net8.0
+ net8.0;net9.0
false
high
diff --git a/src/Tests/FunctionalTests/Collections/Program.cs b/src/Tests/FunctionalTests/Collections/Program.cs
index 6ff5f36699..b710477e4b 100644
--- a/src/Tests/FunctionalTests/Collections/Program.cs
+++ b/src/Tests/FunctionalTests/Collections/Program.cs
@@ -6,6 +6,7 @@
using System.Threading;
using test_component_derived.Nested;
using TestComponentCSharp;
+using Windows.Foundation;
var instance = new Class();
@@ -40,6 +41,84 @@
return 101;
}
+string[] stringArr = new string[] { "apples", "oranges", "pears" };
+string[] stringArr2 = new string[stringArr.Length];
+string[] outStringArr;
+string[] retStringArr = instance2.Array12(stringArr, stringArr2, out outStringArr);
+if (!AllEqual(stringArr, stringArr2, outStringArr, retStringArr))
+{
+ return 101;
+}
+
+TestComponent.Blittable[] blittableArr = new TestComponent.Blittable[] {
+ new TestComponent.Blittable(1, 2, 3, 4, -5, -6, -7, 8.0f, 9.0, typeof(TestComponent.ITests).GUID),
+ new TestComponent.Blittable(10, 20, 30, 40, -50, -60, -70, 80.0f, 90.0, typeof(IStringable).GUID)
+ };
+TestComponent.Blittable[] blittableArr2 = new TestComponent.Blittable[blittableArr.Length];
+TestComponent.Blittable[] outBlittableArr;
+TestComponent.Blittable[] retBlittableArr = instance2.Array13(blittableArr, blittableArr2, out outBlittableArr);
+if (!AllEqual(blittableArr, blittableArr2, outBlittableArr, retBlittableArr))
+{
+ return 101;
+}
+
+#if NET9_0_OR_GREATER
+
+TestComponent.NonBlittable[] nonBlittableArr = new TestComponent.NonBlittable[] {
+ new TestComponent.NonBlittable(false, 'X', "First", (long?)PropertyValue.CreateInt64(123)),
+ new TestComponent.NonBlittable(true, 'Y', "Second", (long?)PropertyValue.CreateInt64(456)),
+ new TestComponent.NonBlittable(false, 'Z', "Third", (long?)PropertyValue.CreateInt64(789))
+ };
+TestComponent.NonBlittable[] nonBlittableArr2 = new TestComponent.NonBlittable[nonBlittableArr.Length];
+TestComponent.NonBlittable[] outNonBlittableArr;
+TestComponent.NonBlittable[] retNonBlittableArr = instance2.Array14(nonBlittableArr, nonBlittableArr2, out outNonBlittableArr);
+if (!AllEqual(nonBlittableArr, nonBlittableArr2, outNonBlittableArr, retNonBlittableArr))
+{
+ return 101;
+}
+
+TestComponent.Nested[] nestedArr = new TestComponent.Nested[]{
+ new TestComponent.Nested(
+ new TestComponent.Blittable(1, 2, 3, 4, -5, -6, -7, 8.0f, 9.0, typeof(TestComponent.ITests).GUID),
+ new TestComponent.NonBlittable(false, 'X', "First", (long?)PropertyValue.CreateInt64(123))),
+ new TestComponent.Nested(
+ new TestComponent.Blittable(10, 20, 30, 40, -50, -60, -70, 80.0f, 90.0, typeof(IStringable).GUID),
+ new TestComponent.NonBlittable(true, 'Y', "Second", (long?)PropertyValue.CreateInt64(456))),
+ new TestComponent.Nested(
+ new TestComponent.Blittable(1, 2, 3, 4, -5, -6, -7, 8.0f, 9.0, typeof(WinRT.IInspectable).GUID),
+ new TestComponent.NonBlittable(false, 'Z', "Third", (long?)PropertyValue.CreateInt64(789)))
+ };
+TestComponent.Nested[] nestedArr2 = new TestComponent.Nested[nestedArr.Length];
+TestComponent.Nested[] outNestedArr;
+TestComponent.Nested[] retNestedArr = instance2.Array15(nestedArr, nestedArr2, out outNestedArr);
+if (!AllEqual(nestedArr, nestedArr2, outNestedArr, retNestedArr))
+{
+ return 101;
+}
+
+EnumValue[] enumArr = new EnumValue[] { EnumValue.One, EnumValue.Two };
+instance.EnumsProperty = enumArr;
+EnumValue[] retEnumArr = instance.EnumsProperty;
+if (!AllEqual(enumArr, retEnumArr))
+{
+ return 101;
+}
+
+#endif
+
+IStringable[] stringableArr = new IStringable[] {
+ Windows.Data.Json.JsonValue.CreateNumberValue(3),
+ Windows.Data.Json.JsonValue.CreateNumberValue(4),
+ Windows.Data.Json.JsonValue.CreateNumberValue(5.0)
+ };
+IStringable[] stringableArr2 = new IStringable[stringableArr.Length];
+IStringable[] outStringableArr;
+IStringable[] retStringableArr = instance2.Array16(stringableArr, stringableArr2, out outStringableArr);
+if (!AllEqual(stringableArr, stringableArr2, outStringableArr, retStringableArr))
+{
+ return 101;
+}
+
var hierarchyDAsObjectList = HierarchyC.CreateDerivedHierarchyDAsObjectList();
foreach (var hierarchyDAsObject in hierarchyDAsObjectList)
{
diff --git a/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj b/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj
index f65cc8b91b..df41ced1b3 100644
--- a/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj
+++ b/src/Tests/FunctionalTests/JsonValueFunctionCalls/JsonValueFunctionCalls.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs b/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs
index dbe1054435..2d47eb4aa3 100644
--- a/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs
+++ b/src/Tests/FunctionalTests/JsonValueFunctionCalls/Program.cs
@@ -19,10 +19,16 @@
// Class function call
result += (int)(a[1] as Windows.Data.Json.JsonValue).GetNumber();
-var enumVal = TestComponentCSharp.Class.BoxedEnum;
-if (enumVal is TestComponentCSharp.EnumValue val && val == TestComponentCSharp.EnumValue.Two)
-{
- result += 1;
-}
+CheckBoxedEnum();
-return result == 17 ? 100 : 101;
\ No newline at end of file
+return result == 17 ? 100 : 101;
+
+[WinRT.DynamicWindowsRuntimeCast(typeof(TestComponentCSharp.EnumValue))]
+void CheckBoxedEnum()
+{
+ var enumVal = TestComponentCSharp.Class.BoxedEnum;
+ if (enumVal is TestComponentCSharp.EnumValue val && val == TestComponentCSharp.EnumValue.Two)
+ {
+ result += 1;
+ }
+}
\ No newline at end of file
diff --git a/src/WinRT.Runtime/Marshalers.cs b/src/WinRT.Runtime/Marshalers.cs
index 4c8064d0b7..ec6f3f1692 100644
--- a/src/WinRT.Runtime/Marshalers.cs
+++ b/src/WinRT.Runtime/Marshalers.cs
@@ -685,6 +685,32 @@ static MarshalGeneric()
DisposeMarshaler = ABI.System.NonBlittableMarshallingStubs.NoOpFunc;
DisposeAbi = ABI.System.NonBlittableMarshallingStubs.NoOpFunc;
}
+ else if (typeof(T).IsEnum)
+ {
+ Func ReturnTypedParameterFunc = (T value) => value;
+ AbiType = typeof(T);
+ CreateMarshaler = ReturnTypedParameterFunc;
+ CreateMarshaler2 = CreateMarshaler;
+ GetAbi = Marshaler.ReturnParameterFunc;
+ FromAbi = (object value) => (T)value;
+ FromManaged = ReturnTypedParameterFunc;
+ DisposeMarshaler = ABI.System.NonBlittableMarshallingStubs.NoOpFunc;
+ DisposeAbi = ABI.System.NonBlittableMarshallingStubs.NoOpFunc;
+ if (typeof(T).IsEnum)
+ {
+ // For marshaling non-blittable enum arrays via MarshalNonBlittable
+ if (typeof(T).GetEnumUnderlyingType() == typeof(int))
+ {
+ CopyAbi = Marshaler.CopyIntEnumFunc;
+ CopyManaged = Marshaler.CopyIntEnumDirectFunc.WithTypedT1();
+ }
+ else
+ {
+ CopyAbi = Marshaler.CopyUIntEnumFunc;
+ CopyManaged = Marshaler.CopyUIntEnumDirectFunc.WithTypedT1();
+ }
+ }
+ }
else if (typeof(T).IsValueType)
{
// Value types can have custom marshaller types and use value types in places where we can't construct
@@ -1088,7 +1114,10 @@ public void Dispose()
{
foreach (var marshaler in _marshalers)
{
- Marshaler.DisposeMarshaler(marshaler);
+ // We make use of MarshalNonBlittable for array marshaling when T is non-blittable or when it is an enum.
+ // Both scenarios are handled by MarshalNonBlittable for marshaling T itself, so we just directly use that
+ // here and below without needing to go through Marshaler.
+ MarshalNonBlittable.DisposeMarshaler(marshaler);
}
}
if (_array != IntPtr.Zero)
@@ -1103,7 +1132,7 @@ public void Dispose()
public static new unsafe MarshalerArray CreateMarshalerArray(T[] array)
{
-#if NET
+#if NET && !NET9_0_OR_GREATER
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot handle array marshalling for non blittable type '{typeof(T)}'.");
@@ -1131,8 +1160,8 @@ public void Dispose()
var element = (byte*)m._array.ToPointer();
for (int i = 0; i < length; i++)
{
- m._marshalers[i] = Marshaler.CreateMarshaler(array[i]);
- Marshaler.CopyAbi(m._marshalers[i], (IntPtr)element);
+ m._marshalers[i] = MarshalNonBlittable.CreateMarshaler(array[i]);
+ MarshalNonBlittable.CopyAbi(m._marshalers[i], (IntPtr)element);
element += abi_element_size;
}
#pragma warning restore IL3050
@@ -1156,7 +1185,7 @@ public void Dispose()
public static new unsafe T[] FromAbiArray(object box)
{
-#if NET
+#if NET && !NET9_0_OR_GREATER
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot handle array marshalling for non blittable type '{typeof(T)}'.");
@@ -1188,7 +1217,7 @@ public void Dispose()
#else
Marshal.PtrToStructure((IntPtr)data, AbiType);
#endif
- array[i] = Marshaler.FromAbi(abi_element);
+ array[i] = MarshalNonBlittable.FromAbi(abi_element);
data += abi_element_size;
}
#pragma warning restore IL3050
@@ -1197,7 +1226,7 @@ public void Dispose()
public static unsafe void CopyAbiArray(T[] array, object box)
{
-#if NET
+#if NET && !NET9_0_OR_GREATER
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot handle array marshalling for non blittable type '{typeof(T)}'.");
@@ -1224,7 +1253,7 @@ public static unsafe void CopyAbiArray(T[] array, object box)
#else
Marshal.PtrToStructure((IntPtr)data, AbiType);
#endif
- array[i] = Marshaler.FromAbi(abi_element);
+ array[i] = MarshalNonBlittable.FromAbi(abi_element);
data += abi_element_size;
}
#pragma warning restore IL3050
@@ -1232,7 +1261,7 @@ public static unsafe void CopyAbiArray(T[] array, object box)
public static new unsafe (int length, IntPtr data) FromManagedArray(T[] array)
{
-#if NET
+#if NET && !NET9_0_OR_GREATER
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot handle array marshalling for non blittable type '{typeof(T)}'.");
@@ -1260,7 +1289,7 @@ public static unsafe void CopyAbiArray(T[] array, object box)
var bytes = (byte*)data.ToPointer();
for (i = 0; i < length; i++)
{
- Marshaler.CopyManaged(array[i], (IntPtr)bytes);
+ MarshalNonBlittable.CopyManaged(array[i], (IntPtr)bytes);
bytes += abi_element_size;
}
#pragma warning restore IL3050
@@ -1278,7 +1307,7 @@ public static unsafe void CopyAbiArray(T[] array, object box)
public static unsafe void CopyManagedArray(T[] array, IntPtr data)
{
-#if NET
+#if NET && !NET9_0_OR_GREATER
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"Cannot handle array marshalling for non blittable type '{typeof(T)}'.");
@@ -1304,7 +1333,7 @@ public static unsafe void CopyManagedArray(T[] array, IntPtr data)
var bytes = (byte*)data.ToPointer();
for (i = 0; i < length; i++)
{
- Marshaler.CopyManaged(array[i], (IntPtr)bytes);
+ MarshalNonBlittable.CopyManaged(array[i], (IntPtr)bytes);
bytes += abi_element_size;
}
#pragma warning restore IL3050