From d25324a06ed1ab772401f05db7a8d387d9d1bd7a Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 15 May 2024 14:08:42 +0200 Subject: [PATCH 1/5] await dotnet.download(); --- src/mono/browser/runtime/dotnet.d.ts | 4 ++ src/mono/browser/runtime/loader/assets.ts | 18 ++++++ src/mono/browser/runtime/loader/config.ts | 10 +++- src/mono/browser/runtime/loader/exit.ts | 1 + src/mono/browser/runtime/loader/globals.ts | 1 + src/mono/browser/runtime/loader/run.ts | 59 +++++++++++++++---- src/mono/browser/runtime/types/index.ts | 4 ++ src/mono/browser/runtime/types/internal.ts | 1 + src/mono/sample/wasm/browser-advanced/main.js | 9 ++- 9 files changed, 91 insertions(+), 16 deletions(-) diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index aa38e6ef9916d3..6423e921e478db 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -117,6 +117,10 @@ interface DotnetHostBuilder { * from a custom source, such as an external CDN. */ withResourceLoader(loadBootResource?: LoadBootResourceCallback): DotnetHostBuilder; + /** + * Downloads all the assets but doesn't create the runtime instance. + */ + download(): Promise; /** * Starts the runtime and returns promise of the API object. */ diff --git a/src/mono/browser/runtime/loader/assets.ts b/src/mono/browser/runtime/loader/assets.ts index 926042d57e7ddf..8c73f424fa0356 100644 --- a/src/mono/browser/runtime/loader/assets.ts +++ b/src/mono/browser/runtime/loader/assets.ts @@ -150,7 +150,12 @@ export function resolve_single_asset_path (behavior: SingleAssetBehaviors): Asse return asset; } +let downloadAssetsStarted = false; export async function mono_download_assets (): Promise { + if (downloadAssetsStarted) { + return; + } + downloadAssetsStarted = true; mono_log_debug("mono_download_assets"); try { const promises_of_assets_core: Promise[] = []; @@ -176,6 +181,14 @@ export async function mono_download_assets (): Promise { loaderHelpers.allDownloadsQueued.promise_control.resolve(); + Promise.all([...promises_of_assets_core, ...promises_of_assets_remaining]).then(() => { + loaderHelpers.allDownloadsFinished.promise_control.resolve(); + }).catch(err => { + loaderHelpers.err("Error in mono_download_assets: " + err); + mono_exit(1, err); + throw err; + }); + // continue after the dotnet.runtime.js was loaded await loaderHelpers.runtimeModuleLoaded.promise; @@ -261,7 +274,12 @@ export async function mono_download_assets (): Promise { } } +let assetsPrepared = false; export function prepareAssets () { + if (assetsPrepared) { + return; + } + assetsPrepared = true; const config = loaderHelpers.config; const modulesAssets: AssetEntryInternal[] = []; diff --git a/src/mono/browser/runtime/loader/config.ts b/src/mono/browser/runtime/loader/config.ts index 53abb025deca71..3165672e6257e6 100644 --- a/src/mono/browser/runtime/loader/config.ts +++ b/src/mono/browser/runtime/loader/config.ts @@ -226,12 +226,19 @@ export function normalizeConfig () { let configLoaded = false; export async function mono_wasm_load_config (module: DotnetModuleInternal): Promise { - const configFilePath = module.configSrc; if (configLoaded) { await loaderHelpers.afterConfigLoaded.promise; return; } + let configFilePath; try { + if (!module.configSrc && (!loaderHelpers.config || Object.keys(loaderHelpers.config).length === 0 || (!loaderHelpers.config.assets && !loaderHelpers.config.resources))) { + // if config file location nor assets are provided + module.configSrc = "./blazor.boot.json"; + } + + configFilePath = module.configSrc; + configLoaded = true; if (configFilePath) { mono_log_debug("mono_wasm_load_config"); @@ -255,6 +262,7 @@ export async function mono_wasm_load_config (module: DotnetModuleInternal): Prom } normalizeConfig(); + loaderHelpers.afterConfigLoaded.promise_control.resolve(loaderHelpers.config); } catch (err) { const errMessage = `Failed to load config file ${configFilePath} ${err} ${(err as Error)?.stack}`; loaderHelpers.config = module.config = Object.assign(loaderHelpers.config, { message: errMessage, error: err, isError: true }); diff --git a/src/mono/browser/runtime/loader/exit.ts b/src/mono/browser/runtime/loader/exit.ts index ecb2b46bb1f1f8..5fa5c2a7dfa875 100644 --- a/src/mono/browser/runtime/loader/exit.ts +++ b/src/mono/browser/runtime/loader/exit.ts @@ -229,6 +229,7 @@ async function flush_node_streams () { function abort_promises (reason: any) { loaderHelpers.allDownloadsQueued.promise_control.reject(reason); + loaderHelpers.allDownloadsFinished.promise_control.reject(reason); loaderHelpers.afterConfigLoaded.promise_control.reject(reason); loaderHelpers.wasmCompilePromise.promise_control.reject(reason); loaderHelpers.runtimeModuleLoaded.promise_control.reject(reason); diff --git a/src/mono/browser/runtime/loader/globals.ts b/src/mono/browser/runtime/loader/globals.ts index b5ce131e7b18fd..5ef69d0e2e8ced 100644 --- a/src/mono/browser/runtime/loader/globals.ts +++ b/src/mono/browser/runtime/loader/globals.ts @@ -103,6 +103,7 @@ export function setLoaderGlobals ( afterConfigLoaded: createPromiseController(), allDownloadsQueued: createPromiseController(), + allDownloadsFinished: createPromiseController(), wasmCompilePromise: createPromiseController(), runtimeModuleLoaded: createPromiseController(), loadingWorkers: createPromiseController(), diff --git a/src/mono/browser/runtime/loader/run.ts b/src/mono/browser/runtime/loader/run.ts index 0bd2dd60d80852..6da0455055e742 100644 --- a/src/mono/browser/runtime/loader/run.ts +++ b/src/mono/browser/runtime/loader/run.ts @@ -348,6 +348,15 @@ export class HostBuilder implements DotnetHostBuilder { } } + async download (): Promise { + try { + await downloadOnly(); + } catch (err) { + mono_exit(1, err); + throw err; + } + } + async create (): Promise { try { if (!this.instance) { @@ -375,16 +384,22 @@ export class HostBuilder implements DotnetHostBuilder { } export async function createApi (): Promise { + await createEmscripten(emscriptenModule); + return globalObjectsRoot.api; +} + +let emscriptenPrepared = false; +async function prepareEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)) { + if (emscriptenPrepared) { + return; + } + emscriptenPrepared = true; if (ENVIRONMENT_IS_WEB && loaderHelpers.config.forwardConsoleLogsToWS && typeof globalThis.WebSocket != "undefined") { setup_proxy_console("main", globalThis.console, globalThis.location.origin); } mono_assert(emscriptenModule, "Null moduleConfig"); mono_assert(loaderHelpers.config, "Null moduleConfig.config"); - await createEmscripten(emscriptenModule); - return globalObjectsRoot.api; -} -export async function createEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise { // extract ModuleConfig if (typeof moduleFactory === "function") { const extension = moduleFactory(globalObjectsRoot.api) as any; @@ -400,6 +415,11 @@ export async function createEmscripten (moduleFactory: DotnetModuleConfig | ((ap } await detect_features_and_polyfill(emscriptenModule); +} + +export async function createEmscripten (moduleFactory: DotnetModuleConfig | ((api: RuntimeAPI) => DotnetModuleConfig)): Promise { + await prepareEmscripten(moduleFactory); + if (BuildConfiguration === "Debug" && !ENVIRONMENT_IS_WORKER) { mono_log_info(`starting script ${loaderHelpers.scriptUrl}`); mono_log_info(`starting in ${loaderHelpers.scriptDirectory}`); @@ -412,13 +432,16 @@ export async function createEmscripten (moduleFactory: DotnetModuleConfig | ((ap : createEmscriptenMain(); } +let jsModuleRuntimePromise: Promise; +let jsModuleNativePromise: Promise; + // in the future we can use feature detection to load different flavors function importModules () { const jsModuleRuntimeAsset = resolve_single_asset_path("js-module-runtime"); const jsModuleNativeAsset = resolve_single_asset_path("js-module-native"); - - let jsModuleRuntimePromise: Promise; - let jsModuleNativePromise: Promise; + if (jsModuleRuntimePromise && jsModuleNativePromise) { + return [jsModuleRuntimePromise, jsModuleNativePromise]; + } if (typeof jsModuleRuntimeAsset.moduleExports === "object") { jsModuleRuntimePromise = jsModuleRuntimeAsset.moduleExports; @@ -457,12 +480,24 @@ async function initializeModules (es6Modules: [RuntimeModuleExportsInternal, Nat }); } -async function createEmscriptenMain (): Promise { - if (!emscriptenModule.configSrc && (!loaderHelpers.config || Object.keys(loaderHelpers.config).length === 0 || (!loaderHelpers.config.assets && !loaderHelpers.config.resources))) { - // if config file location nor assets are provided - emscriptenModule.configSrc = "./blazor.boot.json"; - } +async function downloadOnly ():Promise { + prepareEmscripten(emscriptenModule); + + // download config + await mono_wasm_load_config(emscriptenModule); + prepareAssets(); + + await initCacheToUseIfEnabled(); + + init_globalization(); + + mono_download_assets(); // intentionally not awaited + + await loaderHelpers.allDownloadsFinished.promise; +} + +async function createEmscriptenMain (): Promise { // download config await mono_wasm_load_config(emscriptenModule); diff --git a/src/mono/browser/runtime/types/index.ts b/src/mono/browser/runtime/types/index.ts index df2fb6b69c81b7..77469a6dd88191 100644 --- a/src/mono/browser/runtime/types/index.ts +++ b/src/mono/browser/runtime/types/index.ts @@ -65,6 +65,10 @@ export interface DotnetHostBuilder { * from a custom source, such as an external CDN. */ withResourceLoader(loadBootResource?: LoadBootResourceCallback): DotnetHostBuilder; + /** + * Downloads all the assets but doesn't create the runtime instance. + */ + download(): Promise; /** * Starts the runtime and returns promise of the API object. */ diff --git a/src/mono/browser/runtime/types/internal.ts b/src/mono/browser/runtime/types/internal.ts index 6b9f16cafa05fb..9d80f254ae2031 100644 --- a/src/mono/browser/runtime/types/internal.ts +++ b/src/mono/browser/runtime/types/internal.ts @@ -141,6 +141,7 @@ export type LoaderHelpers = { afterConfigLoaded: PromiseAndController, allDownloadsQueued: PromiseAndController, + allDownloadsFinished: PromiseAndController, wasmCompilePromise: PromiseAndController, runtimeModuleLoaded: PromiseAndController, loadingWorkers: PromiseAndController, diff --git a/src/mono/sample/wasm/browser-advanced/main.js b/src/mono/sample/wasm/browser-advanced/main.js index 115514db72991f..fe0331693d6de6 100644 --- a/src/mono/sample/wasm/browser-advanced/main.js +++ b/src/mono/sample/wasm/browser-advanced/main.js @@ -29,7 +29,7 @@ try { } return originalFetch(url, fetchArgs); }; - const { runtimeBuildInfo, setModuleImports, getAssemblyExports, runMain, getConfig, Module } = await dotnet + dotnet .withElementOnExit() // 'withModuleConfig' is internal lower level API // here we show how emscripten could be further configured @@ -69,8 +69,11 @@ try { .withResourceLoader((type, name, defaultUri, integrity, behavior) => { // loadBootResource could return string with unqualified name of resource. It assumes that we resolve it with document.baseURI return name; - }) - .create(); + }); + + await dotnet.download(); + + const { runtimeBuildInfo, setModuleImports, getAssemblyExports, runMain, getConfig, Module } = await dotnet.create(); // at this point both emscripten and monoVM are fully initialized. console.log('user code after dotnet.create'); From 5d3f2ca416c529d1ae1ca300f159b040a53537f4 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 5 Jun 2024 15:58:35 +0200 Subject: [PATCH 2/5] Added WBT. --- .../scenarios/BuildWasmAppsJobsList.txt | 1 + .../Wasm.Build.Tests/InitThenDownloadTests.cs | 43 +++++++++++++++++++ .../InitThenDownload/InitThenDownload.csproj | 8 ++++ .../testassets/InitThenDownload/Program.cs | 12 ++++++ .../Properties/AssemblyInfo.cs | 4 ++ .../runtimeconfig.template.json | 10 +++++ .../InitThenDownload/wwwroot/index.html | 17 ++++++++ .../InitThenDownload/wwwroot/main.js | 24 +++++++++++ 8 files changed, 119 insertions(+) create mode 100644 src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs create mode 100644 src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj create mode 100644 src/mono/wasm/testassets/InitThenDownload/Program.cs create mode 100644 src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs create mode 100644 src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json create mode 100644 src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html create mode 100644 src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 11bfdab2c7414e..3a2adb45e7e6ff 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -24,6 +24,7 @@ Wasm.Build.Tests.HybridGlobalizationTests Wasm.Build.Tests.IcuShardingTests Wasm.Build.Tests.IcuShardingTests2 Wasm.Build.Tests.IcuTests +Wasm.Build.Tests.InitThenDownloadTests Wasm.Build.Tests.InvariantGlobalizationTests Wasm.Build.Tests.InvariantTimezoneTests Wasm.Build.Tests.MainWithArgsTests diff --git a/src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs b/src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs new file mode 100644 index 00000000000000..68d81971bc761e --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs @@ -0,0 +1,43 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Xunit.Abstractions; +using Xunit; +using Wasm.Build.Tests.TestAppScenarios; + +#nullable enable + +namespace Wasm.Build.Tests; + +public class InitThenDownloadTests : AppTestBase +{ + public InitThenDownloadTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Theory] + [InlineData("Debug")] + [InlineData("Release")] + public async Task ResourcesNotFetchedAfterDownloadFinished(string config) + { + CopyTestAsset("InitThenDownload"); + BuildProject(config); + + var result = await RunSdkStyleAppForBuild(new(Configuration: config)); + var resultTestOutput = result.TestOutput.ToList(); + int index = resultTestOutput.FindIndex(s => s == "download finished"); + Assert.True(index > 0); // number of fetched resources cannot be 0 + var fetchingStrings = resultTestOutput.Skip(index + 1).Where(s => s.StartsWith("fetching")).ToList(); + if (fetchingStrings.Count > 0) + { + // fetching only dotnet.native.wasm on init is acceptable + Assert.True(fetchingStrings.Count == 1); + Assert.EndsWith("dotnet.native.wasm", fetchingStrings[0]); + } + } +} diff --git a/src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj b/src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj new file mode 100644 index 00000000000000..09cdc34774595c --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj @@ -0,0 +1,8 @@ + + + net9.0 + browser-wasm + Exe + true + + \ No newline at end of file diff --git a/src/mono/wasm/testassets/InitThenDownload/Program.cs b/src/mono/wasm/testassets/InitThenDownload/Program.cs new file mode 100644 index 00000000000000..bfc1cdb513450f --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/Program.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; + +public partial class Program +{ + public static int Main(string[] args) + { + return 0; + } +} diff --git a/src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs b/src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000000..9ad9b578f20649 --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json b/src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json new file mode 100644 index 00000000000000..b96a94320ba5ee --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json @@ -0,0 +1,10 @@ +{ + "wasmHostProperties": { + "perHostConfig": [ + { + "name": "browser", + "host": "browser" + } + ] + } +} \ No newline at end of file diff --git a/src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html b/src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html new file mode 100644 index 00000000000000..9fb4eb70e8c4c0 --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html @@ -0,0 +1,17 @@ + + + + + + + wasmapp + + + + + + + + + + diff --git a/src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js b/src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js new file mode 100644 index 00000000000000..ca07f4a3662e74 --- /dev/null +++ b/src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js @@ -0,0 +1,24 @@ +import { dotnet } from './_framework/dotnet.js' + +try { + const originalFetch = globalThis.fetch; + globalThis.fetch = (url, fetchArgs) => { + console.log("TestOutput -> fetching " + url); + return originalFetch(url, fetchArgs); + }; + + // optional call to download all assets + await dotnet.download(); + console.log("TestOutput -> download finished"); + + // and later it could be followed by usual + const dotnetRuntime = await dotnet.create(); + + const config = dotnetRuntime.getConfig(); + let exit_code = await dotnetRuntime.runMainAndExit(config.mainAssemblyName, []); + dotnetRuntime.exit(exit_code); // this does not print WASM EXIT message + console.log(`WASM EXIT ${exit_code}`); +} +catch (err) { + exit(2, err); +} From bf4407dbc472122283e2118db93e129cf748e9c9 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 5 Jun 2024 16:11:05 +0200 Subject: [PATCH 3/5] Rename. --- eng/testing/scenarios/BuildWasmAppsJobsList.txt | 2 +- ...{InitThenDownloadTests.cs => DownloadThenInitTests.cs} | 8 ++++---- .../DownloadThenInitTests.csproj} | 0 .../Program.cs | 0 .../Properties/AssemblyInfo.cs | 0 .../runtimeconfig.template.json | 0 .../wwwroot/index.html | 0 .../wwwroot/main.js | 0 8 files changed, 5 insertions(+), 5 deletions(-) rename src/mono/wasm/Wasm.Build.Tests/{InitThenDownloadTests.cs => DownloadThenInitTests.cs} (83%) rename src/mono/wasm/testassets/{InitThenDownload/InitThenDownload.csproj => DownloadThenInitTests/DownloadThenInitTests.csproj} (100%) rename src/mono/wasm/testassets/{InitThenDownload => DownloadThenInitTests}/Program.cs (100%) rename src/mono/wasm/testassets/{InitThenDownload => DownloadThenInitTests}/Properties/AssemblyInfo.cs (100%) rename src/mono/wasm/testassets/{InitThenDownload => DownloadThenInitTests}/runtimeconfig.template.json (100%) rename src/mono/wasm/testassets/{InitThenDownload => DownloadThenInitTests}/wwwroot/index.html (100%) rename src/mono/wasm/testassets/{InitThenDownload => DownloadThenInitTests}/wwwroot/main.js (100%) diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 133cb980e8dbcd..66f024d43aa0fe 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -20,11 +20,11 @@ Wasm.Build.Tests.Blazor.IcuShardingTests Wasm.Build.Tests.Blazor.SignalRClientTests Wasm.Build.Tests.BuildPublishTests Wasm.Build.Tests.ConfigSrcTests +Wasm.Build.Tests.DownloadThenInitTests Wasm.Build.Tests.HybridGlobalizationTests Wasm.Build.Tests.IcuShardingTests Wasm.Build.Tests.IcuShardingTests2 Wasm.Build.Tests.IcuTests -Wasm.Build.Tests.InitThenDownloadTests Wasm.Build.Tests.InvariantGlobalizationTests Wasm.Build.Tests.InvariantTimezoneTests Wasm.Build.Tests.MainWithArgsTests diff --git a/src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs b/src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs similarity index 83% rename from src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs rename to src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs index 68d81971bc761e..27e8fb8ac4a6f1 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InitThenDownloadTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs @@ -13,9 +13,9 @@ namespace Wasm.Build.Tests; -public class InitThenDownloadTests : AppTestBase +public class DownloadThenInitTests : AppTestBase { - public InitThenDownloadTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + public DownloadThenInitTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) : base(output, buildContext) { } @@ -23,9 +23,9 @@ public InitThenDownloadTests(ITestOutputHelper output, SharedBuildPerTestClassFi [Theory] [InlineData("Debug")] [InlineData("Release")] - public async Task ResourcesNotFetchedAfterDownloadFinished(string config) + public async Task NoResourcesFetchedAfterDownloadFinished(string config) { - CopyTestAsset("InitThenDownload"); + CopyTestAsset("DownloadThenInitTests"); BuildProject(config); var result = await RunSdkStyleAppForBuild(new(Configuration: config)); diff --git a/src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj b/src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/InitThenDownload.csproj rename to src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj diff --git a/src/mono/wasm/testassets/InitThenDownload/Program.cs b/src/mono/wasm/testassets/DownloadThenInitTests/Program.cs similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/Program.cs rename to src/mono/wasm/testassets/DownloadThenInitTests/Program.cs diff --git a/src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs b/src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/Properties/AssemblyInfo.cs rename to src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs diff --git a/src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json b/src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/runtimeconfig.template.json rename to src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json diff --git a/src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html b/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/wwwroot/index.html rename to src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html diff --git a/src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js b/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js similarity index 100% rename from src/mono/wasm/testassets/InitThenDownload/wwwroot/main.js rename to src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js From 3cb8ad33cf9e371af2fe952fbcfd34c43d9173d0 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 6 Jun 2024 16:03:28 +0200 Subject: [PATCH 4/5] Feedback: add the new wbt to TestAppScenarios. --- .../scenarios/BuildWasmAppsJobsList.txt | 2 +- .../DownloadThenInitTests.cs | 7 +++--- .../DownloadThenInitTests.csproj | 8 ------- .../DownloadThenInitTests/Program.cs | 12 ---------- .../Properties/AssemblyInfo.cs | 4 ---- .../runtimeconfig.template.json | 10 -------- .../DownloadThenInitTests/wwwroot/index.html | 17 ------------- .../DownloadThenInitTests/wwwroot/main.js | 24 ------------------- .../WasmBasicTestApp/App/wwwroot/main.js | 12 ++++++++++ 9 files changed, 16 insertions(+), 80 deletions(-) rename src/mono/wasm/Wasm.Build.Tests/{ => TestAppScenarios}/DownloadThenInitTests.cs (88%) delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/Program.cs delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html delete mode 100644 src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 66f024d43aa0fe..6b41da61285c23 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -20,7 +20,6 @@ Wasm.Build.Tests.Blazor.IcuShardingTests Wasm.Build.Tests.Blazor.SignalRClientTests Wasm.Build.Tests.BuildPublishTests Wasm.Build.Tests.ConfigSrcTests -Wasm.Build.Tests.DownloadThenInitTests Wasm.Build.Tests.HybridGlobalizationTests Wasm.Build.Tests.IcuShardingTests Wasm.Build.Tests.IcuShardingTests2 @@ -35,6 +34,7 @@ Wasm.Build.Tests.PInvokeTableGeneratorTests Wasm.Build.Tests.RebuildTests Wasm.Build.Tests.SatelliteAssembliesTests Wasm.Build.Tests.TestAppScenarios.AppSettingsTests +Wasm.Build.Tests.TestAppScenarios.DownloadThenInitTests Wasm.Build.Tests.TestAppScenarios.LazyLoadingTests Wasm.Build.Tests.TestAppScenarios.LibraryInitializerTests Wasm.Build.Tests.TestAppScenarios.SatelliteLoadingTests diff --git a/src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs similarity index 88% rename from src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs rename to src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs index 27e8fb8ac4a6f1..0728b0527976b4 100644 --- a/src/mono/wasm/Wasm.Build.Tests/DownloadThenInitTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs @@ -7,11 +7,10 @@ using System.Threading.Tasks; using Xunit.Abstractions; using Xunit; -using Wasm.Build.Tests.TestAppScenarios; #nullable enable -namespace Wasm.Build.Tests; +namespace Wasm.Build.Tests.TestAppScenarios; public class DownloadThenInitTests : AppTestBase { @@ -25,10 +24,10 @@ public DownloadThenInitTests(ITestOutputHelper output, SharedBuildPerTestClassFi [InlineData("Release")] public async Task NoResourcesFetchedAfterDownloadFinished(string config) { - CopyTestAsset("DownloadThenInitTests"); + CopyTestAsset("WasmBasicTestApp", "DownloadThenInitTests", "App"); BuildProject(config); - var result = await RunSdkStyleAppForBuild(new(Configuration: config)); + var result = await RunSdkStyleAppForBuild(new(Configuration: config, TestScenario: "DownloadThenInit")); var resultTestOutput = result.TestOutput.ToList(); int index = resultTestOutput.FindIndex(s => s == "download finished"); Assert.True(index > 0); // number of fetched resources cannot be 0 diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj b/src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj deleted file mode 100644 index 09cdc34774595c..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/DownloadThenInitTests.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - net9.0 - browser-wasm - Exe - true - - \ No newline at end of file diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/Program.cs b/src/mono/wasm/testassets/DownloadThenInitTests/Program.cs deleted file mode 100644 index bfc1cdb513450f..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/Program.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; - -public partial class Program -{ - public static int Main(string[] args) - { - return 0; - } -} diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs b/src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs deleted file mode 100644 index 9ad9b578f20649..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,4 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -[assembly:System.Runtime.Versioning.SupportedOSPlatform("browser")] diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json b/src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json deleted file mode 100644 index b96a94320ba5ee..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/runtimeconfig.template.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "wasmHostProperties": { - "perHostConfig": [ - { - "name": "browser", - "host": "browser" - } - ] - } -} \ No newline at end of file diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html b/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html deleted file mode 100644 index 9fb4eb70e8c4c0..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/index.html +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - wasmapp - - - - - - - - - - diff --git a/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js b/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js deleted file mode 100644 index ca07f4a3662e74..00000000000000 --- a/src/mono/wasm/testassets/DownloadThenInitTests/wwwroot/main.js +++ /dev/null @@ -1,24 +0,0 @@ -import { dotnet } from './_framework/dotnet.js' - -try { - const originalFetch = globalThis.fetch; - globalThis.fetch = (url, fetchArgs) => { - console.log("TestOutput -> fetching " + url); - return originalFetch(url, fetchArgs); - }; - - // optional call to download all assets - await dotnet.download(); - console.log("TestOutput -> download finished"); - - // and later it could be followed by usual - const dotnetRuntime = await dotnet.create(); - - const config = dotnetRuntime.getConfig(); - let exit_code = await dotnetRuntime.runMainAndExit(config.mainAssemblyName, []); - dotnetRuntime.exit(exit_code); // this does not print WASM EXIT message - console.log(`WASM EXIT ${exit_code}`); -} -catch (err) { - exit(2, err); -} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index e426886485d9db..3c8e36199d25e8 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -84,6 +84,15 @@ switch (testCase) { .withRuntimeOptions(['--interp-pgo-logging']) .withInterpreterPgo(true); break; + case "DownloadThenInit": + const originalFetch = globalThis.fetch; + globalThis.fetch = (url, fetchArgs) => { + testOutput("fetching " + url); + return originalFetch(url, fetchArgs); + }; + await dotnet.download(); + testOutput("download finished"); + break; } const { setModuleImports, getAssemblyExports, getConfig, INTERNAL } = await dotnet.create(); @@ -137,6 +146,9 @@ try { await INTERNAL.interp_pgo_save_data(); exit(0); break; + case "DownloadThenInit": + exit(0); + break; default: console.error(`Unknown test case: ${testCase}`); exit(3); From 934f102477185f404a63ad465b2b40a524183cb2 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 6 Jun 2024 16:23:57 +0200 Subject: [PATCH 5/5] Check for re-download instead of specific files. --- .../TestAppScenarios/DownloadThenInitTests.cs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs index 0728b0527976b4..aaa2df9b596557 100644 --- a/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/TestAppScenarios/DownloadThenInitTests.cs @@ -22,7 +22,7 @@ public DownloadThenInitTests(ITestOutputHelper output, SharedBuildPerTestClassFi [Theory] [InlineData("Debug")] [InlineData("Release")] - public async Task NoResourcesFetchedAfterDownloadFinished(string config) + public async Task NoResourcesReFetchedAfterDownloadFinished(string config) { CopyTestAsset("WasmBasicTestApp", "DownloadThenInitTests", "App"); BuildProject(config); @@ -31,12 +31,13 @@ public async Task NoResourcesFetchedAfterDownloadFinished(string config) var resultTestOutput = result.TestOutput.ToList(); int index = resultTestOutput.FindIndex(s => s == "download finished"); Assert.True(index > 0); // number of fetched resources cannot be 0 - var fetchingStrings = resultTestOutput.Skip(index + 1).Where(s => s.StartsWith("fetching")).ToList(); - if (fetchingStrings.Count > 0) + var afterDownload = resultTestOutput.Skip(index + 1).Where(s => s.StartsWith("fetching")).ToList(); + if (afterDownload.Count > 0) { - // fetching only dotnet.native.wasm on init is acceptable - Assert.True(fetchingStrings.Count == 1); - Assert.EndsWith("dotnet.native.wasm", fetchingStrings[0]); + var duringDownload = resultTestOutput.Take(index + 1).Where(s => s.StartsWith("fetching")).ToList(); + var reFetchedResources = afterDownload.Intersect(duringDownload).ToList(); + if (reFetchedResources.Any()) + Assert.Fail($"Resources should not be fetched twice. Re-fetched on init: {string.Join(", ", reFetchedResources)}"); } } }