Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions eng/testing/scenarios/BuildWasmAppsJobsListCoreCLR.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,6 @@ Wasm.Build.Tests.IcuShardingTests
Wasm.Build.Tests.IcuShardingTests2
Wasm.Build.Tests.IcuTests
Wasm.Build.Tests.MemoryTests
Wasm.Build.Tests.AppSettingsTests
Wasm.Build.Tests.Blazor.AppsettingsTests
Wasm.Build.Tests.DownloadThenInitTests
4 changes: 3 additions & 1 deletion src/coreclr/vm/assemblynative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,9 @@ extern "C" void QCALLTYPE AssemblyNative_LoadFromPath(INT_PTR ptrNativeAssemblyB

if (pwzILPath != NULL)
{
pILImage = PEImage::OpenImage(pwzILPath);
pILImage = PEImage::OpenImage(pwzILPath,
MDInternalImport_Default,
AssemblyProbeExtension::Probe(SString{ SString::Literal, pwzILPath }));

// Need to verify that this is a valid CLR assembly.
if (!pILImage->CheckILFormat())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -858,11 +858,29 @@ private static unsafe void ResolveUsingEvent(IntPtr gchAssemblyLoadContext, Asse
AssemblyLoadContext parentALC = GetLoadContext(parentAssembly)!;

string? parentDirectory = Path.GetDirectoryName(parentAssembly.Location);

#if TARGET_BROWSER
// On Browser/WASM, assemblies loaded via external_assembly_probe have empty Location
// (PEAssembly::GetPath returns empty for IsExternalData). Satellite assemblies are
// registered in JS loadedAssemblies with virtual paths like "/{culture}/{name}.dll".
// Construct the path matching the JS loader's normalizeVirtualPath format.
string assemblyPath = string.IsNullOrEmpty(parentDirectory)
? $"/{assemblyName.CultureName}/{assemblyName.Name}.dll"
: Path.Combine(parentDirectory, assemblyName.CultureName!, $"{assemblyName.Name}.dll");

try
{
return (RuntimeAssembly?)parentALC.LoadFromAssemblyPath(assemblyPath);
}
catch (IOException)
{
return null;
}
#else
if (parentDirectory == null)
return null;

string assemblyPath = Path.Combine(parentDirectory, assemblyName.CultureName!, $"{assemblyName.Name}.dll");

bool exists = FileSystem.FileExists(assemblyPath);
if (!exists && PathInternal.IsCaseSensitive)
{
Expand All @@ -885,6 +903,7 @@ private static unsafe void ResolveUsingEvent(IntPtr gchAssemblyLoadContext, Asse
#endif // CORECLR

return asm;
#endif // TARGET_BROWSER
}

internal IntPtr GetResolvedUnmanagedDll(Assembly assembly, string unmanagedDllName)
Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasm/Wasm.Build.Tests/LazyLoadingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public LazyLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture
return data.Select(d => new object[] { d, data });
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsMonoRuntime)), TestCategory("no-fingerprinting")]
[Theory, TestCategory("no-fingerprinting")]
[MemberData(nameof(LoadLazyAssemblyBeforeItIsNeededData))]
public async Task LoadLazyAssemblyBeforeItIsNeeded(string lazyLoadingTestExtension, string[] allLazyLoadingTestExtensions)
{
Expand Down
4 changes: 2 additions & 2 deletions src/mono/wasm/Wasm.Build.Tests/SatelliteLoadingTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public SatelliteLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFi
{
}

[ConditionalTheory(typeof(BuildTestBase), nameof(IsMonoRuntime)), TestCategory("no-fingerprinting")]
[Theory, TestCategory("no-fingerprinting")]
[InlineData(false)]
[InlineData(true)]
public async Task LoadSatelliteAssembly(bool loadAllSatelliteResources)
Expand Down Expand Up @@ -60,7 +60,7 @@ public async Task LoadSatelliteAssembly(bool loadAllSatelliteResources)
);
}

[ConditionalFact(typeof(BuildTestBase), nameof(IsMonoRuntime)), TestCategory("bundler-friendly")]
[Fact, TestCategory("bundler-friendly")]
public async Task LoadSatelliteAssemblyFromReference()
{
Configuration config = Configuration.Release;
Expand Down
1 change: 1 addition & 0 deletions src/native/libs/Common/JavaScript/loader/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,7 @@ async function loadResourceFetch(asset: AssetEntryInternal): Promise<Response> {
}
}

dotnetLogger.debug(`Attempting to download '${asset.resolvedUrl}'`);
return fetchLike(asset.resolvedUrl!, fetchOptions, expectedContentType);
}

Expand Down
2 changes: 2 additions & 0 deletions src/native/libs/Common/JavaScript/loader/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ function mergeConfigs(target: LoaderConfigInternal, source: Partial<LoaderConfig
source.virtualWorkingDirectory = source.virtualWorkingDirectory !== undefined ? source.virtualWorkingDirectory : target.virtualWorkingDirectory;
source.debugLevel = source.debugLevel !== undefined ? source.debugLevel : target.debugLevel;
source.diagnosticTracing = source.diagnosticTracing !== undefined ? source.diagnosticTracing : target.diagnosticTracing;
source.applicationEnvironment = source.applicationEnvironment !== undefined ? source.applicationEnvironment : target.applicationEnvironment;
// Merge maps and arrays: target values first, source values merged on top.
source.environmentVariables = { ...target.environmentVariables, ...source.environmentVariables };
source.runtimeOptions = [...target.runtimeOptions!, ...source.runtimeOptions!];
Expand Down Expand Up @@ -93,6 +94,7 @@ function defaultConfig(target: LoaderConfigInternal) {
if (target.virtualWorkingDirectory === undefined) target.virtualWorkingDirectory = browserVirtualAppBase;
if (target.maxParallelDownloads === undefined) target.maxParallelDownloads = 16;
if (target.enableDownloadRetry === undefined) target.enableDownloadRetry = true;
if (target.applicationEnvironment === undefined) target.applicationEnvironment = "Production";
normalizeConfig(target);
}

Expand Down
17 changes: 17 additions & 0 deletions src/native/libs/Common/JavaScript/loader/run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,23 @@ export async function createRuntime(downloadOnly: boolean, httpCacheOnly: boolea
const satelliteResourcesPromise = loaderConfig.loadAllSatelliteResources && resources.satelliteResources
? fetchSatelliteAssemblies(Object.keys(resources.satelliteResources))
: Promise.resolve();

// Add appsettings files to VFS for download
if (loaderConfig.appsettings) {
Comment on lines +129 to +130
for (const configUrl of loaderConfig.appsettings) {
const lastSlash = configUrl.lastIndexOf("/");
const configFileName = lastSlash >= 0 ? configUrl.substring(lastSlash + 1) : configUrl;
if (configFileName === "appsettings.json" || configFileName === `appsettings.${loaderConfig.applicationEnvironment}.json`) {
resources.vfs!.push({
name: configUrl,
virtualPath: configFileName,
cache: "no-cache",
useCredentials: true,
} as any);
}
}
}

const vfsPromise = forEachResource(resources.vfs, fetchVfs);

// WASM-TODO: also check that the debugger is linked in and check feature flags
Expand Down
Loading