Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix GetEnumerator when C# enumerator gets passed to native and back #1735

Merged
merged 5 commits into from
Sep 7, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix GetEnumerator when C# enumerator gets passed to native and back a…
…nd add tests
  • Loading branch information
manodasanW committed Sep 6, 2024
commit 2ed7f3a21076bbee1fa6178e0e3825a5f901040c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@
<value>Class is not marked partial</value>
</data>
<data name="ClassNotMarkedPartial_Text" xml:space="preserve">
<value>Class '{0}' implements WinRT interfaces but isn't marked partial. Type should be marked partial for trimming and AOT compatibility if passed across the ABI.</value>
<value>Class '{0}' implements WinRT interfaces but isn't marked partial. Type should be marked partial for trimming and AOT compatibility if passed across the WinRT ABI.</value>
</data>
<data name="DisjointNamespaceRule_Brief" xml:space="preserve">
<value>Namespace is disjoint from main (winmd) namespace</value>
Expand All @@ -130,7 +130,7 @@
<value>Project does not enable unsafe blocks</value>
</data>
<data name="EnableUnsafe_Text" xml:space="preserve">
<value>Type '{0}' implements generic WinRT interfaces which requires generated code using unsafe for trimming and AOT compatibility if passed across the ABI. Project needs to be updated with '&lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt;'.</value>
<value>Type '{0}' implements generic WinRT interfaces which requires generated code using unsafe for trimming and AOT compatibility if passed across the WinRT ABI. Project needs to be updated with '&lt;AllowUnsafeBlocks&gt;true&lt;/AllowUnsafeBlocks&gt;'.</value>
</data>
<data name="GenericTypeRule_Brief" xml:space="preserve">
<value>Class (or interface) is generic</value>
Expand Down
2 changes: 1 addition & 1 deletion src/Tests/FunctionalTests/CCW/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ partial class Language
{
private readonly string[] _values = new string[4];

public string Name { get; } = "Language";
public string Name { get; init; } = "Language";
public int Value { get; set; }
public string this[int i]
{
Expand Down
40 changes: 40 additions & 0 deletions src/Tests/FunctionalTests/Collections/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,46 @@
return 101;
}

int sum = 0;
var enumerator = instance.GetIteratorForCollection(expected);
while (enumerator.MoveNext())
{
sum += enumerator.Current;
}

if (sum != 3)
{
return 101;
}

sum = 0;

CustomIterableTest customIterableTest = new CustomIterableTest();
foreach (var i in customIterableTest)
{
sum += i;
}

if (sum != 6)
{
return 101;
}

sum = 0;

var arr = new int[] { 2, 4, 6 };
CustomIterableTest customIterableTest2 = new CustomIterableTest(arr);
foreach (var i in customIterableTest2)
{
sum += i;
}

if (sum != 12)
{
return 101;
}


return 100;

static bool SequencesEqual<T>(IEnumerable<T> x, params IEnumerable<T>[] list) => list.All((y) => x.SequenceEqual(y));
Expand Down
5 changes: 5 additions & 0 deletions src/Tests/TestComponentCSharp/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,11 @@ namespace winrt::TestComponentCSharp::implementation
return winrt::single_threaded_vector(std::vector{ first, second });
}

IIterator<int32_t> Class::GetIteratorForCollection(IIterable<int32_t> iterable)
{
return iterable.First();
}

