diff --git a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
index 3979d76aeadb74..fe0b293e4e0139 100644
--- a/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
+++ b/src/libraries/System.Runtime.Loader/tests/AssemblyLoadContextTest.cs
@@ -105,6 +105,7 @@ public static void LoadFromAssemblyName_AssemblyNotFound()
}
[Fact]
+ [PlatformSpecific(~TestPlatforms.Browser)] // Corelib does not exist on disc for Browser builds
public static void LoadFromAssemblyName_ValidTrustedPlatformAssembly()
{
var asmName = typeof(System.Linq.Enumerable).Assembly.GetName();
diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj
new file mode 100644
index 00000000000000..7fdc93128a864e
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/LoaderLinkTest.Dynamic.csproj
@@ -0,0 +1,11 @@
+
+
+ $(NetCoreAppCurrent)
+
+
+
+
+
+
+
+
diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs
new file mode 100644
index 00000000000000..3087d8a6daa9cf
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Dynamic/SharedInterfaceImplementation.cs
@@ -0,0 +1,14 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+using LoaderLinkTest.Shared;
+
+namespace LoaderLinkTest.Dynamic
+{
+ public class SharedInterfaceImplementation : ISharedInterface
+ {
+ public string TestString => "Hello";
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs
new file mode 100644
index 00000000000000..3c381e1bc2d3c1
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/ISharedInterface.cs
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+
+namespace LoaderLinkTest.Shared
+{
+ public interface ISharedInterface
+ {
+ string TestString { get; }
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj
new file mode 100644
index 00000000000000..2adb5cb89d9747
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.Shared/LoaderLinkTest.Shared.csproj
@@ -0,0 +1,8 @@
+
+
+ $(NetCoreAppCurrent)
+
+
+
+
+
diff --git a/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs
new file mode 100644
index 00000000000000..c7daa91333664a
--- /dev/null
+++ b/src/libraries/System.Runtime.Loader/tests/LoaderLinkTest.cs
@@ -0,0 +1,33 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using Xunit;
+
+using LoaderLinkTest.Shared;
+
+namespace LoaderLinkTest
+{
+ public class LoaderLinkTest
+ {
+ [Fact]
+ public static void EnsureTypesLinked() // https://github.com/dotnet/runtime/issues/42207
+ {
+ string parentDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ byte[] bytes = File.ReadAllBytes(Path.Combine(parentDir != null ? parentDir : "/", "LoaderLinkTest.Dynamic.dll"));
+ Assembly asm = Assembly.Load(bytes);
+ var dynamicType = asm.GetType("LoaderLinkTest.Dynamic.SharedInterfaceImplementation", true);
+ var sharedInterface = dynamicType.GetInterfaces().First(e => e.Name == nameof(ISharedInterface));
+ Assert.Equal(typeof(ISharedInterface).Assembly, sharedInterface.Assembly);
+ Assert.Equal(typeof(ISharedInterface), sharedInterface);
+
+ var instance = Activator.CreateInstance(dynamicType);
+ Assert.True(instance is ISharedInterface);
+
+ Assert.NotNull(((ISharedInterface)instance).TestString); // cast should not fail
+ }
+ }
+}
diff --git a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
index f43714d9365d9a..ae825641dab5e3 100644
--- a/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
+++ b/src/libraries/System.Runtime.Loader/tests/System.Runtime.Loader.Tests.csproj
@@ -14,6 +14,7 @@
+
@@ -29,8 +30,10 @@
+
+
-
\ No newline at end of file
+
diff --git a/src/mono/mono/metadata/assembly-internals.h b/src/mono/mono/metadata/assembly-internals.h
index 29a3334c3315ce..486cfa3ed681ce 100644
--- a/src/mono/mono/metadata/assembly-internals.h
+++ b/src/mono/mono/metadata/assembly-internals.h
@@ -16,7 +16,8 @@
#else
#define MONO_ASSEMBLY_CORLIB_NAME "System.Private.CoreLib"
#endif
-#define MONO_ASSEMBLY_CORLIB_RESOURCE_NAME (MONO_ASSEMBLY_CORLIB_NAME ".resources")
+#define MONO_ASSEMBLY_RESOURCE_SUFFIX ".resources"
+#define MONO_ASSEMBLY_CORLIB_RESOURCE_NAME (MONO_ASSEMBLY_CORLIB_NAME MONO_ASSEMBLY_RESOURCE_SUFFIX)
/* Flag bits for mono_assembly_names_equal_flags (). */
typedef enum {
diff --git a/src/mono/mono/metadata/assembly.c b/src/mono/mono/metadata/assembly.c
index 973555e68e9125..931fe18e0883b6 100644
--- a/src/mono/mono/metadata/assembly.c
+++ b/src/mono/mono/metadata/assembly.c
@@ -1651,16 +1651,16 @@ load_reference_by_aname_individual_asmctx (MonoAssemblyName *aname, MonoAssembly
}
#else
static MonoAssembly *
-search_bundle_for_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname, gboolean is_satellite)
+search_bundle_for_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname)
{
- if ((bundles == NULL && !is_satellite) || (satellite_bundles == NULL && is_satellite))
+ if (bundles == NULL && satellite_bundles == NULL)
return NULL;
MonoImageOpenStatus status;
MonoImage *image;
MonoAssemblyLoadRequest req;
image = mono_assembly_open_from_bundle (alc, aname->name, &status, FALSE, aname->culture);
- if (!image) {
+ if (!image && !g_str_has_suffix (aname->name, ".dll")) {
char *name = g_strdup_printf ("%s.dll", aname->name);
image = mono_assembly_open_from_bundle (alc, name, &status, FALSE, aname->culture);
}
@@ -1692,23 +1692,27 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M
* Try these until one of them succeeds (by returning a non-NULL reference):
* 1. Check if it's already loaded by the ALC.
*
- * 2. If we have a bundle registered, search the images for a matching name.
+ * 2. If it's a non-default ALC, call the Load() method.
*
- * 3. If it's a non-default ALC, call the Load() method.
- *
- * 4. If the ALC is not the default and this is not a satellite request,
+ * 3. If the ALC is not the default and this is not a satellite request,
* check if it's already loaded by the default ALC.
*
- * 5. If the ALC is the default or this is not a satellite request,
+ * 4. If we have a bundle registered and this is not a satellite request,
+ * search the images for a matching name.
+ *
+ * 5. If we have a satellite bundle registered and this is a satellite request,
+ * find the parent ALC and search the images for a matching name and culture.
+ *
+ * 6. If the ALC is the default or this is not a satellite request,
* check the TPA list, APP_PATHS, and ApplicationBase.
*
- * 6. If this is a satellite request, call the ALC ResolveSatelliteAssembly method.
+ * 7. If this is a satellite request, call the ALC ResolveSatelliteAssembly method.
*
- * 7. Call the ALC Resolving event.
+ * 8. Call the ALC Resolving event.
*
- * 8. Call the ALC AssemblyResolve event (except for corlib satellite assemblies).
+ * 9. Call the ALC AssemblyResolve event (except for corlib satellite assemblies).
*
- * 9. Return NULL.
+ * 10. Return NULL.
*/
reference = mono_assembly_loaded_internal (alc, aname, FALSE);
@@ -1717,14 +1721,6 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M
goto leave;
}
- if (bundles != NULL || satellite_bundles != NULL) {
- reference = search_bundle_for_assembly (alc, aname, is_satellite);
- if (reference) {
- mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name);
- goto leave;
- }
- }
-
if (!is_default) {
reference = mono_alc_invoke_resolve_using_load_nofail (alc, aname);
if (reference) {
@@ -1741,6 +1737,38 @@ netcore_load_reference (MonoAssemblyName *aname, MonoAssemblyLoadContext *alc, M
}
}
+ if (bundles != NULL && !is_satellite) {
+ reference = search_bundle_for_assembly (mono_domain_default_alc (mono_alc_domain (alc)), aname);
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the bundle: '%s'.", aname->name);
+ goto leave;
+ }
+ }
+
+ if (satellite_bundles != NULL && is_satellite) {
+ // Satellite assembly byname requests should be loaded in the same ALC as their parent assembly
+ size_t name_len = strlen (aname->name);
+ char *parent_name = NULL;
+ MonoAssemblyLoadContext *parent_alc = NULL;
+ if (g_str_has_suffix (aname->name, MONO_ASSEMBLY_RESOURCE_SUFFIX))
+ parent_name = g_strdup_printf ("%s.dll", g_strndup (aname->name, name_len - strlen (MONO_ASSEMBLY_RESOURCE_SUFFIX)));
+
+ if (parent_name) {
+ MonoAssemblyOpenRequest req;
+ mono_assembly_request_prepare_open (&req, MONO_ASMCTX_DEFAULT, alc);
+ MonoAssembly *parent_assembly = mono_assembly_request_open (parent_name, &req, NULL);
+ parent_alc = mono_assembly_get_alc (parent_assembly);
+ }
+
+ if (parent_alc)
+ reference = search_bundle_for_assembly (parent_alc, aname);
+
+ if (reference) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_ASSEMBLY, "Assembly found in the satellite bundle: '%s'.", aname->name);
+ goto leave;
+ }
+ }
+
if (is_default || !is_satellite) {
reference = invoke_assembly_preload_hook (mono_domain_default_alc (mono_alc_domain (alc)), aname, assemblies_path);
if (reference) {
@@ -2593,11 +2621,9 @@ mono_assembly_open_from_bundle (MonoAssemblyLoadContext *alc, const char *filena
#else
gboolean is_satellite = culture && culture [0] != 0;;
if (is_satellite)
- {
image = open_from_satellite_bundle (alc, filename, status, refonly, culture);
- } else {
+ else
image = open_from_bundle_internal (alc, filename, status, refonly, FALSE);
- }
#endif
if (image) {