From 505177abf0ec128281cb47561de18eaddde79b74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Fri, 12 Jul 2024 14:37:41 +0200 Subject: [PATCH 1/5] Compare lazy assemblies without extension during build --- .../GenerateWasmBootJson.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs index 63cee84d412a84..de9864bcb774df 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -176,6 +176,15 @@ public void WriteBootJson(Stream output, string entryAssemblyName) { var endpointByAsset = Endpoints.ToDictionary(e => e.GetMetadata("AssetFile")); + var lazyLoadAssembliesWithoutExtension = LazyLoadedAssemblies.ToDictionary(l => + { + var extension = Path.GetExtension(l.ItemSpec); + if (extension == ".dll" || extension == Utils.WebcilInWasmExtension) + return Path.GetFileNameWithoutExtension(l.ItemSpec); + + return l.ItemSpec; + }); + var remainingLazyLoadAssemblies = new List(LazyLoadedAssemblies ?? Array.Empty()); var resourceData = result.resources; @@ -194,7 +203,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName) var resourceName = Path.GetFileName(resource.GetMetadata("OriginalItemSpec")); var resourceRoute = Path.GetFileName(endpointByAsset[resource.ItemSpec].ItemSpec); - if (TryGetLazyLoadedAssembly(resourceName, out var lazyLoad)) + if (TryGetLazyLoadedAssembly(lazyLoadAssembliesWithoutExtension, resourceName, out var lazyLoad)) { MapFingerprintedAsset(resourceData, resourceRoute, resourceName); Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a lazy loaded assembly.", resource.ItemSpec); @@ -220,7 +229,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName) else if (string.Equals("symbol", assetTraitValue, StringComparison.OrdinalIgnoreCase)) { MapFingerprintedAsset(resourceData, resourceRoute, resourceName); - if (TryGetLazyLoadedAssembly($"{fileName}.dll", out _) || TryGetLazyLoadedAssembly($"{fileName}{Utils.WebcilInWasmExtension}", out _)) + if (TryGetLazyLoadedAssembly(lazyLoadAssembliesWithoutExtension, fileName, out _)) { Log.LogMessage(MessageImportance.Low, "Candidate '{0}' is defined as a lazy loaded symbols file.", resource.ItemSpec); resourceData.lazyAssembly ??= new ResourceHashesByNameDictionary(); @@ -463,9 +472,13 @@ private void AddToAdditionalResources(ITaskItem resource, Dictionary lazyLoadAssembliesNoExtension, string fileName, out ITaskItem lazyLoadedAssembly) { - return (lazyLoadedAssembly = LazyLoadedAssemblies?.SingleOrDefault(a => a.ItemSpec == fileName)) != null; + var extension = Path.GetExtension(fileName); + if (extension == ".dll" || extension == Utils.WebcilInWasmExtension) + fileName = Path.GetFileNameWithoutExtension(fileName); + + return lazyLoadAssembliesNoExtension.TryGetValue(fileName, out lazyLoadedAssembly); } private Version? parsedTargetFrameworkVersion; From 8cded5c35839129b305ed06dbddd0886e38e5f50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Fri, 12 Jul 2024 14:52:12 +0200 Subject: [PATCH 2/5] Compare lazy assemblies without extension during runtime --- src/mono/browser/runtime/lazyLoading.ts | 18 ++++++++++++++++-- .../App/WasmBasicTestApp.csproj | 2 +- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/mono/browser/runtime/lazyLoading.ts b/src/mono/browser/runtime/lazyLoading.ts index 3d075b3005a8e9..5123ffe1cf5101 100644 --- a/src/mono/browser/runtime/lazyLoading.ts +++ b/src/mono/browser/runtime/lazyLoading.ts @@ -13,11 +13,19 @@ export async function loadLazyAssembly (assemblyNameToLoad: string): Promise - + From b31a34426668392d496047855cfdbe854f60a016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Mon, 22 Jul 2024 10:55:03 +0200 Subject: [PATCH 3/5] Fix loading PDB for assembly without extension --- src/mono/browser/runtime/lazyLoading.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/mono/browser/runtime/lazyLoading.ts b/src/mono/browser/runtime/lazyLoading.ts index 5123ffe1cf5101..9787c18ac33ec3 100644 --- a/src/mono/browser/runtime/lazyLoading.ts +++ b/src/mono/browser/runtime/lazyLoading.ts @@ -7,7 +7,6 @@ import { AssetEntry } from "./types"; export async function loadLazyAssembly (assemblyNameToLoad: string): Promise { const resources = loaderHelpers.config.resources!; - const originalAssemblyName = assemblyNameToLoad; const lazyAssemblies = resources.lazyAssembly; if (!lazyAssemblies) { throw new Error("No assemblies have been marked as lazy-loadable. Use the 'BlazorWebAssemblyLazyLoad' item group in your project file to enable lazy loading an assembly."); @@ -52,7 +51,7 @@ export async function loadLazyAssembly (assemblyNameToLoad: string): Promise Date: Mon, 22 Jul 2024 10:55:13 +0200 Subject: [PATCH 4/5] More tests --- .../TestAppScenarios/LazyLoadingTests.cs | 28 +++++++++++++++---- .../App/WasmBasicTestApp.csproj | 10 ++++++- .../WasmBasicTestApp/App/wwwroot/main.js | 18 +++++++++++- 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs index 6a167ec2de10a5..eb98b3d6f6e0a3 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/LazyLoadingTests.cs @@ -20,16 +20,32 @@ public LazyLoadingTests(ITestOutputHelper output, SharedBuildPerTestClassFixture { } - [Fact, TestCategory("no-fingerprinting")] - public async Task LoadLazyAssemblyBeforeItIsNeeded() + public static IEnumerable LoadLazyAssemblyBeforeItIsNeededData() + { + string[] data = ["wasm", "dll", "NoExtension"]; + return data.Select(d => new object[] { d, data }); + } + + [Theory, TestCategory("no-fingerprinting")] + [MemberData(nameof(LoadLazyAssemblyBeforeItIsNeededData))] + public async Task LoadLazyAssemblyBeforeItIsNeeded(string lazyLoadingTestExtension, string[] allLazyLoadingTestExtensions) { CopyTestAsset("WasmBasicTestApp", "LazyLoadingTests", "App"); - BuildProject("Debug"); + BuildProject("Debug", extraArgs: $"-p:LazyLoadingTestExtension={lazyLoadingTestExtension}"); - var result = await RunSdkStyleAppForBuild(new(Configuration: "Debug", TestScenario: "LazyLoadingTest")); + // We are running the app and passing all possible lazy extensions to test matrix of all possibilities. + // We don't need to rebuild the application to test how client is trying to load the assembly. + foreach (var clientLazyLoadingTestExtension in allLazyLoadingTestExtensions) + { + var result = await RunSdkStyleAppForBuild(new( + Configuration: "Debug", + TestScenario: "LazyLoadingTest", + BrowserQueryString: new Dictionary { ["lazyLoadingTestExtension"] = clientLazyLoadingTestExtension } + )); - Assert.True(result.TestOutput.Any(m => m.Contains("FirstName")), "The lazy loading test didn't emit expected message with JSON"); - Assert.True(result.ConsoleOutput.Any(m => m.Contains("Attempting to download") && m.Contains("_framework/Json.") && m.Contains(".pdb")), "The lazy loading test didn't load PDB"); + Assert.True(result.TestOutput.Any(m => m.Contains("FirstName")), "The lazy loading test didn't emit expected message with JSON"); + Assert.True(result.ConsoleOutput.Any(m => m.Contains("Attempting to download") && m.Contains("_framework/Json.") && m.Contains(".pdb")), "The lazy loading test didn't load PDB"); + } } [Fact] diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj index a287f0da91f719..a62c057733b4f5 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/WasmBasicTestApp.csproj @@ -6,11 +6,19 @@ true + + + .dll + .wasm + + $(WasmAssemblyExtension) + + - + diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index 85fd83270b2731..7fccb3c8e473d1 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -138,7 +138,23 @@ try { break; case "LazyLoadingTest": if (params.get("loadRequiredAssembly") !== "false") { - await INTERNAL.loadLazyAssembly(`Json${assemblyExtension}`); + let lazyAssemblyExtension = assemblyExtension; + switch (params.get("lazyLoadingTestExtension")) { + case "wasm": + lazyAssemblyExtension = ".wasm"; + break; + case "dll": + lazyAssemblyExtension = ".dll"; + break; + case "NoExtension": + lazyAssemblyExtension = ""; + break; + default: + lazyAssemblyExtension = assemblyExtension; + break; + } + + await INTERNAL.loadLazyAssembly(`Json${lazyAssemblyExtension}`); } exports.LazyLoadingTest.Run(); exit(0); From 4d3cbd85a61dbbeb70dad09d1b5dfd0bea05d583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Fi=C5=A1era?= Date: Mon, 22 Jul 2024 13:38:10 +0200 Subject: [PATCH 5/5] Fix case without lazy assemblies --- .../GenerateWasmBootJson.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs index de9864bcb774df..748671aeec8984 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -176,7 +176,7 @@ public void WriteBootJson(Stream output, string entryAssemblyName) { var endpointByAsset = Endpoints.ToDictionary(e => e.GetMetadata("AssetFile")); - var lazyLoadAssembliesWithoutExtension = LazyLoadedAssemblies.ToDictionary(l => + var lazyLoadAssembliesWithoutExtension = (LazyLoadedAssemblies ?? Array.Empty()).ToDictionary(l => { var extension = Path.GetExtension(l.ItemSpec); if (extension == ".dll" || extension == Utils.WebcilInWasmExtension)