IBindableIterable Class::BindableIterableProperty()
{
return _bindableIterable;
Expand Down
2 changes: 2 additions & 0 deletions src/Tests/TestComponentCSharp/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ namespace winrt::TestComponentCSharp::implementation
Windows::Foundation::Collections::IIterable<TestComponentCSharp::EnumValue> GetEnumIterable();
Windows::Foundation::Collections::IIterable<TestComponentCSharp::CustomDisposableTest> GetClassIterable();

Windows::Foundation::Collections::IIterator<int32_t> GetIteratorForCollection(Windows::Foundation::Collections::IIterable<int32_t> iterable);

Microsoft::UI::Xaml::Interop::IBindableIterable BindableIterableProperty();
void BindableIterableProperty(Microsoft::UI::Xaml::Interop::IBindableIterable const& value);
void RaiseBindableIterableChanged();
Expand Down
21 changes: 21 additions & 0 deletions src/Tests/TestComponentCSharp/CustomIterableTest.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#include "pch.h"
#include "CustomIterableTest.h"
#include "CustomIterableTest.g.cpp"

namespace winrt::TestComponentCSharp::implementation
{
CustomIterableTest::CustomIterableTest()
{
_iterable = winrt::single_threaded_vector(std::vector{ 0, 2, 4 });
}

CustomIterableTest::CustomIterableTest(winrt::Windows::Foundation::Collections::IIterable<int32_t> const& iterable)
{
_iterable = iterable;
}

winrt::Windows::Foundation::Collections::IIterator<int32_t> CustomIterableTest::First()
{
return _iterable.First();
}
}
22 changes: 22 additions & 0 deletions src/Tests/TestComponentCSharp/CustomIterableTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma once
#include "CustomIterableTest.g.h"

namespace winrt::TestComponentCSharp::implementation
{
struct CustomIterableTest : CustomIterableTestT<CustomIterableTest>
{
CustomIterableTest();
CustomIterableTest(winrt::Windows::Foundation::Collections::IIterable<int32_t> const& iterable);

winrt::Windows::Foundation::Collections::IIterator<int32_t> First();

winrt::Windows::Foundation::Collections::IIterable<int32_t> _iterable;
};
}

namespace winrt::TestComponentCSharp::factory_implementation
{
struct CustomIterableTest : CustomIterableTestT<CustomIterableTest, implementation::CustomIterableTest>
{
};
}
9 changes: 9 additions & 0 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.idl
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,8 @@ namespace TestComponentCSharp
Windows.Foundation.Collections.IIterable<EnumValue> GetEnumIterable();
Windows.Foundation.Collections.IIterable<CustomDisposableTest> GetClassIterable();

Windows.Foundation.Collections.IIterator<Int32> GetIteratorForCollection(Windows.Foundation.Collections.IIterable<Int32> iterable);

// Bindable
Microsoft.UI.Xaml.Interop.IBindableIterable BindableIterableProperty;
void RaiseBindableIterableChanged();
Expand Down Expand Up @@ -518,6 +520,13 @@ namespace TestComponentCSharp
CustomIteratorTest();
}

[default_interface]
runtimeclass CustomIterableTest : Windows.Foundation.Collections.IIterable<Int32>
{
CustomIterableTest();
CustomIterableTest(Windows.Foundation.Collections.IIterable<Int32> iterable);
}

// SupportedOSPlatform warning tests
[contract(Windows.Foundation.UniversalApiContract, 10)]
[attributeusage(target_all)]
Expand Down
2 changes: 2 additions & 0 deletions src/Tests/TestComponentCSharp/TestComponentCSharp.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
<ClInclude Include="ClassWithExplicitIUnknown.h" />
<ClInclude Include="CustomExperimentClass.h" />
<ClInclude Include="CustomEquals.h" />
<ClInclude Include="CustomIterableTest.h" />
<ClInclude Include="ManualProjectionTestClasses.h" />
<ClInclude Include="pch.h" />
<ClInclude Include="Class.h">
Expand All @@ -105,6 +106,7 @@
<ClCompile Include="ClassWithExplicitIUnknown.cpp" />
<ClCompile Include="CustomExperimentClass.cpp" />
<ClCompile Include="CustomEquals.cpp" />
<ClCompile Include="CustomIterableTest.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<ClCompile Include="CustomExperimentClass.cpp" />
<ClCompile Include="WinRT.Class.cpp" />
<ClCompile Include="ClassWithExplicitIUnknown.cpp" />
<ClCompile Include="NonUniqueClass.cpp" />
<ClCompile Include="CustomIterableTest.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
Expand All @@ -39,6 +41,8 @@
<ClInclude Include="CustomExperimentClass.h" />
<ClInclude Include="WinRT.Class.h" />
<ClInclude Include="ClassWithExplicitIUnknown.h" />
<ClInclude Include="NonUniqueClass.h" />
<ClInclude Include="CustomIterableTest.h" />
</ItemGroup>
<ItemGroup>
<Midl Include="TestComponentCSharp.idl" />
Expand Down
7 changes: 6 additions & 1 deletion src/WinRT.Runtime/Projections/IEnumerable.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ static IEnumerableMethods()
{
return new global::ABI.System.Collections.Generic.FromAbiEnumerator<T>(ienumeratorImpl);
}
else if (first is global::ABI.System.Collections.Generic.ToAbiEnumeratorAdapter<T> toAbiAdapter)
{
// Unwrap to get the C# enumerator if it was originally one.
return toAbiAdapter.m_enumerator;
}

throw new InvalidOperationException("Unexpected type for enumerator");
}
Expand Down Expand Up @@ -939,7 +944,7 @@ public ComWrappers.ComInterfaceEntry[] GetExposedInterfaces()
// we can't make them AOT friendly due to we can't reference them.
public sealed class ToAbiEnumeratorAdapter<T> : global::System.Collections.Generic.IEnumerator<T>, global::System.Collections.IEnumerator
{
private readonly global::System.Collections.Generic.IEnumerator<T> m_enumerator;
internal readonly global::System.Collections.Generic.IEnumerator<T> m_enumerator;

internal ToAbiEnumeratorAdapter(global::System.Collections.Generic.IEnumerator<T> enumerator) => m_enumerator = enumerator;

Expand Down