From 5c457e8262339a682df6085c2706da6c3a062895 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 23 Dec 2025 20:20:53 -0800 Subject: [PATCH 01/13] Add IReadOnlyListAdapterExtensions for string IndexOf Introduces a new extension method for IReadOnlyList to provide an IndexOf overload that accepts a ReadOnlySpan, allowing callers to avoid string allocations. The extension is marked obsolete and editor-browsable never, indicating it is for internal or transitional use. --- .../IReadOnlyListAdapterExtensions.cs | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs new file mode 100644 index 000000000..acfacb2ef --- /dev/null +++ b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.ComponentModel; + +namespace WindowsRuntime.InteropServices; + +/// +/// Extensions for the type. +/// +[Obsolete(WindowsRuntimeConstants.PrivateImplementationDetailObsoleteMessage, + DiagnosticId = WindowsRuntimeConstants.PrivateImplementationDetailObsoleteDiagnosticId, + UrlFormat = WindowsRuntimeConstants.CsWinRTDiagnosticsUrlFormat)] +[EditorBrowsable(EditorBrowsableState.Never)] +public static class IReadOnlyListAdapterExtensions +{ + extension(IReadOnlyListAdapter) + { + /// + /// + /// This overload can be used to avoid a allocation on the caller side. + /// + public static bool IndexOf(IReadOnlyList list, ReadOnlySpan value, out uint index) + { + int count = list.Count; + + for (int i = 0; i < count; i++) + { + if (list[1].SequenceEqual(value)) + { + index = (uint)i; + + return true; + } + } + + // Return '0' in case of failure (see notes in original overload) + index = 0; + + return false; + } + } +} \ No newline at end of file From a9a87e936363996b0df28cbfee979bd5eae389cf Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 23 Dec 2025 20:27:46 -0800 Subject: [PATCH 02/13] Add Count method to IReadOnlyListAdapter Introduced a static Count method to retrieve the number of items in an IReadOnlyList, with aggressive inlining for performance. This provides a convenient and efficient way to access the count, aligning with IVectorView API expectations. --- .../Collections/IReadOnlyListAdapter{T}.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs index 4634d8e46..b862d767e 100644 --- a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs +++ b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.ComponentModel; +using System.Runtime.CompilerServices; namespace WindowsRuntime.InteropServices; @@ -41,6 +42,18 @@ public static T GetAt(IReadOnlyList list, uint index) } } + /// + /// Gets the number of items in the vector view. + /// + /// The wrapped instance. + /// The number of items in the vector view. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint Count(IReadOnlyList list) + { + return (uint)list.Count; + } + /// /// Retrieves the index of a specified item in the vector view. /// From a5e3da6f779172f7a7a29578764d58a27bafdf08 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Tue, 23 Dec 2025 20:46:14 -0800 Subject: [PATCH 03/13] Refactor variable naming for clarity in ABI implementations Replaces instances of 'unboxedValue' with 'thisObject' across multiple ABI and interop files for improved code readability and consistency. No functional changes were made. --- .../ABI/System/Collections/IEnumerable.cs | 4 +- .../ABI/System/Collections/IEnumerator.cs | 12 +++--- .../ABI/System/Collections/IList.cs | 40 +++++++++---------- .../Specialized/INotifyCollectionChanged.cs | 12 +++--- .../NotifyCollectionChangedEventHandler.cs | 8 ++-- .../ComponentModel/INotifyDataErrorInfo.cs | 20 +++++----- .../ComponentModel/INotifyPropertyChanged.cs | 12 +++--- .../PropertyChangedEventHandler.cs | 8 ++-- src/WinRT.Runtime2/ABI/System/EventHandler.cs | 8 ++-- src/WinRT.Runtime2/ABI/System/Exception.cs | 4 +- .../ABI/System/IServiceProvider.cs | 4 +- src/WinRT.Runtime2/ABI/System/String.cs | 12 +++--- src/WinRT.Runtime2/ABI/System/Type.cs | 4 +- .../ABI/System/Windows.Input/ICommand.cs | 20 +++++----- .../AsyncActionCompletedHandler.cs | 8 ++-- .../Collections/IVectorChangedEventArgs.cs | 8 ++-- .../ABI/Windows.Foundation/IAsyncAction.cs | 12 +++--- .../ABI/Windows.Foundation/IAsyncInfo.cs | 20 +++++----- .../IBindableIReadOnlyListAdapter.cs | 12 +++--- .../IPropertyValueImpl.InspectableArray.cs | 10 ++--- 20 files changed, 119 insertions(+), 119 deletions(-) diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs index 9453e84e5..ed4035ac7 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerable.cs @@ -165,9 +165,9 @@ private static HRESULT First(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - global::System.Collections.IEnumerator enumerator = unboxedValue.GetEnumerator(); + global::System.Collections.IEnumerator enumerator = thisObject.GetEnumerator(); *result = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(enumerator).DetachThisPtrUnsafe(); diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs index cde1bf29a..500724f5c 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IEnumerator.cs @@ -175,9 +175,9 @@ private static HRESULT get_Current(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - object? current = IBindableIteratorAdapter.GetInstance(unboxedValue).Current; + object? current = IBindableIteratorAdapter.GetInstance(thisObject).Current; *result = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(current).DetachThisPtrUnsafe(); @@ -200,9 +200,9 @@ private static HRESULT get_HasCurrent(void* thisPtr, bool* result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = IBindableIteratorAdapter.GetInstance(unboxedValue).HasCurrent; + *result = IBindableIteratorAdapter.GetInstance(thisObject).HasCurrent; return WellKnownErrorCodes.S_OK; } @@ -223,9 +223,9 @@ private static HRESULT MoveNext(void* thisPtr, bool* result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = IBindableIteratorAdapter.GetInstance(unboxedValue).MoveNext(); + *result = IBindableIteratorAdapter.GetInstance(thisObject).MoveNext(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/Collections/IList.cs b/src/WinRT.Runtime2/ABI/System/Collections/IList.cs index aaad09b50..3b3de8718 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/IList.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/IList.cs @@ -234,9 +234,9 @@ private static HRESULT GetAt(void* thisPtr, uint index, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - object? value = BindableIListAdapter.GetAt(unboxedValue, index); + object? value = BindableIListAdapter.GetAt(thisObject, index); *result = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(value).DetachThisPtrUnsafe(); @@ -259,9 +259,9 @@ private static HRESULT get_Size(void* thisPtr, uint* size) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *size = BindableIListAdapter.Size(unboxedValue); + *size = BindableIListAdapter.Size(thisObject); return WellKnownErrorCodes.S_OK; } @@ -282,9 +282,9 @@ private static HRESULT GetView(void* thisPtr, void** view) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - BindableIReadOnlyListAdapter adapter = BindableIListAdapter.GetView(unboxedValue); + BindableIReadOnlyListAdapter adapter = BindableIListAdapter.GetView(thisObject); *view = WindowsRuntime.InteropServices.BindableIReadOnlyListAdapterMarshaller.ConvertToUnmanaged(adapter).DetachThisPtrUnsafe(); @@ -307,11 +307,11 @@ private static HRESULT IndexOf(void* thisPtr, void* value, uint* index, bool* re try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); - *result = BindableIListAdapter.IndexOf(unboxedValue, item, out *index); + *result = BindableIListAdapter.IndexOf(thisObject, item, out *index); return WellKnownErrorCodes.S_OK; } @@ -327,11 +327,11 @@ private static HRESULT SetAt(void* thisPtr, uint index, void* value) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); - BindableIListAdapter.SetAt(unboxedValue, index, item); + BindableIListAdapter.SetAt(thisObject, index, item); return WellKnownErrorCodes.S_OK; } @@ -347,11 +347,11 @@ private static HRESULT InsertAt(void* thisPtr, uint index, void* value) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); - BindableIListAdapter.InsertAt(unboxedValue, index, item); + BindableIListAdapter.InsertAt(thisObject, index, item); return WellKnownErrorCodes.S_OK; } @@ -367,9 +367,9 @@ private static HRESULT RemoveAt(void* thisPtr, uint index) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - BindableIListAdapter.RemoveAt(unboxedValue, index); + BindableIListAdapter.RemoveAt(thisObject, index); return WellKnownErrorCodes.S_OK; } @@ -385,11 +385,11 @@ private static HRESULT Append(void* thisPtr, void* value) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? item = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); - BindableIListAdapter.Append(unboxedValue, item); + BindableIListAdapter.Append(thisObject, item); return WellKnownErrorCodes.S_OK; } @@ -405,9 +405,9 @@ private static HRESULT RemoveAtEnd(void* thisPtr) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - BindableIListAdapter.RemoveAtEnd(unboxedValue); + BindableIListAdapter.RemoveAtEnd(thisObject); return WellKnownErrorCodes.S_OK; } @@ -423,9 +423,9 @@ private static HRESULT Clear(void* thisPtr) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - BindableIListAdapter.Clear(unboxedValue); + BindableIListAdapter.Clear(thisObject); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs index 066cb0636..e893f79b0 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/INotifyCollectionChanged.cs @@ -157,13 +157,13 @@ private static HRESULT add_CollectionChanged(void* thisPtr, void* handler, Event { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); NotifyCollectionChangedEventHandler? managedHandler = NotifyCollectionChangedEventHandlerMarshaller.ConvertToManaged(handler); - *token = CollectionChangedTable.GetOrCreateValue(unboxedValue).AddEventHandler(managedHandler); + *token = CollectionChangedTable.GetOrCreateValue(thisObject).AddEventHandler(managedHandler); - unboxedValue.CollectionChanged += managedHandler; + thisObject.CollectionChanged += managedHandler; return WellKnownErrorCodes.S_OK; } @@ -179,11 +179,11 @@ private static HRESULT remove_CollectionChanged(void* thisPtr, EventRegistration { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - if (unboxedValue is not null && CollectionChangedTable.TryGetValue(unboxedValue, out var table) && table.RemoveEventHandler(token, out NotifyCollectionChangedEventHandler? managedHandler)) + if (thisObject is not null && CollectionChangedTable.TryGetValue(thisObject, out var table) && table.RemoveEventHandler(token, out NotifyCollectionChangedEventHandler? managedHandler)) { - unboxedValue.CollectionChanged -= managedHandler; + thisObject.CollectionChanged -= managedHandler; } return WellKnownErrorCodes.S_OK; diff --git a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs index 4e50e4eb8..40e21cfbc 100644 --- a/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/Collections/Specialized/NotifyCollectionChangedEventHandler.cs @@ -223,9 +223,9 @@ private static HRESULT Invoke(void* thisPtr, void* sender, void* e) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue( + thisObject( WindowsRuntimeObjectMarshaller.ConvertToManaged(sender), NotifyCollectionChangedEventArgsMarshaller.ConvertToManaged(e)!); @@ -294,9 +294,9 @@ private static HRESULT get_Value(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = NotifyCollectionChangedEventHandlerMarshaller.ConvertToUnmanaged(unboxedValue).DetachThisPtrUnsafe(); + *result = NotifyCollectionChangedEventHandlerMarshaller.ConvertToUnmanaged(thisObject).DetachThisPtrUnsafe(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs index 6d1699463..3bc5626ed 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyDataErrorInfo.cs @@ -213,9 +213,9 @@ private static HRESULT get_HasErrors(void* thisPtr, bool* result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = unboxedValue.HasErrors; + *result = thisObject.HasErrors; return WellKnownErrorCodes.S_OK; } @@ -233,7 +233,7 @@ private static HRESULT add_ErrorsChanged(void* thisPtr, void* handler, EventRegi try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod)] static extern EventHandler? ConvertToManaged( @@ -242,9 +242,9 @@ private static HRESULT add_ErrorsChanged(void* thisPtr, void* handler, EventRegi EventHandler? managedHandler = ConvertToManaged(null, handler); - *token = ErrorsChanged.GetOrCreateValue(unboxedValue).AddEventHandler(managedHandler); + *token = ErrorsChanged.GetOrCreateValue(thisObject).AddEventHandler(managedHandler); - unboxedValue.ErrorsChanged += managedHandler; + thisObject.ErrorsChanged += managedHandler; return WellKnownErrorCodes.S_OK; } @@ -260,11 +260,11 @@ private static HRESULT remove_ErrorsChanged(void* thisPtr, EventRegistrationToke { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - if (unboxedValue is not null && ErrorsChanged.TryGetValue(unboxedValue, out var table) && table.RemoveEventHandler(token, out EventHandler? managedHandler)) + if (thisObject is not null && ErrorsChanged.TryGetValue(thisObject, out var table) && table.RemoveEventHandler(token, out EventHandler? managedHandler)) { - unboxedValue.ErrorsChanged -= managedHandler; + thisObject.ErrorsChanged -= managedHandler; } return WellKnownErrorCodes.S_OK; @@ -283,9 +283,9 @@ private static HRESULT GetErrors(void* thisPtr, HSTRING propertyName, void** res try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - IEnumerable managedResult = unboxedValue.GetErrors(HStringMarshaller.ConvertToManaged(propertyName)); + IEnumerable managedResult = thisObject.GetErrors(HStringMarshaller.ConvertToManaged(propertyName)); [UnsafeAccessor(UnsafeAccessorKind.StaticMethod)] static extern WindowsRuntimeObjectReferenceValue ConvertToUnmanaged( diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs index 332ae0d9f..681d1d046 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/INotifyPropertyChanged.cs @@ -158,13 +158,13 @@ private static HRESULT add_PropertyChanged(void* thisPtr, void* handler, EventRe try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); PropertyChangedEventHandler? managedHandler = PropertyChangedEventHandlerMarshaller.ConvertToManaged(handler); - *token = PropertyChangedTable.GetOrCreateValue(unboxedValue).AddEventHandler(managedHandler); + *token = PropertyChangedTable.GetOrCreateValue(thisObject).AddEventHandler(managedHandler); - unboxedValue.PropertyChanged += managedHandler; + thisObject.PropertyChanged += managedHandler; return WellKnownErrorCodes.S_OK; } @@ -180,11 +180,11 @@ private static HRESULT remove_PropertyChanged(void* thisPtr, EventRegistrationTo { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - if (unboxedValue is not null && PropertyChangedTable.TryGetValue(unboxedValue, out var table) && table.RemoveEventHandler(token, out PropertyChangedEventHandler? managedHandler)) + if (thisObject is not null && PropertyChangedTable.TryGetValue(thisObject, out var table) && table.RemoveEventHandler(token, out PropertyChangedEventHandler? managedHandler)) { - unboxedValue.PropertyChanged -= managedHandler; + thisObject.PropertyChanged -= managedHandler; } return WellKnownErrorCodes.S_OK; diff --git a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs index f0c8970ac..d7dc50c23 100644 --- a/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/ComponentModel/PropertyChangedEventHandler.cs @@ -222,9 +222,9 @@ private static HRESULT Invoke(void* thisPtr, void* sender, void* e) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue( + thisObject( WindowsRuntimeObjectMarshaller.ConvertToManaged(sender), PropertyChangedEventArgsMarshaller.ConvertToManaged(e)!); @@ -293,9 +293,9 @@ private static HRESULT get_Value(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = PropertyChangedEventHandlerMarshaller.ConvertToUnmanaged(unboxedValue).DetachThisPtrUnsafe(); + *result = PropertyChangedEventHandlerMarshaller.ConvertToUnmanaged(thisObject).DetachThisPtrUnsafe(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/EventHandler.cs b/src/WinRT.Runtime2/ABI/System/EventHandler.cs index 0e8336d1f..d1adbe342 100644 --- a/src/WinRT.Runtime2/ABI/System/EventHandler.cs +++ b/src/WinRT.Runtime2/ABI/System/EventHandler.cs @@ -229,9 +229,9 @@ private static HRESULT Invoke(void* thisPtr, void* sender, void* e) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue( + thisObject( WindowsRuntimeObjectMarshaller.ConvertToManaged(sender), WindowsRuntimeObjectMarshaller.ConvertToManaged(e) as EventArgs ?? EventArgs.Empty); @@ -300,9 +300,9 @@ private static HRESULT get_Value(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = EventHandlerMarshaller.ConvertToUnmanaged(unboxedValue).DetachThisPtrUnsafe(); + *result = EventHandlerMarshaller.ConvertToUnmanaged(thisObject).DetachThisPtrUnsafe(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/Exception.cs b/src/WinRT.Runtime2/ABI/System/Exception.cs index 37c20f295..097dc9f06 100644 --- a/src/WinRT.Runtime2/ABI/System/Exception.cs +++ b/src/WinRT.Runtime2/ABI/System/Exception.cs @@ -227,9 +227,9 @@ private static HRESULT get_Value(void* thisPtr, Exception* result) try { - global::System.Exception unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + global::System.Exception thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = ExceptionMarshaller.ConvertToUnmanaged(unboxedValue); + *result = ExceptionMarshaller.ConvertToUnmanaged(thisObject); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs b/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs index d38df50ab..efe35d588 100644 --- a/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs +++ b/src/WinRT.Runtime2/ABI/System/IServiceProvider.cs @@ -133,7 +133,7 @@ private static HRESULT GetService(void* thisPtr, Type serviceType, void** result try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); global::System.Type? managedType = TypeMarshaller.ConvertToManaged(serviceType); @@ -143,7 +143,7 @@ private static HRESULT GetService(void* thisPtr, Type serviceType, void** result TypeExceptions.ThrowArgumentExceptionForNullType(serviceType); } - object? service = unboxedValue.GetService(managedType); + object? service = thisObject.GetService(managedType); *result = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(service).DetachThisPtrUnsafe(); diff --git a/src/WinRT.Runtime2/ABI/System/String.cs b/src/WinRT.Runtime2/ABI/System/String.cs index 201a747f1..4ee042a1f 100644 --- a/src/WinRT.Runtime2/ABI/System/String.cs +++ b/src/WinRT.Runtime2/ABI/System/String.cs @@ -217,9 +217,9 @@ public static HRESULT get_Value(void* thisPtr, HSTRING* result) try { - string unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + string thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = HStringMarshaller.ConvertToUnmanaged(unboxedValue); + *result = HStringMarshaller.ConvertToUnmanaged(thisObject); return WellKnownErrorCodes.S_OK; } @@ -386,9 +386,9 @@ private static HRESULT GetGuid(void* thisPtr, Guid* value) try { - string unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + string thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *value = Guid.Parse(unboxedValue); + *value = Guid.Parse(thisObject); return WellKnownErrorCodes.S_OK; } @@ -413,11 +413,11 @@ private static HRESULT GetNumeric(void* thisPtr, T* value) try { - string unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + string thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); try { - *value = T.Parse(unboxedValue, CultureInfo.InvariantCulture); + *value = T.Parse(thisObject, CultureInfo.InvariantCulture); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/Type.cs b/src/WinRT.Runtime2/ABI/System/Type.cs index 9e8c9deec..38df75e65 100644 --- a/src/WinRT.Runtime2/ABI/System/Type.cs +++ b/src/WinRT.Runtime2/ABI/System/Type.cs @@ -328,9 +328,9 @@ private static HRESULT get_Value(void* thisPtr, Type* result) try { - global::System.Type unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + global::System.Type thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = TypeMarshaller.ConvertToUnmanaged(unboxedValue); + *result = TypeMarshaller.ConvertToUnmanaged(thisObject); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs b/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs index b9aa0ec0b..c6531f57f 100644 --- a/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs +++ b/src/WinRT.Runtime2/ABI/System/Windows.Input/ICommand.cs @@ -190,13 +190,13 @@ private static HRESULT add_CanExecuteChanged(void* thisPtr, void* handler, Event try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); EventHandler? managedHandler = EventHandlerMarshaller.ConvertToManaged(handler); - *token = CanExecuteChangedTable.GetOrCreateValue(unboxedValue).AddEventHandler(managedHandler); + *token = CanExecuteChangedTable.GetOrCreateValue(thisObject).AddEventHandler(managedHandler); - unboxedValue.CanExecuteChanged += managedHandler; + thisObject.CanExecuteChanged += managedHandler; return WellKnownErrorCodes.S_OK; } @@ -212,7 +212,7 @@ private static HRESULT remove_CanExecuteChanged(void* thisPtr, EventRegistration { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); // This 'null' check on the unboxed object is intentional, and we're only do this specifically from 'remove_EventName' methods. // The reason is that for tracker objects (ie. in XAML scenarios), the framework will often mark objects as not rooted, and then @@ -220,9 +220,9 @@ private static HRESULT remove_CanExecuteChanged(void* thisPtr, EventRegistration // count of the registered handlers is 0 (which is valid for tracked objects), 'ComWrappers' will allow the GC to collect them, // and just keep the CCW alive and in a special "destroyed" state. When that happens, trying to get the original managed object // back will just return 'null', which is why we have this additional check here. In all other ABI methods, it's not needed. - if (unboxedValue is not null && CanExecuteChangedTable.TryGetValue(unboxedValue, out var table) && table.RemoveEventHandler(token, out EventHandler? managedHandler)) + if (thisObject is not null && CanExecuteChangedTable.TryGetValue(thisObject, out var table) && table.RemoveEventHandler(token, out EventHandler? managedHandler)) { - unboxedValue.CanExecuteChanged -= managedHandler; + thisObject.CanExecuteChanged -= managedHandler; } return WellKnownErrorCodes.S_OK; @@ -241,9 +241,9 @@ private static HRESULT CanExecute(void* thisPtr, void* parameter, bool* result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = unboxedValue.CanExecute(WindowsRuntimeObjectMarshaller.ConvertToManaged(parameter)); + *result = thisObject.CanExecute(WindowsRuntimeObjectMarshaller.ConvertToManaged(parameter)); return WellKnownErrorCodes.S_OK; } @@ -259,9 +259,9 @@ private static HRESULT Execute(void* thisPtr, void* parameter) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue.Execute(WindowsRuntimeObjectMarshaller.ConvertToManaged(parameter)); + thisObject.Execute(WindowsRuntimeObjectMarshaller.ConvertToManaged(parameter)); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs index 5d5b8d1a5..bdd5388bd 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/AsyncActionCompletedHandler.cs @@ -229,9 +229,9 @@ private static HRESULT Invoke(void* thisPtr, void* asyncInfo, AsyncStatus asyncS try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue(IAsyncActionMarshaller.ConvertToManaged(asyncInfo)!, asyncStatus); + thisObject(IAsyncActionMarshaller.ConvertToManaged(asyncInfo)!, asyncStatus); return WellKnownErrorCodes.S_OK; } @@ -298,9 +298,9 @@ private static HRESULT get_Value(void* thisPtr, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = AsyncActionCompletedHandlerMarshaller.ConvertToUnmanaged(unboxedValue).DetachThisPtrUnsafe(); + *result = AsyncActionCompletedHandlerMarshaller.ConvertToUnmanaged(thisObject).DetachThisPtrUnsafe(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs index 39546c8b1..ad9fdc704 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/Collections/IVectorChangedEventArgs.cs @@ -135,9 +135,9 @@ private static HRESULT get_CollectionChange(void* thisPtr, CollectionChange* res { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = unboxedValue.CollectionChange; + *result = thisObject.CollectionChange; return WellKnownErrorCodes.S_OK; } @@ -153,9 +153,9 @@ private static HRESULT get_Index(void* thisPtr, uint* result) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *result = unboxedValue.Index; + *result = thisObject.Index; return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs index ccf338616..97f9ffab1 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncAction.cs @@ -215,9 +215,9 @@ private static HRESULT get_Completed(void* thisPtr, void** handler) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *handler = AsyncActionCompletedHandlerMarshaller.ConvertToUnmanaged(unboxedValue.Completed).DetachThisPtrUnsafe(); + *handler = AsyncActionCompletedHandlerMarshaller.ConvertToUnmanaged(thisObject.Completed).DetachThisPtrUnsafe(); return WellKnownErrorCodes.S_OK; } @@ -233,9 +233,9 @@ private static HRESULT set_Completed(void* thisPtr, void* handler) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue.Completed = AsyncActionCompletedHandlerMarshaller.ConvertToManaged(handler); + thisObject.Completed = AsyncActionCompletedHandlerMarshaller.ConvertToManaged(handler); return WellKnownErrorCodes.S_OK; } @@ -251,9 +251,9 @@ private static HRESULT GetResults(void* thisPtr) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue.GetResults(); + thisObject.GetResults(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs index c4f6832db..58a2a514d 100644 --- a/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs +++ b/src/WinRT.Runtime2/ABI/Windows.Foundation/IAsyncInfo.cs @@ -189,9 +189,9 @@ private static HRESULT get_ErrorCode(void* thisPtr, System.Exception* errorCode) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *errorCode = System.ExceptionMarshaller.ConvertToUnmanaged(unboxedValue.ErrorCode); + *errorCode = System.ExceptionMarshaller.ConvertToUnmanaged(thisObject.ErrorCode); return WellKnownErrorCodes.S_OK; } @@ -212,9 +212,9 @@ private static HRESULT get_Id(void* thisPtr, uint* id) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *id = unboxedValue.Id; + *id = thisObject.Id; return WellKnownErrorCodes.S_OK; } @@ -235,9 +235,9 @@ private static HRESULT get_Status(void* thisPtr, AsyncStatus* status) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *status = unboxedValue.Status; + *status = thisObject.Status; return WellKnownErrorCodes.S_OK; } @@ -253,9 +253,9 @@ private static HRESULT Cancel(void* thisPtr) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue.Cancel(); + thisObject.Cancel(); return WellKnownErrorCodes.S_OK; } @@ -271,9 +271,9 @@ private static HRESULT Close(void* thisPtr) { try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - unboxedValue.Close(); + thisObject.Close(); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/ABI/WindowsRuntime.InteropServices/Bindables/IBindableIReadOnlyListAdapter.cs b/src/WinRT.Runtime2/ABI/WindowsRuntime.InteropServices/Bindables/IBindableIReadOnlyListAdapter.cs index f7cfe892a..8c4b8ff7c 100644 --- a/src/WinRT.Runtime2/ABI/WindowsRuntime.InteropServices/Bindables/IBindableIReadOnlyListAdapter.cs +++ b/src/WinRT.Runtime2/ABI/WindowsRuntime.InteropServices/Bindables/IBindableIReadOnlyListAdapter.cs @@ -151,9 +151,9 @@ private static HRESULT GetAt(void* thisPtr, uint index, void** result) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - object? item = unboxedValue.GetAt(index); + object? item = thisObject.GetAt(index); *result = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(item).DetachThisPtrUnsafe(); @@ -176,9 +176,9 @@ private static HRESULT get_Size(void* thisPtr, uint* size) try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *size = unboxedValue.Size; + *size = thisObject.Size; return WellKnownErrorCodes.S_OK; } @@ -199,11 +199,11 @@ private static HRESULT IndexOf(void* thisPtr, void* value, uint* index, bool* re try { - var unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + var thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); object? target = WindowsRuntimeObjectMarshaller.ConvertToManaged(value); - *result = unboxedValue.IndexOf(target, out *index); + *result = thisObject.IndexOf(target, out *index); return WellKnownErrorCodes.S_OK; } diff --git a/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IPropertyValueImpl.InspectableArray.cs b/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IPropertyValueImpl.InspectableArray.cs index ee97dbbf0..3db035ce5 100644 --- a/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IPropertyValueImpl.InspectableArray.cs +++ b/src/WinRT.Runtime2/InteropServices/ProjectionImpls/IPropertyValueImpl.InspectableArray.cs @@ -109,21 +109,21 @@ internal static HRESULT GetInspectableArray(void* thisPtr, int* size, void*** va try { - object[] unboxedValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); + object[] thisObject = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)thisPtr); - *size = unboxedValue.Length; + *size = thisObject.Length; // Try to create and initialize the array locally first, we'll transfer it in case we succeed - void** arrayPtr = (void**)Marshal.AllocCoTaskMem(unboxedValue.Length * sizeof(void*)); + void** arrayPtr = (void**)Marshal.AllocCoTaskMem(thisObject.Length * sizeof(void*)); int i = 0; bool success = false; try { // Marshal all elements in the managed array - for (; i < unboxedValue.Length; i++) + for (; i < thisObject.Length; i++) { - arrayPtr[i] = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(unboxedValue[i]).DetachThisPtrUnsafe(); + arrayPtr[i] = WindowsRuntimeObjectMarshaller.ConvertToUnmanaged(thisObject[i]).DetachThisPtrUnsafe(); } success = true; From 51894bc2c68d97192555bf1001f8bbab133d796d Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 24 Dec 2025 18:11:13 -0800 Subject: [PATCH 04/13] Add GetAt method for IReadOnlyList interop Introduces a factory for generating the GetAt method implementation for IReadOnlyList interop types. Updates the type builder to include the generated GetAt method in the vtable, and extends InteropReferences with support for IReadOnlyListAdapter and its GetAt method reference. --- ...ropTypeDefinitionBuilder.IReadOnlyList1.cs | 9 +- ...hodDefinitionFactory.IReadOnlyList1Impl.cs | 132 ++++++++++++++++++ .../References/InteropReferences.cs | 21 +++ 3 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index af61f50d6..6bea07cfa 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -426,6 +426,13 @@ public static void ImplType( ModuleDefinition module, out TypeDefinition implType) { + // Define the 'GetAt' method + MethodDefinition getAtMethod = InteropMethodDefinitionFactory.IReadOnlyList1Impl.GetAt( + readOnlyListType: readOnlyListType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + Impl( interfaceType: ComInterfaceType.InterfaceIsIInspectable, ns: InteropUtf8NameFactory.TypeNamespace(readOnlyListType), @@ -435,7 +442,7 @@ public static void ImplType( interopReferences: interopReferences, module: module, implType: out implType, - vtableMethods: []); + vtableMethods: [getAtMethod]); // Track the type (it may be needed by COM interface entries for user-defined types) emitState.TrackTypeDefinition(implType, readOnlyListType, "Impl"); diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs new file mode 100644 index 000000000..ae08b4d62 --- /dev/null +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -0,0 +1,132 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using AsmResolver.DotNet; +using AsmResolver.DotNet.Code.Cil; +using AsmResolver.DotNet.Signatures; +using AsmResolver.PE.DotNet.Cil; +using AsmResolver.PE.DotNet.Metadata.Tables; +using WindowsRuntime.InteropGenerator.Generation; +using WindowsRuntime.InteropGenerator.References; +using static AsmResolver.PE.DotNet.Cil.CilOpCodes; + +#pragma warning disable IDE1006 + +namespace WindowsRuntime.InteropGenerator.Factories; + +/// +/// A factory for interop method definitions. +/// +internal static partial class InteropMethodDefinitionFactory +{ + /// + /// Helpers for impl types for interfaces. + /// + public static class IReadOnlyList1Impl + { + /// + /// Creates a for the GetAt export method. + /// + /// The for the type. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static MethodDefinition GetAt( + GenericInstanceTypeSignature readOnlyListType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = readOnlyListType.TypeArguments[0]; + + // Define the 'GetAt' method as follows: + // + // [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] + // private static int GetAt(void* thisPtr, uint index, * result) + MethodDefinition getAtMethod = new( + name: "GetAt"u8, + attributes: MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Int32, + parameterTypes: [ + module.CorLibTypeFactory.Void.MakePointerType(), + module.CorLibTypeFactory.UInt32, + elementType.GetAbiType(interopReferences).Import(module).MakePointerType()])) + { + CustomAttributes = { InteropCustomAttributeFactory.UnmanagedCallersOnly(interopReferences, module) } + }; + + // Declare the local variables: + // [0]: '' (for 'thisObject') + // [1]: 'int' (the 'HRESULT' to return) + CilLocalVariable loc_0_thisObject = new(readOnlyListType.Import(module)); + CilLocalVariable loc_1_hresult = new(module.CorLibTypeFactory.Int32); + + // Labels for jumps + CilInstruction nop_beforeTry = new(Nop); + CilInstruction ldarg_0_tryStart = new(Ldarg_0); + CilInstruction ldloc_1_returnHResult = new(Ldloc_1); + CilInstruction call_catchStartMarshalException = new(Call, interopReferences.RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged.Import(module)); + CilInstruction nop_convertToUnmanaged = new(Nop); + + // Create a method body for the 'GetAt' method + getAtMethod.CilMethodBody = new CilMethodBody() + { + LocalVariables = { loc_0_thisObject, loc_1_hresult }, + Instructions = + { + // Return 'E_POINTER' if the argument is 'null' + { Ldarg_2 }, + { Ldc_I4_0 }, + { Conv_U }, + { Bne_Un_S, nop_beforeTry.CreateLabel() }, + { Ldc_I4, unchecked((int)0x80004003) }, + { Ret }, + { nop_beforeTry }, + + // '.try' code + { ldarg_0_tryStart }, + { Call, interopReferences.ComInterfaceDispatchGetInstance.MakeGenericInstanceMethod(readOnlyListType).Import(module) }, + { Stloc_0 }, + { Ldarg_2 }, + { Ldloc_0 }, + { Ldarg_1 }, + { Call, interopReferences.IReadOnlyListAdapter1GetAt(elementType).Import(module) }, + { nop_convertToUnmanaged }, + { Ldc_I4_0 }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // '.catch' code + { call_catchStartMarshalException }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // Return the 'HRESULT' from location [1] + { ldloc_1_returnHResult }, + { Ret } + }, + ExceptionHandlers = + { + new CilExceptionHandler + { + HandlerType = CilExceptionHandlerType.Exception, + TryStart = ldarg_0_tryStart.CreateLabel(), + TryEnd = call_catchStartMarshalException.CreateLabel(), + HandlerStart = call_catchStartMarshalException.CreateLabel(), + HandlerEnd = ldloc_1_returnHResult.CreateLabel(), + ExceptionType = interopReferences.Exception.Import(module) + } + } + }; + + // Track the method for rewrite to marshal the result value + emitState.TrackRetValValueMethodRewrite( + retValType: elementType, + method: getAtMethod, + marker: nop_convertToUnmanaged); + + return getAtMethod; + } + } +} \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 797a43b9c..51d57e775 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -658,6 +658,11 @@ public InteropReferences( /// public TypeReference IListMethods1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IListMethods`1"u8); + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>. + /// + public TypeReference IReadOnlyListAdapter1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyListAdapter`1"u8); + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>. /// @@ -3054,6 +3059,22 @@ public MethodSpecification IListMethods1Insert(TypeSignature elementType, TypeDe .MakeGenericInstanceMethod(vectorMethods.ToReferenceTypeSignature()); } + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>.GetAt. + /// + /// The input element type. + public MemberReference IReadOnlyListAdapter1GetAt(TypeSignature elementType) + { + return IReadOnlyListAdapter1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("GetAt"u8, MethodSignature.CreateStatic( + returnType: new GenericParameterSignature(GenericParameterType.Type, 0), + parameterTypes: [ + IReadOnlyList1.MakeGenericReferenceType(elementType), + _corLibTypeFactory.UInt32])); + } + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>.Item. /// From ceb512a26eb2005c2d3eed9523682287185a74fb Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Wed, 24 Dec 2025 18:28:01 -0800 Subject: [PATCH 05/13] Add get_Size method to IReadOnlyList interop Introduces the get_Size method for IReadOnlyList interop, including its definition in the generator, factory, and references. Also renames the Count method to Size in IReadOnlyListAdapter to match the interop signature. --- ...ropTypeDefinitionBuilder.IReadOnlyList1.cs | 10 +- ...hodDefinitionFactory.IReadOnlyList1Impl.cs | 94 +++++++++++++++++++ .../References/InteropReferences.cs | 14 +++ .../Collections/IReadOnlyListAdapter{T}.cs | 2 +- 4 files changed, 118 insertions(+), 2 deletions(-) diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index 6bea07cfa..fd03a58d2 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -433,6 +433,12 @@ public static void ImplType( emitState: emitState, module: module); + // Define the 'get_Size' method + MethodDefinition sizeMethod = InteropMethodDefinitionFactory.IReadOnlyList1Impl.get_Size( + readOnlyListType: readOnlyListType, + interopReferences: interopReferences, + module: module); + Impl( interfaceType: ComInterfaceType.InterfaceIsIInspectable, ns: InteropUtf8NameFactory.TypeNamespace(readOnlyListType), @@ -442,7 +448,9 @@ public static void ImplType( interopReferences: interopReferences, module: module, implType: out implType, - vtableMethods: [getAtMethod]); + vtableMethods: [ + getAtMethod, + sizeMethod]); // Track the type (it may be needed by COM interface entries for user-defined types) emitState.TrackTypeDefinition(implType, readOnlyListType, "Impl"); diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index ae08b4d62..fc0fc7594 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -128,5 +128,99 @@ public static MethodDefinition GetAt( return getAtMethod; } + + /// + /// Creates a for the get_Size export method. + /// + /// The for the type. + /// The instance to use. + /// The interop module being built. + public static MethodDefinition get_Size( + GenericInstanceTypeSignature readOnlyListType, + InteropReferences interopReferences, + ModuleDefinition module) + { + TypeSignature elementType = readOnlyListType.TypeArguments[0]; + + // Define the 'get_Size' method as follows: + // + // [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] + // private static int get_Size(void* thisPtr, uint* result) + MethodDefinition sizeMethod = new( + name: "get_Size"u8, + attributes: MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Int32, + parameterTypes: [ + module.CorLibTypeFactory.Void.MakePointerType(), + module.CorLibTypeFactory.UInt32.MakePointerType()])) + { + CustomAttributes = { InteropCustomAttributeFactory.UnmanagedCallersOnly(interopReferences, module) } + }; + + // Declare the local variables: + // [0]: '' (for 'thisObject') + // [1]: 'int' (the 'HRESULT' to return) + CilLocalVariable loc_0_thisObject = new(readOnlyListType.Import(module)); + CilLocalVariable loc_1_hresult = new(module.CorLibTypeFactory.Int32); + + // Labels for jumps + CilInstruction nop_beforeTry = new(Nop); + CilInstruction ldarg_0_tryStart = new(Ldarg_0); + CilInstruction ldloc_1_returnHResult = new(Ldloc_1); + CilInstruction call_catchStartMarshalException = new(Call, interopReferences.RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged.Import(module)); + + // Create a method body for the 'get_Size' method + sizeMethod.CilMethodBody = new CilMethodBody() + { + LocalVariables = { loc_0_thisObject, loc_1_hresult }, + Instructions = + { + // Return 'E_POINTER' if the argument is 'null' + { Ldarg_1 }, + { Ldc_I4_0 }, + { Conv_U }, + { Bne_Un_S, nop_beforeTry.CreateLabel() }, + { Ldc_I4, unchecked((int)0x80004003) }, + { Ret }, + { nop_beforeTry }, + + // '.try' code + { ldarg_0_tryStart }, + { Call, interopReferences.ComInterfaceDispatchGetInstance.MakeGenericInstanceMethod(readOnlyListType).Import(module) }, + { Stloc_0 }, + { Ldarg_1 }, + { Ldloc_0 }, + { Call, interopReferences.IReadOnlyListAdapter1Size(elementType).Import(module) }, + { Stind_I4 }, + { Ldc_I4_0 }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // '.catch' code + { call_catchStartMarshalException }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // Return the 'HRESULT' from location [1] + { ldloc_1_returnHResult }, + { Ret } + }, + ExceptionHandlers = + { + new CilExceptionHandler + { + HandlerType = CilExceptionHandlerType.Exception, + TryStart = ldarg_0_tryStart.CreateLabel(), + TryEnd = call_catchStartMarshalException.CreateLabel(), + HandlerStart = call_catchStartMarshalException.CreateLabel(), + HandlerEnd = ldloc_1_returnHResult.CreateLabel(), + ExceptionType = interopReferences.Exception.Import(module) + } + } + }; + + return sizeMethod; + } } } \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 51d57e775..7ebc635e0 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -3075,6 +3075,20 @@ public MemberReference IReadOnlyListAdapter1GetAt(TypeSignature elementType) _corLibTypeFactory.UInt32])); } + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>.Size. + /// + /// The input element type. + public MemberReference IReadOnlyListAdapter1Size(TypeSignature elementType) + { + return IReadOnlyListAdapter1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("Size"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.UInt32, + parameterTypes: [IReadOnlyList1.MakeGenericReferenceType(elementType)])); + } + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>.Item. /// diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs index b862d767e..58ad9c088 100644 --- a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs +++ b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapter{T}.cs @@ -49,7 +49,7 @@ public static T GetAt(IReadOnlyList list, uint index) /// The number of items in the vector view. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static uint Count(IReadOnlyList list) + public static uint Size(IReadOnlyList list) { return (uint)list.Count; } From b6e718586956ae5eda3d5d1d173e2a29e4c02215 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 20:49:02 -0800 Subject: [PATCH 06/13] Add IndexOf method to IReadOnlyList interop Introduces support for the IndexOf method in the IReadOnlyList COM interop implementation. This includes the method definition, its factory logic, and a new reference accessor for IndexOf in InteropReferences. --- ...ropTypeDefinitionBuilder.IReadOnlyList1.cs | 10 +- ...hodDefinitionFactory.IReadOnlyList1Impl.cs | 113 ++++++++++++++++++ .../References/InteropReferences.cs | 17 +++ 3 files changed, 139 insertions(+), 1 deletion(-) diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index fd03a58d2..92a66b521 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -439,6 +439,13 @@ public static void ImplType( interopReferences: interopReferences, module: module); + // Define the 'IndexOf' method + MethodDefinition indexOfMethod = InteropMethodDefinitionFactory.IReadOnlyList1Impl.IndexOf( + readOnlyListType: readOnlyListType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + Impl( interfaceType: ComInterfaceType.InterfaceIsIInspectable, ns: InteropUtf8NameFactory.TypeNamespace(readOnlyListType), @@ -450,7 +457,8 @@ public static void ImplType( implType: out implType, vtableMethods: [ getAtMethod, - sizeMethod]); + sizeMethod, + indexOfMethod]); // Track the type (it may be needed by COM interface entries for user-defined types) emitState.TrackTypeDefinition(implType, readOnlyListType, "Impl"); diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index fc0fc7594..33e7cbf2b 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -222,5 +222,118 @@ public static MethodDefinition get_Size( return sizeMethod; } + + /// + /// Creates a for the IndexOf export method. + /// + /// The for the type. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static MethodDefinition IndexOf( + GenericInstanceTypeSignature readOnlyListType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = readOnlyListType.TypeArguments[0]; + + // Define the 'IndexOf' method as follows: + // + // [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] + // private static int IndexOf(void* thisPtr, value, uint* index, bool* result) + MethodDefinition indexOfMethod = new( + name: "IndexOf"u8, + attributes: MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Int32, + parameterTypes: [ + module.CorLibTypeFactory.Void.MakePointerType(), + elementType.GetAbiType(interopReferences).Import(module), + module.CorLibTypeFactory.UInt32.MakePointerType(), + module.CorLibTypeFactory.Boolean.MakePointerType()])) + { + CustomAttributes = { InteropCustomAttributeFactory.UnmanagedCallersOnly(interopReferences, module) } + }; + + // Declare the local variables: + // [0]: '' (for 'thisObject') + // [1]: 'int' (the 'HRESULT' to return) + CilLocalVariable loc_0_thisObject = new(readOnlyListType.Import(module)); + CilLocalVariable loc_1_hresult = new(module.CorLibTypeFactory.Int32); + + // Labels for jumps + CilInstruction ldc_i4_e_pointer = new(Ldc_I4, unchecked((int)0x80004003)); + CilInstruction nop_beforeTry = new(Nop); + CilInstruction ldarg_0_tryStart = new(Ldarg_0); + CilInstruction nop_parameter1Rewrite = new(Nop); + CilInstruction ldloc_1_returnHResult = new(Ldloc_1); + CilInstruction call_catchStartMarshalException = new(Call, interopReferences.RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged.Import(module)); + + // Create a method body for the 'IndexOf' method + indexOfMethod.CilMethodBody = new CilMethodBody() + { + LocalVariables = { loc_0_thisObject, loc_1_hresult }, + Instructions = + { + // Return 'E_POINTER' if either argument is 'null' + { Ldarg_2 }, + { Ldc_I4_0 }, + { Conv_U }, + { Beq_S, ldc_i4_e_pointer.CreateLabel() }, + { Ldarg_2 }, + { Ldc_I4_0 }, + { Conv_U }, + { Bne_Un_S, nop_beforeTry.CreateLabel() }, + { ldc_i4_e_pointer }, + { Ret }, + { nop_beforeTry }, + + // '.try' code + { ldarg_0_tryStart }, + { Call, interopReferences.ComInterfaceDispatchGetInstance.MakeGenericInstanceMethod(readOnlyListType).Import(module) }, + { Stloc_0 }, + { Ldarg_3 }, + { Ldloc_0 }, + { nop_parameter1Rewrite }, + { Ldarg_2 }, + { Call, interopReferences.IReadOnlyListAdapter1IndexOf(elementType).Import(module) }, + { Stind_I1 }, + { Ldc_I4_0 }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // '.catch' code + { call_catchStartMarshalException }, + { Stloc_1 }, + { Leave_S, ldloc_1_returnHResult.CreateLabel() }, + + // Return the 'HRESULT' from location [1] + { ldloc_1_returnHResult }, + { Ret } + }, + ExceptionHandlers = + { + new CilExceptionHandler + { + HandlerType = CilExceptionHandlerType.Exception, + TryStart = ldarg_0_tryStart.CreateLabel(), + TryEnd = call_catchStartMarshalException.CreateLabel(), + HandlerStart = call_catchStartMarshalException.CreateLabel(), + HandlerEnd = ldloc_1_returnHResult.CreateLabel(), + ExceptionType = interopReferences.Exception.Import(module) + } + } + }; + + // Track rewriting the two parameters for this method + emitState.TrackManagedParameterMethodRewrite( + paraneterType: elementType, + method: indexOfMethod, + marker: nop_parameter1Rewrite, + parameterIndex: 1); + + return indexOfMethod; + } } } \ No newline at end of file diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 7ebc635e0..9a225e546 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -3075,6 +3075,23 @@ public MemberReference IReadOnlyListAdapter1GetAt(TypeSignature elementType) _corLibTypeFactory.UInt32])); } + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>.IndexOf. + /// + /// The input element type. + public MemberReference IReadOnlyListAdapter1IndexOf(TypeSignature elementType) + { + return IReadOnlyListAdapter1 + .MakeGenericReferenceType(elementType) + .ToTypeDefOrRef() + .CreateMemberReference("IndexOf"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Boolean, + parameterTypes: [ + IReadOnlyList1.MakeGenericReferenceType(elementType), + new GenericParameterSignature(GenericParameterType.Type, 0), + _corLibTypeFactory.UInt32.MakeByReferenceType()])); + } + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>.Size. /// From 6c010a53466c1c807805fcd7736f62c4fbf38720 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 20:57:43 -0800 Subject: [PATCH 07/13] Add support for marshalling ReadOnlySpan Introduces handling for 'ReadOnlySpan' parameters in interop method rewriting, using 'HStringMarshaller.ConvertToManagedUnsafe' for marshalling without materializing a string object. Also adds a reference to the new marshaller method in InteropReferences. --- .../InteropMethodRewriteFactory.ManagedParameter.cs | 7 +++++++ .../References/InteropReferences.cs | 8 ++++++++ 2 files changed, 15 insertions(+) diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs index f4644c925..3feba88bb 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodRewriteFactory.ManagedParameter.cs @@ -85,6 +85,13 @@ public static void RewriteMethod( CilInstruction.CreateLdarg(parameterIndex), new CilInstruction(Call, marshallerType.UnboxToManaged().Import(module))]); } + else if (SignatureComparer.IgnoreVersion.Equals(parameterType, interopReferences.ReadOnlySpanChar)) + { + // When marshalling 'ReadOnlySpan' values, we also use 'HStringMarshaller', but without materializing the 'string' object + body.Instructions.ReferenceReplaceRange(marker, [ + CilInstruction.CreateLdarg(parameterIndex), + new CilInstruction(Call, interopReferences.HStringMarshallerConvertToManagedUnsafe.Import(module))]); + } else { // The last case handles all other value types. It doesn't matter if they possibly hold some unmanaged diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 9a225e546..13219c85c 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -1845,6 +1845,14 @@ public InteropReferences( returnType: _corLibTypeFactory.String, parameterTypes: [_corLibTypeFactory.Void.MakePointerType()])); + /// + /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller.ConvertToManagedUnsafe. + /// + public MemberReference HStringMarshallerConvertToManagedUnsafe => field ??= HStringMarshaller + .CreateMemberReference("ConvertToManagedUnsafe"u8, MethodSignature.CreateStatic( + returnType: ReadOnlySpanChar, + parameterTypes: [_corLibTypeFactory.Void.MakePointerType()])); + /// /// Gets the for WindowsRuntime.InteropServices.HStringMarshaller.Free. /// From f1278895a58853875e3995b2b1e3ef31a01f1bcd Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 20:57:58 -0800 Subject: [PATCH 08/13] Optimize IReadOnlyList.IndexOf interop handling Refactors the interop method generation for IReadOnlyList.IndexOf to use a specialized method for string element types, leveraging ReadOnlySpan to avoid allocations. Adds new references and logic to support this optimization in the interop references and method body generation. --- ...hodDefinitionFactory.IReadOnlyList1Impl.cs | 14 ++++++++++++-- .../References/InteropReferences.cs | 19 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index 33e7cbf2b..19917de81 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -270,6 +270,11 @@ public static MethodDefinition IndexOf( CilInstruction ldloc_1_returnHResult = new(Ldloc_1); CilInstruction call_catchStartMarshalException = new(Call, interopReferences.RestrictedErrorInfoExceptionMarshallerConvertToUnmanaged.Import(module)); + // Get the target 'IndexOf' method (we can optimize for 'string' types) + MemberReference adapterIndexOfMethod = elementType.IsTypeOfString() + ? interopReferences.IReadOnlyListAdapterOfStringIndexOf() + : interopReferences.IReadOnlyListAdapter1IndexOf(elementType); + // Create a method body for the 'IndexOf' method indexOfMethod.CilMethodBody = new CilMethodBody() { @@ -297,7 +302,7 @@ public static MethodDefinition IndexOf( { Ldloc_0 }, { nop_parameter1Rewrite }, { Ldarg_2 }, - { Call, interopReferences.IReadOnlyListAdapter1IndexOf(elementType).Import(module) }, + { Call, adapterIndexOfMethod.Import(module) }, { Stind_I1 }, { Ldc_I4_0 }, { Stloc_1 }, @@ -326,9 +331,14 @@ public static MethodDefinition IndexOf( } }; + // If the element type is 'string', we use 'ReadOnlySpan' to avoid an allocation + TypeSignature parameterType = elementType.IsTypeOfString() + ? interopReferences.ReadOnlySpanChar + : elementType; + // Track rewriting the two parameters for this method emitState.TrackManagedParameterMethodRewrite( - paraneterType: elementType, + paraneterType: parameterType, method: indexOfMethod, marker: nop_parameter1Rewrite, parameterIndex: 1); diff --git a/src/WinRT.Interop.Generator/References/InteropReferences.cs b/src/WinRT.Interop.Generator/References/InteropReferences.cs index 13219c85c..36fa36124 100644 --- a/src/WinRT.Interop.Generator/References/InteropReferences.cs +++ b/src/WinRT.Interop.Generator/References/InteropReferences.cs @@ -663,6 +663,11 @@ public InteropReferences( /// public TypeReference IReadOnlyListAdapter1 => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyListAdapter`1"u8); + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapterExtensions. + /// + public TypeReference IReadOnlyListAdapterExtensions => field ??= _windowsRuntimeModule.CreateTypeReference("WindowsRuntime.InteropServices"u8, "IReadOnlyListAdapterExtensions"u8); + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListMethods<T>. /// @@ -3100,6 +3105,20 @@ public MemberReference IReadOnlyListAdapter1IndexOf(TypeSignature elementType) _corLibTypeFactory.UInt32.MakeByReferenceType()])); } + /// + /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<string>.IndexOf. + /// + public MemberReference IReadOnlyListAdapterOfStringIndexOf() + { + return IReadOnlyListAdapterExtensions + .CreateMemberReference("IndexOf"u8, MethodSignature.CreateStatic( + returnType: _corLibTypeFactory.Boolean, + parameterTypes: [ + IReadOnlyList1.MakeGenericReferenceType(_corLibTypeFactory.String), + ReadOnlySpanChar, + _corLibTypeFactory.UInt32.MakeByReferenceType()])); + } + /// /// Gets the for WindowsRuntime.InteropServices.IReadOnlyListAdapter<T>.Size. /// From 558d03ab7d41282d001f292184ad6e3283f8e454 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 21:17:35 -0800 Subject: [PATCH 09/13] Fix GetMany signature in IVector and IVectorView vtables Removed an extra uint parameter from the GetMany method signatures in IVectorVftbl and IVectorViewVftbl, and updated WellKnownTypeSignatureFactory to match. This corrects the method signature to align with the expected delegate definition. --- .../Factories/WellKnownTypeSignatureFactory.cs | 5 ++--- src/WinRT.Runtime2/InteropServices/Vtables/IVectorVftbl.cs | 2 +- .../InteropServices/Vtables/IVectorViewVftbl.cs | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs b/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs index 9cd443c9f..9852748df 100644 --- a/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs +++ b/src/WinRT.Interop.Generator/Factories/WellKnownTypeSignatureFactory.cs @@ -394,7 +394,7 @@ public static MethodSignature IReadOnlyList1IndexOfImpl(TypeSignature elementTyp /// The resulting instance. public static MethodSignature IReadOnlyList1GetManyImpl(TypeSignature elementType, InteropReferences interopReferences) { - // Signature for 'delegate* unmanaged[MemberFunction]*, uint*, HRESULT> GetMany' + // Signature for 'delegate* unmanaged[MemberFunction]*, uint*, HRESULT> GetMany' return new( attributes: CallingConventionAttributes.Unmanaged, returnType: new CustomModifierTypeSignature( @@ -404,7 +404,6 @@ public static MethodSignature IReadOnlyList1GetManyImpl(TypeSignature elementTyp parameterTypes: [ interopReferences.CorLibTypeFactory.Void.MakePointerType(), interopReferences.CorLibTypeFactory.UInt32, - interopReferences.CorLibTypeFactory.UInt32, elementType.MakePointerType(), interopReferences.CorLibTypeFactory.UInt32.MakePointerType()]); } @@ -583,7 +582,7 @@ public static MethodSignature IList1ClearImpl(InteropReferences interopReference /// The resulting instance. public static MethodSignature IList1GetManyImpl(TypeSignature elementType, InteropReferences interopReferences) { - // Signature for 'delegate* unmanaged[MemberFunction]*, uint*, HRESULT> GetMany'. + // Signature for 'delegate* unmanaged[MemberFunction]*, uint*, HRESULT> GetMany'. // This is the same as 'IVectorView.GetMany', so we can reuse that one here (like the methods above). return IReadOnlyList1GetManyImpl(elementType, interopReferences); } diff --git a/src/WinRT.Runtime2/InteropServices/Vtables/IVectorVftbl.cs b/src/WinRT.Runtime2/InteropServices/Vtables/IVectorVftbl.cs index 303cabe49..7f0150e3f 100644 --- a/src/WinRT.Runtime2/InteropServices/Vtables/IVectorVftbl.cs +++ b/src/WinRT.Runtime2/InteropServices/Vtables/IVectorVftbl.cs @@ -32,6 +32,6 @@ internal unsafe struct IVectorVftbl public delegate* unmanaged[MemberFunction] Append; public delegate* unmanaged[MemberFunction] RemoveAtEnd; public delegate* unmanaged[MemberFunction] Clear; - public delegate* unmanaged[MemberFunction] GetMany; + public delegate* unmanaged[MemberFunction] GetMany; public delegate* unmanaged[MemberFunction] ReplaceAll; } \ No newline at end of file diff --git a/src/WinRT.Runtime2/InteropServices/Vtables/IVectorViewVftbl.cs b/src/WinRT.Runtime2/InteropServices/Vtables/IVectorViewVftbl.cs index 52e4d415b..1a7952888 100644 --- a/src/WinRT.Runtime2/InteropServices/Vtables/IVectorViewVftbl.cs +++ b/src/WinRT.Runtime2/InteropServices/Vtables/IVectorViewVftbl.cs @@ -28,5 +28,5 @@ internal unsafe struct IVectorViewVftbl // does not matter, since this vtable slot is never actually used within this assembly. It is only // used from 'WinRT.Interop.dll', which will emit specialized vtable types when necessary. public delegate* unmanaged[MemberFunction] IndexOf; - public delegate* unmanaged[MemberFunction] GetMany; + public delegate* unmanaged[MemberFunction] GetMany; } \ No newline at end of file From c5426ddae44c8da21dc9b7a79bcd45dddb87b8c3 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 21:22:04 -0800 Subject: [PATCH 10/13] Add 'GetMany' method to IReadOnlyList interop implementation Introduces the 'GetMany' method to the IReadOnlyList interop implementation, including its definition and integration into the vtable. This supports additional COM interop scenarios requiring bulk retrieval of elements. --- ...ropTypeDefinitionBuilder.IReadOnlyList1.cs | 10 +++- ...hodDefinitionFactory.IReadOnlyList1Impl.cs | 47 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs index 92a66b521..ca474b1ef 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.IReadOnlyList1.cs @@ -446,6 +446,13 @@ public static void ImplType( emitState: emitState, module: module); + // Define the 'GetMany' method + MethodDefinition getManyMethod = InteropMethodDefinitionFactory.IReadOnlyList1Impl.GetMany( + readOnlyListType: readOnlyListType, + interopReferences: interopReferences, + emitState: emitState, + module: module); + Impl( interfaceType: ComInterfaceType.InterfaceIsIInspectable, ns: InteropUtf8NameFactory.TypeNamespace(readOnlyListType), @@ -458,7 +465,8 @@ public static void ImplType( vtableMethods: [ getAtMethod, sizeMethod, - indexOfMethod]); + indexOfMethod, + getManyMethod]); // Track the type (it may be needed by COM interface entries for user-defined types) emitState.TrackTypeDefinition(implType, readOnlyListType, "Impl"); diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index 19917de81..d6f0c7ece 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -345,5 +345,52 @@ public static MethodDefinition IndexOf( return indexOfMethod; } + +#pragma warning disable IDE0017 + /// + /// Creates a for the GetMany export method. + /// + /// The for the type. + /// The instance to use. + /// The emit state for this invocation. + /// The interop module being built. + public static MethodDefinition GetMany( + GenericInstanceTypeSignature readOnlyListType, + InteropReferences interopReferences, + InteropGeneratorEmitState emitState, + ModuleDefinition module) + { + TypeSignature elementType = readOnlyListType.TypeArguments[0]; + + // Define the 'GetMany' method as follows: + // + // [UnmanagedCallersOnly(CallConvs = [typeof(CallConvMemberFunction)])] + // private static int GetMany(void* thisPtr, uint size, * items, uint* result) + MethodDefinition indexOfMethod = new( + name: "GetMany"u8, + attributes: MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.Static, + signature: MethodSignature.CreateStatic( + returnType: module.CorLibTypeFactory.Int32, + parameterTypes: [ + module.CorLibTypeFactory.Void.MakePointerType(), + module.CorLibTypeFactory.UInt32.MakePointerType(), + elementType.GetAbiType(interopReferences).Import(module).MakePointerType(), + module.CorLibTypeFactory.UInt32.MakePointerType()])) + { + CustomAttributes = { InteropCustomAttributeFactory.UnmanagedCallersOnly(interopReferences, module) } + }; + + // Create a method body for the 'GetMany' method + indexOfMethod.CilMethodBody = new CilMethodBody() + { + Instructions = + { + { Ldnull }, + { Throw } // TODO + }, + }; + + return indexOfMethod; + } } } \ No newline at end of file From cf24a2c3426bb9a444f79bb0e310158cb260b782 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Fri, 26 Dec 2025 21:24:41 -0800 Subject: [PATCH 11/13] Fix typo: rename 'paraneterType' to 'parameterType' Corrects the misspelled parameter name 'paraneterType' to 'parameterType' across multiple files for consistency and clarity in method signatures and documentation. --- .../InteropTypeDefinitionBuilder.Delegate.cs | 8 ++++---- .../InteropMethodDefinitionFactory.IMapMethods.cs | 6 +++--- ...InteropMethodDefinitionFactory.IMapViewMethods.cs | 4 ++-- ...eropMethodDefinitionFactory.IReadOnlyList1Impl.cs | 2 +- .../InteropMethodDefinitionFactory.IVectorMethods.cs | 6 +++--- .../Generation/InteropGeneratorEmitState.cs | 12 ++++++------ 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs index 618aa3711..4ca1b85d0 100644 --- a/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs +++ b/src/WinRT.Interop.Generator/Builders/InteropTypeDefinitionBuilder.Delegate.cs @@ -278,13 +278,13 @@ public static void ImplType( // Track rewriting the two parameters for this method emitState.TrackManagedParameterMethodRewrite( - paraneterType: senderType, + parameterType: senderType, method: invokeMethod, marker: nop_parameter1Rewrite, parameterIndex: 1); emitState.TrackManagedParameterMethodRewrite( - paraneterType: argsType, + parameterType: argsType, method: invokeMethod, marker: nop_parameter2Rewrite, parameterIndex: 2); @@ -650,7 +650,7 @@ public static void NativeDelegateType( // Track rewriting the two parameters for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: senderType, + parameterType: senderType, method: invokeMethod, tryMarker: nop_try_sender, loadMarker: nop_ld_sender, @@ -658,7 +658,7 @@ public static void NativeDelegateType( parameterIndex: 1); emitState.TrackNativeParameterMethodRewrite( - paraneterType: argsType, + parameterType: argsType, method: invokeMethod, tryMarker: nop_try_args, loadMarker: nop_ld_args, diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapMethods.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapMethods.cs index 7e5baa419..6e566a2f3 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapMethods.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapMethods.cs @@ -137,7 +137,7 @@ public static MethodDefinition Insert( // Track rewriting the two parameters for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: keyType, + parameterType: keyType, method: insertMethod, tryMarker: nop_try_key, loadMarker: nop_ld_key, @@ -145,7 +145,7 @@ public static MethodDefinition Insert( parameterIndex: 1); emitState.TrackNativeParameterMethodRewrite( - paraneterType: valueType, + parameterType: valueType, method: insertMethod, tryMarker: nop_try_value, loadMarker: nop_ld_value, @@ -259,7 +259,7 @@ public static MethodDefinition Remove( // Track rewriting the return value for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: keyType, + parameterType: keyType, method: removeMethod, tryMarker: nop_try_key, loadMarker: nop_ld_key, diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapViewMethods.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapViewMethods.cs index eb60e9ed6..9040c993b 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapViewMethods.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IMapViewMethods.cs @@ -130,7 +130,7 @@ public static MethodDefinition HasKey( // Track rewriting the return value for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: keyType, + parameterType: keyType, method: hasKeyMethod, tryMarker: nop_try_key, loadMarker: nop_ld_key, @@ -253,7 +253,7 @@ public static MethodDefinition Lookup( // Track rewriting the 'key' parameter for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: keyType, + parameterType: keyType, method: lookupMethod, tryMarker: nop_try_key, loadMarker: nop_ld_key, diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index d6f0c7ece..9b7910520 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -338,7 +338,7 @@ public static MethodDefinition IndexOf( // Track rewriting the two parameters for this method emitState.TrackManagedParameterMethodRewrite( - paraneterType: parameterType, + parameterType: parameterType, method: indexOfMethod, marker: nop_parameter1Rewrite, parameterIndex: 1); diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IVectorMethods.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IVectorMethods.cs index 4a0ed367e..1d8b066ec 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IVectorMethods.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IVectorMethods.cs @@ -174,7 +174,7 @@ public static MethodDefinition Append( // Track rewriting the 'value' parameter for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: elementType, + parameterType: elementType, method: appendMethod, tryMarker: nop_try_value, loadMarker: nop_ld_value, @@ -304,7 +304,7 @@ public static MethodDefinition IndexOf( // Track rewriting the 'value' parameter for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: elementType, + parameterType: elementType, method: indexOfMethod, tryMarker: nop_try_value, loadMarker: nop_ld_value, @@ -418,7 +418,7 @@ private static MethodDefinition SetAtOrInsertAt( // Track rewriting the 'value' parameter for this method emitState.TrackNativeParameterMethodRewrite( - paraneterType: elementType, + parameterType: elementType, method: setAtOrInsertAtMethod, tryMarker: nop_try_value, loadMarker: nop_ld_value, diff --git a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs index 96e09161c..6718ea006 100644 --- a/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs +++ b/src/WinRT.Interop.Generator/Generation/InteropGeneratorEmitState.cs @@ -135,12 +135,12 @@ public void TrackRetValValueMethodRewrite( /// /// Tracks a method rewrite that involves loading a managed parameter in the specified method. /// - /// + /// /// /// /// public void TrackManagedParameterMethodRewrite( - TypeSignature paraneterType, + TypeSignature parameterType, MethodDefinition method, CilInstruction marker, int parameterIndex) @@ -149,7 +149,7 @@ public void TrackManagedParameterMethodRewrite( _methodRewriteInfos.Add(new MethodRewriteInfo.ManagedParameter { - Type = paraneterType, + Type = parameterType, Method = method, Marker = marker, ParameterIndex = parameterIndex @@ -159,14 +159,14 @@ public void TrackManagedParameterMethodRewrite( /// /// Tracks a method rewrite that involves loading a native parameter in the specified method. /// - /// + /// /// /// /// /// /// public void TrackNativeParameterMethodRewrite( - TypeSignature paraneterType, + TypeSignature parameterType, MethodDefinition method, CilInstruction tryMarker, CilInstruction loadMarker, @@ -177,7 +177,7 @@ public void TrackNativeParameterMethodRewrite( _methodRewriteInfos.Add(new MethodRewriteInfo.NativeParameter { - Type = paraneterType, + Type = parameterType, Method = method, TryMarker = tryMarker, Marker = loadMarker, From d139a5bfa5a240ab35775b50f9891b4610facd9f Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 27 Dec 2025 19:41:00 -0800 Subject: [PATCH 12/13] Fix typo in 'IndexOf' method Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Collections/IReadOnlyListAdapterExtensions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs index acfacb2ef..ea1a073fd 100644 --- a/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs +++ b/src/WinRT.Runtime2/InteropServices/Collections/IReadOnlyListAdapterExtensions.cs @@ -28,7 +28,7 @@ public static bool IndexOf(IReadOnlyList list, ReadOnlySpan value, for (int i = 0; i < count; i++) { - if (list[1].SequenceEqual(value)) + if (list[i].SequenceEqual(value)) { index = (uint)i; From 5be243f0b2d6039d41b6e453903dbf44c679b7a4 Mon Sep 17 00:00:00 2001 From: Sergio Pedri Date: Sat, 27 Dec 2025 19:41:13 -0800 Subject: [PATCH 13/13] Fix 'GetMany' impl signature Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs index 9b7910520..a91a51881 100644 --- a/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs +++ b/src/WinRT.Interop.Generator/Factories/InteropMethodDefinitionFactory.IReadOnlyList1Impl.cs @@ -373,7 +373,7 @@ public static MethodDefinition GetMany( returnType: module.CorLibTypeFactory.Int32, parameterTypes: [ module.CorLibTypeFactory.Void.MakePointerType(), - module.CorLibTypeFactory.UInt32.MakePointerType(), + module.CorLibTypeFactory.UInt32, elementType.GetAbiType(interopReferences).Import(module).MakePointerType(), module.CorLibTypeFactory.UInt32.MakePointerType()])) {