From d0806d627284150eafdde3dbfddc56e8bd07e13a Mon Sep 17 00:00:00 2001 From: Andrew Boyarshin Date: Mon, 30 Aug 2021 15:23:02 +0700 Subject: [PATCH 1/5] Fix WinMD handling in System.Reflection.MetadataLoadContext Add a test to prevent regressions --- .../Assemblies/Ecma/EcmaAssembly.Modules.cs | 3 +- .../TypeLoading/General/Ecma/MetadataTable.cs | 9 ++- .../Reflection/TypeLoading/General/Helpers.cs | 2 - .../Modules/Ecma/EcmaModule.MetadataTables.cs | 27 +++++---- .../src/SampleMetadata/SampleMetadata.cs | 2 + .../tests/src/TestUtils/TestData.cs | 58 +++++++++++++++++++ .../tests/src/Tests/Type/TypeTests.cs | 30 ++++++++++ 7 files changed, 113 insertions(+), 18 deletions(-) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs index c7cb4bd3143d8..a8ba4ab7b43c6 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.Modules.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; namespace System.Reflection.TypeLoading.Ecma @@ -81,7 +82,7 @@ protected sealed override IEnumerable GetAssemblyFileInfosFrom AssemblyFile af = h.GetAssemblyFile(reader); if (includeResourceModules || af.ContainsMetadata) { - yield return new AssemblyFileInfo(af.Name.GetString(reader), af.ContainsMetadata, h.GetToken().GetTokenRowNumber()); + yield return new AssemblyFileInfo(af.Name.GetString(reader), af.ContainsMetadata, reader.GetRowNumber(h)); } } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Ecma/MetadataTable.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Ecma/MetadataTable.cs index 9d7e285adb599..ab0ba437503c1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Ecma/MetadataTable.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Ecma/MetadataTable.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Threading; namespace System.Reflection.TypeLoading.Ecma @@ -13,10 +14,8 @@ namespace System.Reflection.TypeLoading.Ecma /// /// The key type is hard-coded to EntityHandle. /// The "T" type is the value type (e.g. RoTypeDefinition objects) - /// The "C" type is an optional context value passed through the factory methods (so we don't to allocate a closure each time.) /// - internal sealed class MetadataTable - where T : class + internal sealed class MetadataTable where T : class { private readonly T?[] _table; @@ -26,12 +25,12 @@ public MetadataTable(int count) _table = new T?[count]; } - public T GetOrAdd(EntityHandle handle, C context, Func factory) + public T GetOrAdd(EntityHandle handle, EcmaModule context, Func factory) { Debug.Assert(!handle.IsNil); Debug.Assert(factory != null); - int index = handle.GetToken().GetTokenRowNumber() - 1; + int index = context.Reader.GetRowNumber(handle) - 1; T?[] table = _table; T? result = Volatile.Read(ref table[index]); if (result != null) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index 2c45856dcf736..777b16f4d00db 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -34,8 +34,6 @@ public static ReadOnlyCollection ToReadOnlyCollection(this IEnumerable return new ReadOnlyCollection(list.ToArray()); } - public static int GetTokenRowNumber(this int token) => token & 0x00ffffff; - public static RoMethod? FilterInheritedAccessor(this RoMethod accessor) { if (accessor.ReflectedType == accessor.DeclaringType) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs index 6463a72aabcc3..42e78fd86f294 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs @@ -12,7 +12,7 @@ namespace System.Reflection.TypeLoading.Ecma /// internal sealed partial class EcmaModule { - internal MetadataTable TypeDefTable + internal MetadataTable TypeDefTable { get { @@ -21,7 +21,7 @@ internal MetadataTable TypeDefTable _lazyTypeDefTable; } } - private volatile MetadataTable? _lazyTypeDefTable; + private volatile MetadataTable? _lazyTypeDefTable; private void EnsureTypeDefTableFullyFilled() { @@ -36,7 +36,7 @@ private void EnsureTypeDefTableFullyFilled() } private bool _typeDefTableFullyFilled; // Only gets set true if EnsureTypeDefTableFullyFilled() fills the table. False negative just means some unnecessary work is done. - internal MetadataTable TypeRefTable + internal MetadataTable TypeRefTable { get { @@ -45,9 +45,9 @@ internal MetadataTable TypeRefTable _lazyTypeRefTable; } } - private volatile MetadataTable? _lazyTypeRefTable; + private volatile MetadataTable? _lazyTypeRefTable; - internal MetadataTable GenericParamTable + internal MetadataTable GenericParamTable { get { @@ -56,9 +56,9 @@ internal MetadataTable GenericParamTable _lazyGenericParamTable; } } - private volatile MetadataTable? _lazyGenericParamTable; + private volatile MetadataTable? _lazyGenericParamTable; - internal MetadataTable AssemblyRefTable + internal MetadataTable AssemblyRefTable { get { @@ -67,11 +67,18 @@ internal MetadataTable AssemblyRefTable _lazyAssemblyRefTable; } } - private volatile MetadataTable? _lazyAssemblyRefTable; + private volatile MetadataTable? _lazyAssemblyRefTable; - private MetadataTable CreateTable(TableIndex tableIndex) where T : class + private MetadataTable CreateTable(TableIndex tableIndex) where T : class { - return new MetadataTable(Reader.GetTableRowCount(tableIndex)); + int rowCount = tableIndex switch + { + // Windows Metadata assemblies contain additional "virtual" AssemblyRefs we need to account for. + // This is the simplest way to get the total AssemblyRefs count: + TableIndex.AssemblyRef => Reader.AssemblyReferences.Count, + _ => Reader.GetTableRowCount(tableIndex) + }; + return new MetadataTable(rowCount); } } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/SampleMetadata/SampleMetadata.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/SampleMetadata/SampleMetadata.cs index 743eb72befdaf..dc452df4a546f 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/SampleMetadata/SampleMetadata.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/SampleMetadata/SampleMetadata.cs @@ -548,4 +548,6 @@ public class ClassWithDefaultMember1 where T : ClassWithDefaultMember1 { public int Yes; } + + public delegate void SampleCompletedHandler(); } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/TestData.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/TestData.cs index 0d6721275be3c..d9d7a54ff39a8 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/TestData.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/TestUtils/TestData.cs @@ -3074,5 +3074,63 @@ internal static class TestData "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + "AAAAAAAAAAAAAAAA"); + + // // Metadata version: WindowsRuntime 1.4 + // .assembly extern mscorlib + // { + // .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. + // .ver 255:255:255:255 + // } + // .assembly windowsruntime Foundation + // { + // .hash algorithm 0x00008004 + // .ver 255:255:255:255 + // } + // .module Foundation.winmd + // .imagebase 0x00400000 + // .file alignment 0x00000200 + // .stackreserve 0x00100000 + // .subsystem 0x0003 // WINDOWS_CUI + // .corflags 0x00000001 // ILONLY + // + // .class public auto ansi windowsruntime sealed Foundation.CompletedHandler + // extends [mscorlib]System.MulticastDelegate + // { + // .method private hidebysig specialname rtspecialname + // instance void .ctor(object 'object', native int 'method') runtime managed + // { + // } // end of method CompletedHandler::.ctor + // + // .method public hidebysig newslot specialname virtual + // instance void Invoke() runtime managed + // { + // } // end of method CompletedHandler::Invoke + // } // end of class Foundation.CompletedHandler + public static readonly string s_MetadataDelegateAssemblyName = "Foundation, Version=255.255.255.255, Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime"; + public static readonly byte[] s_MetadataDelegateImage = Convert.FromBase64String( + "TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFt" + + "IGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAECAHiMLGEAAAAAAAAAAOAAAiELAQsAAAQAAAACAAAAAAAAbiIAAAAgAAAAQAAA" + + "AABAAAAgAAAAAgAABAAAAAAAAAAEAAAAAAAAAABgAAAAAgAAAAAAAAMAQIUAABAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAABgiAABTAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAEAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAACAAAAAAAAAAAAAAA" + + "CCAAAEgAAAAAAAAAAAAAAC50ZXh0AAAAdAIAAAAgAAAABAAAAAIAAAAAAAAAAAAAAAAAACAAAGAucmVsb2MAAAwAAAAAQAAAAAIAAAAGAAAAAAAAAAAAAAAA" + + "AABAAABCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQIgAAAAAAAEgAAAACAAUAUCAAAMgBAAABAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEJTSkIBAAEAAAAAABQAAABXaW5kb3dzUnVudGltZSAxLjQAAAAA" + + "BQB0AAAAtAAAACN+AAAoAQAAdAAAACNTdHJpbmdzAAAAAJwBAAAIAAAAI1VTAKQBAAAQAAAAI0dVSUQAAAC0AQAAFAAAACNCbG9iAAAAAAAAAAIAAAFHAQAA" + + "CQAAAAD6JTMAFgAAAQAAAAEAAAACAAAAAgAAAAIAAAABAAAAAQAAAAAAIwABAAAAAAAGABEACgAAAAAAAQAAAAAAAQABAAFBAAA9AE4ABQABAAEAAAAAAAMA" + + "gRhZAAoAAQAAAAAAAwDGCW0AEAADAAAAAQBfAAAAAgBmAASAAAD/AP8A/wD/AAACAAAAAE4AAAD/AP8A/wD/AAAAAAABADQAAAAAAAAAADxNb2R1bGU+AFN5" + + "c3RlbQBNdWx0aWNhc3REZWxlZ2F0ZQBGb3VuZGF0aW9uLndpbm1kAG1zY29ybGliAENvbXBsZXRlZEhhbmRsZXIARm91bmRhdGlvbgAuY3RvcgBvYmplY3QA" + + "bWV0aG9kAEludm9rZQAAAyAAAAAAAP9GtVt8T4ROg3HdL1tpj4gACLd6XFYZNOCJBSACARwYAyAAAUAiAAAAAAAAAAAAAF4iAAAAIAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAABQIgAAAAAAAAAAAAAAAAAAAABfQ29yRGxsTWFpbgBtc2NvcmVlLmRsbAAAAAAA/yUAIEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAACAAAAwAAABwMgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" + + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" + ); } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 09e5d783fd4bf..4f176bec3863b 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -4,6 +4,7 @@ using SampleMetadata; using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using Xunit; @@ -28,6 +29,7 @@ private static IEnumerable InvariantTestData { yield return typeof(object).Project(); yield return typeof(Span<>).Project(); + yield return typeof(SampleCompletedHandler).Project(); #if false foreach (Type t in typeof(TopLevelType).Project().Assembly.GetTypes()) { @@ -383,6 +385,8 @@ public static void TestIsPrimitive() Assert.False(typeof(BindingFlags).Project().IsPrimitive); Assert.False(typeof(int[]).Project().IsPrimitive); + Assert.False(typeof(SampleCompletedHandler).Project().IsPrimitive); + return; } @@ -403,6 +407,7 @@ public static void TestIsValueType() Assert.False(typeof(ValueType).Project().IsValueType); Assert.False(typeof(Enum).Project().IsValueType); Assert.True(typeof(MyColor).Project().IsValueType); + Assert.False(typeof(SampleCompletedHandler).Project().IsValueType); return; } @@ -611,5 +616,30 @@ public static void TypesWithStrangeCharacters() Assert.Equal(t, tRetrieved); } } + + [Fact] + public static void WindowsRuntimeMetadataDelegateType() + { + // Get the array of runtime assemblies. + // This will allow us to at least inspect types depending only on BCL. + string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll"); + + // Create MetadataLoadContext that can resolve assemblies using the created array. + PathAssemblyResolver resolver = new(runtimeAssemblies); + using MetadataLoadContext mlc = new(resolver); + + Stream peStream = new MemoryStream(TestData.s_MetadataDelegateImage); + Assembly a = mlc.LoadFromStream(peStream); + Assert.NotNull(a); + Assert.Equal(string.Empty, a.Location); + Assert.Equal("WindowsRuntime 1.4", a.ImageRuntimeVersion); + + string fullName = a.GetName().FullName; + Assert.Equal(TestData.s_MetadataDelegateAssemblyName, fullName); + + Type[] types = a.GetTypes(); + Assert.Single(types); + Assert.False(types[0].IsValueType); + } } } From 114f43dc80a1b73b6407a2066a3a10a7f05bb1c0 Mon Sep 17 00:00:00 2001 From: Andrew Boyarshin Date: Mon, 30 Aug 2021 16:04:27 +0700 Subject: [PATCH 2/5] Apply review suggestion --- .../tests/src/Tests/Type/TypeTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 4f176bec3863b..925b64f1fc128 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -628,7 +628,7 @@ public static void WindowsRuntimeMetadataDelegateType() PathAssemblyResolver resolver = new(runtimeAssemblies); using MetadataLoadContext mlc = new(resolver); - Stream peStream = new MemoryStream(TestData.s_MetadataDelegateImage); + using MemoryStream peStream = new(TestData.s_MetadataDelegateImage); Assembly a = mlc.LoadFromStream(peStream); Assert.NotNull(a); Assert.Equal(string.Empty, a.Location); From 66463ea0885cec0a5a71199a72626ac29008c8a3 Mon Sep 17 00:00:00 2001 From: Andrew Boyarshin Date: Mon, 30 Aug 2021 18:30:27 +0700 Subject: [PATCH 3/5] Skip the new test on Browser platform The MetadataLoadContext should work on Browser, but the test requires better MetadataAssemblyResolver implementation --- .../tests/src/Tests/Type/TypeTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 925b64f1fc128..2f17af506583a 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -618,6 +618,7 @@ public static void TypesWithStrangeCharacters() } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "BCL assemblies enumeration and loading is not supported on Browser.")] public static void WindowsRuntimeMetadataDelegateType() { // Get the array of runtime assemblies. From ccb94df56cb808a82c95109f12c44a8b9fe41363 Mon Sep 17 00:00:00 2001 From: Andrew Boyarshin Date: Sat, 9 Oct 2021 18:42:17 +0700 Subject: [PATCH 4/5] Address review feedback --- .../Modules/Ecma/EcmaModule.MetadataTables.cs | 11 +++++------ .../tests/src/Tests/Type/TypeTests.cs | 3 +-- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs index 42e78fd86f294..34de0d8396b0b 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.MetadataTables.cs @@ -71,13 +71,12 @@ internal MetadataTable AssemblyRefTable private MetadataTable CreateTable(TableIndex tableIndex) where T : class { - int rowCount = tableIndex switch - { - // Windows Metadata assemblies contain additional "virtual" AssemblyRefs we need to account for. + // Windows Metadata assemblies contain additional "virtual" AssemblyRefs we need to account for. + int rowCount = tableIndex == TableIndex.AssemblyRef // This is the simplest way to get the total AssemblyRefs count: - TableIndex.AssemblyRef => Reader.AssemblyReferences.Count, - _ => Reader.GetTableRowCount(tableIndex) - }; + ? Reader.AssemblyReferences.Count + : Reader.GetTableRowCount(tableIndex); + return new MetadataTable(rowCount); } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 2f17af506583a..4f8ba04e8baac 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -618,12 +618,11 @@ public static void TypesWithStrangeCharacters() } [Fact] - [SkipOnPlatform(TestPlatforms.Browser, "BCL assemblies enumeration and loading is not supported on Browser.")] public static void WindowsRuntimeMetadataDelegateType() { // Get the array of runtime assemblies. // This will allow us to at least inspect types depending only on BCL. - string[] runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll"); + string[] runtimeAssemblies = Directory.GetFiles(Path.GetDirectoryName(TestUtils.GetPathToCoreAssembly()), "*.dll"); // Create MetadataLoadContext that can resolve assemblies using the created array. PathAssemblyResolver resolver = new(runtimeAssemblies); From 7698e905b2cdfe1d2b44abc95d2efa92ab905b6a Mon Sep 17 00:00:00 2001 From: Andrew Boyarshin Date: Sat, 9 Oct 2021 20:09:49 +0700 Subject: [PATCH 5/5] Bring back the test skip for Browser System.Runtime still fails to resolve on Browser. WinMD parsing on Browser is questionable enough. Though, with better MetadataAssemblyResolver impl it should still work. Making this new unit test be Browser-aware is out-of-scope for this fix. The issue to be fixed is not related to assembly loading at all. --- .../tests/src/Tests/Type/TypeTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs index 4f8ba04e8baac..278329ce8e14d 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Type/TypeTests.cs @@ -618,6 +618,7 @@ public static void TypesWithStrangeCharacters() } [Fact] + [SkipOnPlatform(TestPlatforms.Browser, "BCL assemblies enumeration and loading is not supported on Browser.")] public static void WindowsRuntimeMetadataDelegateType() { // Get the array of runtime assemblies.