From d43bdc42e192ff640afeebb50dd200ecb4ccfd2e Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 25 Oct 2022 13:25:01 +0200 Subject: [PATCH 01/18] Removed fixed path separator + duplicated `browser-wasm`. --- eng/testing/tests.wasm.targets | 2 +- src/mono/wasm/build/WasmApp.targets | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index aa1ab7b2cdce5..f75d1c4599104 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -139,7 +139,7 @@ WasmTriggerPublishApp $(BundleTestWasmAppDependsOn);_BundleAOTTestWasmAppForHelix - $(WasmAppHostDir)/WasmAppHost + $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppHost')) --runtime-config $(BundleDir)/WasmTestRunner.runtimeconfig.json $(WasmHostArguments) $(StartArguments) $(WasmXHarnessMonoArgs) $(_AppArgs) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 5cb9d26781b47..f8f2b07a86a6f 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -135,7 +135,7 @@ The path might not have been created yet, for example when creating a new project in VS, so don't use an Exists() check --> - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) From 913c4842abcd3d5f39a10e0e147d837eb2672a84 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 1 Nov 2022 14:30:24 +0100 Subject: [PATCH 02/18] Working fix. --- eng/testing/tests.wasm.targets | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/testing/tests.wasm.targets b/eng/testing/tests.wasm.targets index f75d1c4599104..a90afc11d9e26 100644 --- a/eng/testing/tests.wasm.targets +++ b/eng/testing/tests.wasm.targets @@ -139,10 +139,10 @@ WasmTriggerPublishApp $(BundleTestWasmAppDependsOn);_BundleAOTTestWasmAppForHelix - $([MSBuild]::NormalizeDirectory('$(ArtifactsBinDir)', 'WasmAppHost')) - --runtime-config $(BundleDir)/WasmTestRunner.runtimeconfig.json $(WasmHostArguments) $(StartArguments) $(WasmXHarnessMonoArgs) $(_AppArgs) + <_RuntimeConfigJsonPath>$([MSBuild]::NormalizePath($(BundleDir), 'WasmTestRunner.runtimeconfig.json')) + exec "$([MSBuild]::NormalizePath($(WasmAppHostDir), 'WasmAppHost.dll'))" --runtime-config "$(_RuntimeConfigJsonPath)" $(WasmHostArguments) $(StartArguments) $(WasmXHarnessMonoArgs) $(_AppArgs) From 1d56d6de70b8d89bde93a5fc0c70ea4386a48073 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 2 Nov 2022 13:20:48 +0100 Subject: [PATCH 03/18] Fix for different `OutputPath` conventions. --- src/mono/wasm/build/WasmApp.targets | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index f8f2b07a86a6f..27e1e073cec56 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -135,7 +135,9 @@ The path might not have been created yet, for example when creating a new project in VS, so don't use an Exists() check --> - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and $(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and !$(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFrameworks)' != ''">$([System.IO.Path]::Combine($(OutputPath), $(NetCoreAppCurrent), 'browser-wasm', 'AppBundle')) From 9b775700a2868a526ce768412b8d78910787db3d Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 14 Nov 2022 12:03:15 +0100 Subject: [PATCH 04/18] Fixing the url printed on the console. --- src/mono/wasm/host/BrowserArguments.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/host/BrowserArguments.cs b/src/mono/wasm/host/BrowserArguments.cs index 27ee2fb36978e..c05b700043741 100644 --- a/src/mono/wasm/host/BrowserArguments.cs +++ b/src/mono/wasm/host/BrowserArguments.cs @@ -19,7 +19,10 @@ internal sealed class BrowserArguments public BrowserArguments(CommonConfiguration commonConfig) { CommonConfig = commonConfig; - AppArgs = GetOptions().Parse(commonConfig.RemainingArgs).ToArray(); + List appArgs = GetOptions().Parse(commonConfig.RemainingArgs); + if (CommonConfig.Debugging) + appArgs.Add("--debug"); + AppArgs = appArgs.ToArray(); ParseJsonProperties(CommonConfig.HostConfig.Properties); } From 7f1d5b4ebf9eabbf9c736074e58beab0f9249b35 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Tue, 15 Nov 2022 08:48:13 +0100 Subject: [PATCH 05/18] `ProcessQueryArguments` in test-main.js forces debug to be the 1st arg. --- src/mono/wasm/host/BrowserArguments.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/mono/wasm/host/BrowserArguments.cs b/src/mono/wasm/host/BrowserArguments.cs index c05b700043741..af4984a8afb42 100644 --- a/src/mono/wasm/host/BrowserArguments.cs +++ b/src/mono/wasm/host/BrowserArguments.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Text.Json; using Mono.Options; +using System.Linq; namespace Microsoft.WebAssembly.AppHost; @@ -19,10 +20,8 @@ internal sealed class BrowserArguments public BrowserArguments(CommonConfiguration commonConfig) { CommonConfig = commonConfig; - List appArgs = GetOptions().Parse(commonConfig.RemainingArgs); - if (CommonConfig.Debugging) - appArgs.Add("--debug"); - AppArgs = appArgs.ToArray(); + var appArgs = GetOptions().Parse(commonConfig.RemainingArgs); + AppArgs = CommonConfig.Debugging ? new List {"--debug"}.Concat(appArgs).ToArray() : appArgs.ToArray(); ParseJsonProperties(CommonConfig.HostConfig.Properties); } From bd80440f3e09633c968cc7dac0a657703b718618 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Wed, 23 Nov 2022 16:17:07 +0100 Subject: [PATCH 06/18] Removing special case for WBT. --- src/mono/wasm/build/WasmApp.targets | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 27e1e073cec56..164d5ba953c5e 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -135,8 +135,7 @@ The path might not have been created yet, for example when creating a new project in VS, so don't use an Exists() check --> - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and $(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and !$(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != ''">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFrameworks)' != ''">$([System.IO.Path]::Combine($(OutputPath), $(NetCoreAppCurrent), 'browser-wasm', 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != ''">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and $(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and !$(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFrameworks)' != ''">$([System.IO.Path]::Combine($(OutputPath), $(NetCoreAppCurrent), 'browser-wasm', 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and $(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFramework)' != '' and !$(OutputPath.Contains('browser-wasm'))">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) - <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == '' and '$(TargetFrameworks)' != ''">$([System.IO.Path]::Combine($(OutputPath), $(NetCoreAppCurrent), 'browser-wasm', 'AppBundle')) + <_AppBundleDirForRunCommand Condition="'$(_AppBundleDirForRunCommand)' == ''">$([System.IO.Path]::Combine($(OutputPath), 'browser-wasm', 'AppBundle')) From 41d8c15963a6154a7598d0657fecf2998993a6ec Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Wed, 25 Jan 2023 14:52:37 +0100 Subject: [PATCH 10/18] Update src/mono/wasm/host/BrowserArguments.cs Co-authored-by: Ankit Jain --- src/mono/wasm/host/BrowserArguments.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mono/wasm/host/BrowserArguments.cs b/src/mono/wasm/host/BrowserArguments.cs index de6aa78e1a471..27ee2fb36978e 100644 --- a/src/mono/wasm/host/BrowserArguments.cs +++ b/src/mono/wasm/host/BrowserArguments.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Text.Json; using Mono.Options; -using System.Linq; namespace Microsoft.WebAssembly.AppHost; From b76bd9c67719e05397f7f86a5981f2eb98761245 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 26 Jan 2023 13:04:58 +0100 Subject: [PATCH 11/18] Fetch does not work for node<18 => get rid of json. --- .../Wasm.Build.Tests/data/test-main-7.0.js | 14 ++---- src/mono/wasm/host/BrowserHost.cs | 47 ++++++++++++++----- src/mono/wasm/host/JSEngineHost.cs | 5 +- src/mono/wasm/test-main.js | 13 ++--- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js index b8c9ed01d33dd..0e6026aa93aee 100644 --- a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js +++ b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js @@ -63,15 +63,7 @@ async function getArgs() { queryArguments = Array.from(WScript.Arguments); } - let runArgsJson = initRunArgs({}); - const response = await fetch('/runArgs.json'); - if (response.ok) { - runArgsJson = initRunArgs(await response.json()); - } else { - console.debug(`could not load /runArgs.json: ${response.status}. Ignoring`); - } - let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson; - + const runArgs = queryArguments.length > 0 ? processArguments(queryArguments) : initRunArgs({}); return runArgs; } @@ -92,8 +84,8 @@ function initRunArgs(runArgs) { return runArgs; } -function processArguments(incomingArguments, runArgsJson) { - const runArgs = runArgsJson; +function processArguments(incomingArguments) { + const runArgs = initRunArgs({}); console.log("Incoming arguments: " + incomingArguments.join(' ')); while (incomingArguments && incomingArguments.length > 0) { diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index a592ca7386fff..01d1359b67954 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -13,6 +13,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using Microsoft.WebAssembly.Diagnostics; +using System.Linq; #nullable enable @@ -64,13 +65,6 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke envVars[(string)de.Key] = (string)de.Value; } - var runArgsJson = new RunArgumentsJson(applicationArguments: _args.AppArgs, - runtimeArguments: _args.CommonConfig.RuntimeArguments, - environmentVariables: envVars, - forwardConsoleToWS: _args.ForwardConsoleOutput ?? false, - debugging: _args.CommonConfig.Debugging); - runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); - string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls) ? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) : new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" }; @@ -80,7 +74,12 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke urls, token); - string[] fullUrls = BuildUrls(serverURLs, _args.AppArgs); + string[] fullUrls = BuildUrls(serverURLs, + _args.AppArgs, + _args.CommonConfig.RuntimeArguments, + envVars, + _args.ForwardConsoleOutput ?? false, + _args.CommonConfig.Debugging); Console.WriteLine(); foreach (string url in fullUrls) Console.WriteLine($"App url: {url}"); @@ -157,16 +156,38 @@ private async Task RunConsoleMessagesPump(WebSocket socket, WasmTestMessagesProc } } - private string[] BuildUrls(ServerURLs serverURLs, IEnumerable passThroughArguments) + private string[] BuildUrls(ServerURLs serverURLs, + IEnumerable passThroughArguments, + string[] runtimeArguments, + IDictionary environmentVariables, + bool forwardConsoleToWS=false, + bool debugging = false) { var sb = new StringBuilder(); - foreach (string arg in passThroughArguments) + if (!forwardConsoleToWS) + sb.Append($"arg=--no-forward-console"); + if (debugging) { if (sb.Length > 0) - sb.Append('&'); - - sb.Append($"arg={HttpUtility.UrlEncode(arg)}"); + { + sb.Append($"&arg=--debug"); + } + else + { + sb.Append($"arg=--debug"); + } } + if (sb.Length > 0 && runtimeArguments.Length > 0) + sb.Append('&'); + sb.AppendJoin("&", runtimeArguments.Select(arg => ($"arg=--runtime-arg={HttpUtility.UrlEncode(arg)}"))); + + if (sb.Length > 0 && environmentVariables.Count > 0) + sb.Append('&'); + sb.AppendJoin("&", environmentVariables.Select(arg => $"arg=--setenv={HttpUtility.UrlEncode(arg.Key)}={HttpUtility.UrlEncode(arg.Value)}")); + + if (sb.Length > 0 && passThroughArguments.Any()) + sb.Append('&'); + sb.AppendJoin("&", passThroughArguments.Select(arg => $"arg={HttpUtility.UrlEncode(arg)}")); string query = sb.ToString(); string filename = Path.GetFileName(_args.HTMLPath!); diff --git a/src/mono/wasm/host/JSEngineHost.cs b/src/mono/wasm/host/JSEngineHost.cs index fc77d69818a41..2aad5993a0265 100644 --- a/src/mono/wasm/host/JSEngineHost.cs +++ b/src/mono/wasm/host/JSEngineHost.cs @@ -67,10 +67,6 @@ private async Task RunAsync() if (_args.CommonConfig.Debugging) throw new CommandLineException($"Debugging not supported with {_args.Host}"); - var runArgsJson = new RunArgumentsJson(applicationArguments: Array.Empty(), - runtimeArguments: _args.CommonConfig.RuntimeArguments); - runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); - var args = new List(); if (_args.Host == WasmHost.V8) @@ -88,6 +84,7 @@ private async Task RunAsync() args.Add("--"); } + args.AddRange(_args.CommonConfig.RuntimeArguments); args.AddRange(_args.AppArgs); ProcessStartInfo psi = new() diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 499c7c378a615..12c9cff7b719e 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -63,14 +63,7 @@ async function getArgs() { queryArguments = Array.from(WScript.Arguments); } - let runArgsJson = initRunArgs({}); - const response = await fetch('/runArgs.json'); - if (response.ok) { - runArgsJson = initRunArgs(await response.json()); - } else { - console.debug(`could not load /runArgs.json: ${response.status}. Ignoring`); - } - let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson; + const runArgs = queryArguments.length > 0 ? processArguments(queryArguments) : initRunArgs({}); return runArgs; } @@ -91,8 +84,8 @@ function initRunArgs(runArgs) { return runArgs; } -function processArguments(incomingArguments, runArgsJson) { - const runArgs = runArgsJson; +function processArguments(incomingArguments) { + const runArgs = initRunArgs({}); console.log("Incoming arguments: " + incomingArguments.join(' ')); while (incomingArguments && incomingArguments.length > 0) { From bda0ebbd74769c368e6aee8ef9f13a7374ab5931 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Thu, 26 Jan 2023 16:42:49 +0100 Subject: [PATCH 12/18] Separated runtime args from app args for both hosts. --- .../Wasm.Build.Tests/data/test-main-7.0.js | 15 ++++-- src/mono/wasm/host/BrowserHost.cs | 3 +- src/mono/wasm/host/JSEngineHost.cs | 9 ++-- src/mono/wasm/runtime/run-outer.ts | 53 +++++++++++++++++-- .../wasm/templates/templates/browser/main.js | 3 +- src/mono/wasm/test-main.js | 15 ++++-- 6 files changed, 76 insertions(+), 22 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js index 0e6026aa93aee..1252d6988d4c8 100644 --- a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js +++ b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js @@ -47,12 +47,17 @@ async function getArgs() { queryArguments = process.argv.slice(2); } else if (is_browser) { // We expect to be run by tests/runtime/run.js which passes in the arguments using http parameters - const url = new URL(decodeURI(window.location)); + const allArgs = window.location.search.split("%20--%20"); // mono runtime args -- app args + const runtimeParams = new URLSearchParams(allArgs[0]); + const runtimeValues = runtimeParams.getAll("arg"); + const appParams = new URLSearchParams(allArgs[1]); + const appValues = appParams.getAll("arg"); let urlArguments = [] - for (let param of url.searchParams) { - if (param[0] == "arg") { - urlArguments.push(param[1]); - } + for (let param of runtimeValues) { + urlArguments.push(param); + } + for (let param of appValues) { + urlArguments.push(param); } queryArguments = urlArguments; } else if (v8args !== undefined) { diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index 01d1359b67954..807d9427b582b 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -185,8 +185,7 @@ private string[] BuildUrls(ServerURLs serverURLs, sb.Append('&'); sb.AppendJoin("&", environmentVariables.Select(arg => $"arg=--setenv={HttpUtility.UrlEncode(arg.Key)}={HttpUtility.UrlEncode(arg.Value)}")); - if (sb.Length > 0 && passThroughArguments.Any()) - sb.Append('&'); + sb.Append(" -- "); sb.AppendJoin("&", passThroughArguments.Select(arg => $"arg={HttpUtility.UrlEncode(arg)}")); string query = sb.ToString(); diff --git a/src/mono/wasm/host/JSEngineHost.cs b/src/mono/wasm/host/JSEngineHost.cs index 2aad5993a0265..cf723eb5c5769 100644 --- a/src/mono/wasm/host/JSEngineHost.cs +++ b/src/mono/wasm/host/JSEngineHost.cs @@ -78,13 +78,10 @@ private async Task RunAsync() args.Add(_args.JSPath!); args.AddRange(engineArgs); - if (_args.Host is WasmHost.V8 or WasmHost.JavaScriptCore) - { - // v8/jsc want arguments to the script separated by "--", others don't - args.Add("--"); - } - + // only v8/jsc require arguments to the script separated by "--", for consistency do it for all + args.Add("--"); args.AddRange(_args.CommonConfig.RuntimeArguments); + args.Add("--"); args.AddRange(_args.AppArgs); ProcessStartInfo psi = new() diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index 6c4115a292eef..de520b61eb51e 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -261,9 +261,56 @@ class HostBuilder implements DotnetHostBuilder { throw new Error("URLSearchParams is supported"); } - const params = new URLSearchParams(window.location.search); - const values = params.getAll("arg"); - return this.withApplicationArguments(...values); + const allArgs = window.location.search.split("%20--%20"); + let appArgs; + if (ENVIRONMENT_IS_WEB) // mono runtime args -- app args + { + if (allArgs.length != 2) + throw new Error("URL has wrong format, expected: mono runtime args -- app args"); + appArgs = allArgs[1]; + } + else // hosting engine args -- mono runtime args -- app args + { + if (allArgs.length != 3) + throw new Error("URL has wrong format, expected: hosting engine args -- mono runtime args -- app args"); + appArgs = allArgs[2]; + } + const appParams = new URLSearchParams(appArgs); + const appValues = appParams.getAll("arg"); + return this.withApplicationArguments(...appValues); + } catch (err) { + mono_exit(1, err); + throw err; + } + } + + withRuntimeOptionsFromQuery(): DotnetHostBuilder { + try { + if (!globalThis.window) { + throw new Error("Missing window to the query parameters from"); + } + + if (typeof globalThis.URLSearchParams == "undefined") { + throw new Error("URLSearchParams is supported"); + } + + const allArgs = window.location.search.split("%20--%20"); + let runtimeArgs; + if (ENVIRONMENT_IS_WEB) // mono runtime args -- app args + { + if (allArgs.length != 2) + throw new Error("URL has wrong format, expected: mono runtime args -- app args"); + runtimeArgs = allArgs[0]; + } + else // hosting engine args -- mono runtime args -- app args + { + if (allArgs.length != 3) + throw new Error("URL has wrong format, expected: hosting engine args -- mono runtime args -- app args"); + runtimeArgs = allArgs[1]; + } + const runtimeParams = new URLSearchParams(runtimeArgs); + const runtimeValues = runtimeParams.getAll("arg"); + return this.withRuntimeOptions(runtimeValues); } catch (err) { mono_exit(1, err); throw err; diff --git a/src/mono/wasm/templates/templates/browser/main.js b/src/mono/wasm/templates/templates/browser/main.js index 6d9bd43f7eb7b..f725ea85c9aec 100644 --- a/src/mono/wasm/templates/templates/browser/main.js +++ b/src/mono/wasm/templates/templates/browser/main.js @@ -6,6 +6,7 @@ import { dotnet } from './dotnet.js' const { setModuleImports, getAssemblyExports, getConfig } = await dotnet .withDiagnosticTracing(false) .withApplicationArgumentsFromQuery() + .withRuntimeOptionsFromQuery() .create(); setModuleImports('main.js', { @@ -22,4 +23,4 @@ const text = exports.MyClass.Greeting(); console.log(text); document.getElementById('out').innerHTML = text; -await dotnet.run(); \ No newline at end of file +await dotnet.run(); diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 12c9cff7b719e..ef56ed3b21695 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -47,12 +47,17 @@ async function getArgs() { queryArguments = process.argv.slice(2); } else if (is_browser) { // We expect to be run by tests/runtime/run.js which passes in the arguments using http parameters - const url = new URL(decodeURI(window.location)); + const allArgs = window.location.search.split("%20--%20"); // mono runtime args -- app args + const runtimeParams = new URLSearchParams(allArgs[0]); + const runtimeValues = runtimeParams.getAll("arg"); + const appParams = new URLSearchParams(allArgs[1]); + const appValues = appParams.getAll("arg"); let urlArguments = [] - for (let param of url.searchParams) { - if (param[0] == "arg") { - urlArguments.push(param[1]); - } + for (let param of runtimeValues) { + urlArguments.push(param); + } + for (let param of appValues) { + urlArguments.push(param); } queryArguments = urlArguments; } else if (v8args !== undefined) { From af469921ddbf77556fb70082626747fd03ef4387 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 27 Jan 2023 09:59:02 +0100 Subject: [PATCH 13/18] Revert 7.0 file. --- .../Wasm.Build.Tests/data/test-main-7.0.js | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js index 1252d6988d4c8..bac3f856160c5 100644 --- a/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js +++ b/src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js @@ -10,7 +10,7 @@ /***************************************************************************** * Please don't use this as template for startup code. * There are simpler and better samples like src\mono\sample\wasm\browser\main.js - * This one is not ES6 nor CJS, doesn't use top level await and has edge case polyfills. + * This one is not ES6 nor CJS, doesn't use top level await and has edge case polyfills. * It handles strange things which happen with XHarness. ****************************************************************************/ @@ -47,17 +47,12 @@ async function getArgs() { queryArguments = process.argv.slice(2); } else if (is_browser) { // We expect to be run by tests/runtime/run.js which passes in the arguments using http parameters - const allArgs = window.location.search.split("%20--%20"); // mono runtime args -- app args - const runtimeParams = new URLSearchParams(allArgs[0]); - const runtimeValues = runtimeParams.getAll("arg"); - const appParams = new URLSearchParams(allArgs[1]); - const appValues = appParams.getAll("arg"); + const url = new URL(decodeURI(window.location)); let urlArguments = [] - for (let param of runtimeValues) { - urlArguments.push(param); - } - for (let param of appValues) { - urlArguments.push(param); + for (let param of url.searchParams) { + if (param[0] == "arg") { + urlArguments.push(param[1]); + } } queryArguments = urlArguments; } else if (v8args !== undefined) { @@ -68,7 +63,18 @@ async function getArgs() { queryArguments = Array.from(WScript.Arguments); } - const runArgs = queryArguments.length > 0 ? processArguments(queryArguments) : initRunArgs({}); + let runArgs; + if (queryArguments.length > 0) { + runArgs = processArguments(queryArguments); + } else { + const response = fetch('/runArgs.json') + if (!response.ok) { + console.debug(`could not load /args.json: ${response.status}. Ignoring`); + } + runArgs = await response.json(); + } + runArgs = initRunArgs(runArgs); + return runArgs; } @@ -260,7 +266,7 @@ async function run() { dotnet .withEnvironmentVariable("NodeJSPlatform", process.platform) .withAsyncFlushOnExit(); - + const modulesToLoad = runArgs.environmentVariables["NPM_MODULES"]; if (modulesToLoad) { dotnet.withModuleConfig({ @@ -336,4 +342,4 @@ async function run() { } } -run(); +run(); \ No newline at end of file From dae5d7460c3a23b108e1d141e72c3b0bcdc9d730 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 27 Jan 2023 12:12:15 +0100 Subject: [PATCH 14/18] Focusing on enabling libs debugging for browser. --- src/mono/wasm/host/BrowserHost.cs | 46 +++++----------- src/mono/wasm/host/JSEngineHost.cs | 16 ++++-- src/mono/wasm/runtime/run-outer.ts | 53 ++----------------- .../wasm/templates/templates/browser/main.js | 3 +- src/mono/wasm/test-main.js | 18 +++++-- 5 files changed, 43 insertions(+), 93 deletions(-) diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index 807d9427b582b..a592ca7386fff 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -13,7 +13,6 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; using Microsoft.WebAssembly.Diagnostics; -using System.Linq; #nullable enable @@ -65,6 +64,13 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke envVars[(string)de.Key] = (string)de.Value; } + var runArgsJson = new RunArgumentsJson(applicationArguments: _args.AppArgs, + runtimeArguments: _args.CommonConfig.RuntimeArguments, + environmentVariables: envVars, + forwardConsoleToWS: _args.ForwardConsoleOutput ?? false, + debugging: _args.CommonConfig.Debugging); + runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); + string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls) ? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) : new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" }; @@ -74,12 +80,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke urls, token); - string[] fullUrls = BuildUrls(serverURLs, - _args.AppArgs, - _args.CommonConfig.RuntimeArguments, - envVars, - _args.ForwardConsoleOutput ?? false, - _args.CommonConfig.Debugging); + string[] fullUrls = BuildUrls(serverURLs, _args.AppArgs); Console.WriteLine(); foreach (string url in fullUrls) Console.WriteLine($"App url: {url}"); @@ -156,37 +157,16 @@ private async Task RunConsoleMessagesPump(WebSocket socket, WasmTestMessagesProc } } - private string[] BuildUrls(ServerURLs serverURLs, - IEnumerable passThroughArguments, - string[] runtimeArguments, - IDictionary environmentVariables, - bool forwardConsoleToWS=false, - bool debugging = false) + private string[] BuildUrls(ServerURLs serverURLs, IEnumerable passThroughArguments) { var sb = new StringBuilder(); - if (!forwardConsoleToWS) - sb.Append($"arg=--no-forward-console"); - if (debugging) + foreach (string arg in passThroughArguments) { if (sb.Length > 0) - { - sb.Append($"&arg=--debug"); - } - else - { - sb.Append($"arg=--debug"); - } - } - if (sb.Length > 0 && runtimeArguments.Length > 0) - sb.Append('&'); - sb.AppendJoin("&", runtimeArguments.Select(arg => ($"arg=--runtime-arg={HttpUtility.UrlEncode(arg)}"))); + sb.Append('&'); - if (sb.Length > 0 && environmentVariables.Count > 0) - sb.Append('&'); - sb.AppendJoin("&", environmentVariables.Select(arg => $"arg=--setenv={HttpUtility.UrlEncode(arg.Key)}={HttpUtility.UrlEncode(arg.Value)}")); - - sb.Append(" -- "); - sb.AppendJoin("&", passThroughArguments.Select(arg => $"arg={HttpUtility.UrlEncode(arg)}")); + sb.Append($"arg={HttpUtility.UrlEncode(arg)}"); + } string query = sb.ToString(); string filename = Path.GetFileName(_args.HTMLPath!); diff --git a/src/mono/wasm/host/JSEngineHost.cs b/src/mono/wasm/host/JSEngineHost.cs index 5c1ff06b7a1df..cc80f068a18a5 100644 --- a/src/mono/wasm/host/JSEngineHost.cs +++ b/src/mono/wasm/host/JSEngineHost.cs @@ -65,6 +65,10 @@ private async Task RunAsync() if (_args.CommonConfig.Debugging) throw new CommandLineException($"Debugging not supported with {_args.Host}"); + var runArgsJson = new RunArgumentsJson(applicationArguments: Array.Empty(), + runtimeArguments: _args.CommonConfig.RuntimeArguments); + runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); + var args = new List(); if (_args.Host == WasmHost.V8) @@ -76,11 +80,13 @@ private async Task RunAsync() args.AddRange(_args.CommonConfig.HostArguments); args.Add(_args.JSPath!); - - // only v8/jsc require arguments to the script separated by "--", for consistency do it for all - args.Add("--"); - args.AddRange(_args.CommonConfig.RuntimeArguments); - args.Add("--"); + + if (_args.Host is WasmHost.V8 or WasmHost.JavaScriptCore) + { + // v8/jsc want arguments to the script separated by "--", others don't + args.Add("--"); + } + args.AddRange(_args.AppArgs); ProcessStartInfo psi = new() diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index de520b61eb51e..6c4115a292eef 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -261,56 +261,9 @@ class HostBuilder implements DotnetHostBuilder { throw new Error("URLSearchParams is supported"); } - const allArgs = window.location.search.split("%20--%20"); - let appArgs; - if (ENVIRONMENT_IS_WEB) // mono runtime args -- app args - { - if (allArgs.length != 2) - throw new Error("URL has wrong format, expected: mono runtime args -- app args"); - appArgs = allArgs[1]; - } - else // hosting engine args -- mono runtime args -- app args - { - if (allArgs.length != 3) - throw new Error("URL has wrong format, expected: hosting engine args -- mono runtime args -- app args"); - appArgs = allArgs[2]; - } - const appParams = new URLSearchParams(appArgs); - const appValues = appParams.getAll("arg"); - return this.withApplicationArguments(...appValues); - } catch (err) { - mono_exit(1, err); - throw err; - } - } - - withRuntimeOptionsFromQuery(): DotnetHostBuilder { - try { - if (!globalThis.window) { - throw new Error("Missing window to the query parameters from"); - } - - if (typeof globalThis.URLSearchParams == "undefined") { - throw new Error("URLSearchParams is supported"); - } - - const allArgs = window.location.search.split("%20--%20"); - let runtimeArgs; - if (ENVIRONMENT_IS_WEB) // mono runtime args -- app args - { - if (allArgs.length != 2) - throw new Error("URL has wrong format, expected: mono runtime args -- app args"); - runtimeArgs = allArgs[0]; - } - else // hosting engine args -- mono runtime args -- app args - { - if (allArgs.length != 3) - throw new Error("URL has wrong format, expected: hosting engine args -- mono runtime args -- app args"); - runtimeArgs = allArgs[1]; - } - const runtimeParams = new URLSearchParams(runtimeArgs); - const runtimeValues = runtimeParams.getAll("arg"); - return this.withRuntimeOptions(runtimeValues); + const params = new URLSearchParams(window.location.search); + const values = params.getAll("arg"); + return this.withApplicationArguments(...values); } catch (err) { mono_exit(1, err); throw err; diff --git a/src/mono/wasm/templates/templates/browser/main.js b/src/mono/wasm/templates/templates/browser/main.js index f725ea85c9aec..6d9bd43f7eb7b 100644 --- a/src/mono/wasm/templates/templates/browser/main.js +++ b/src/mono/wasm/templates/templates/browser/main.js @@ -6,7 +6,6 @@ import { dotnet } from './dotnet.js' const { setModuleImports, getAssemblyExports, getConfig } = await dotnet .withDiagnosticTracing(false) .withApplicationArgumentsFromQuery() - .withRuntimeOptionsFromQuery() .create(); setModuleImports('main.js', { @@ -23,4 +22,4 @@ const text = exports.MyClass.Greeting(); console.log(text); document.getElementById('out').innerHTML = text; -await dotnet.run(); +await dotnet.run(); \ No newline at end of file diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index ef56ed3b21695..525126b40fcab 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -68,7 +68,19 @@ async function getArgs() { queryArguments = Array.from(WScript.Arguments); } - const runArgs = queryArguments.length > 0 ? processArguments(queryArguments) : initRunArgs({}); + let runArgsJson; + // ToDo: runArgs should be read for all kinds of hosts, but + // fetch is added to node>=18 and current Windows's emcc node<18 + if (is_browser) + { + const response = await globalThis.fetch('./runArgs.json'); + if (response.ok) { + runArgsJson = await response.json(); + } else { + console.debug(`could not load /runArgs.json: ${response.status}. Ignoring`); + } + } + let runArgs = initRunArgs(queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson); return runArgs; } @@ -89,8 +101,8 @@ function initRunArgs(runArgs) { return runArgs; } -function processArguments(incomingArguments) { - const runArgs = initRunArgs({}); +function processArguments(incomingArguments, runArgsJson) { + const runArgs = runArgsJson ?? initRunArgs({}); console.log("Incoming arguments: " + incomingArguments.join(' ')); while (incomingArguments && incomingArguments.length > 0) { From 12f069a78a102e579c89b9445f2cf09ab52678e7 Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Fri, 27 Jan 2023 18:00:09 +0100 Subject: [PATCH 15/18] Should have been reverted with dae5d7460c3a23b108e1d141e72c3b0bcdc9d730. --- src/mono/wasm/test-main.js | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 525126b40fcab..c165f4eb3497e 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -47,17 +47,12 @@ async function getArgs() { queryArguments = process.argv.slice(2); } else if (is_browser) { // We expect to be run by tests/runtime/run.js which passes in the arguments using http parameters - const allArgs = window.location.search.split("%20--%20"); // mono runtime args -- app args - const runtimeParams = new URLSearchParams(allArgs[0]); - const runtimeValues = runtimeParams.getAll("arg"); - const appParams = new URLSearchParams(allArgs[1]); - const appValues = appParams.getAll("arg"); + const url = new URL(decodeURI(window.location)); let urlArguments = [] - for (let param of runtimeValues) { - urlArguments.push(param); - } - for (let param of appValues) { - urlArguments.push(param); + for (let param of url.searchParams) { + if (param[0] == "arg") { + urlArguments.push(param[1]); + } } queryArguments = urlArguments; } else if (v8args !== undefined) { From a4b28577e13c6b6ffe268ae817d4d52856f8d9dd Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 30 Jan 2023 11:12:41 +0100 Subject: [PATCH 16/18] Fix CI lib tests: avoid referencing undefined properties. --- src/mono/wasm/test-main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index c165f4eb3497e..8e441f87f69f0 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -75,7 +75,7 @@ async function getArgs() { console.debug(`could not load /runArgs.json: ${response.status}. Ignoring`); } } - let runArgs = initRunArgs(queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson); + let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : initRunArgs(runArgsJson); return runArgs; } @@ -97,7 +97,7 @@ function initRunArgs(runArgs) { } function processArguments(incomingArguments, runArgsJson) { - const runArgs = runArgsJson ?? initRunArgs({}); + const runArgs = initRunArgs(runArgsJson); console.log("Incoming arguments: " + incomingArguments.join(' ')); while (incomingArguments && incomingArguments.length > 0) { From 39be37066f4faea7a6b2343c0dc61d8c4842cdae Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz Date: Mon, 30 Jan 2023 17:10:54 +0100 Subject: [PATCH 17/18] In all the cases runArgs should be first populated by defaults that can be later overwritten. --- src/mono/wasm/test-main.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 8e441f87f69f0..e1fb753827b9d 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -70,12 +70,14 @@ async function getArgs() { { const response = await globalThis.fetch('./runArgs.json'); if (response.ok) { - runArgsJson = await response.json(); + runArgsJson = initRunArgs(await response.json()); } else { console.debug(`could not load /runArgs.json: ${response.status}. Ignoring`); } } - let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : initRunArgs(runArgsJson); + if (!runArgsJson) + runArgsJson = initRunArgs({}); + let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson; return runArgs; } @@ -96,9 +98,7 @@ function initRunArgs(runArgs) { return runArgs; } -function processArguments(incomingArguments, runArgsJson) { - const runArgs = initRunArgs(runArgsJson); - +function processArguments(incomingArguments, runArgs) { console.log("Incoming arguments: " + incomingArguments.join(' ')); while (incomingArguments && incomingArguments.length > 0) { const currentArg = incomingArguments[0]; From ef668261234ff16489c4006d1452d49f46b0af0a Mon Sep 17 00:00:00 2001 From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com> Date: Tue, 31 Jan 2023 10:24:58 +0100 Subject: [PATCH 18/18] Update src/mono/wasm/test-main.js Co-authored-by: Ankit Jain --- src/mono/wasm/test-main.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index e1fb753827b9d..979c8a2d90ae0 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -77,8 +77,7 @@ async function getArgs() { } if (!runArgsJson) runArgsJson = initRunArgs({}); - let runArgs = queryArguments.length > 0 ? processArguments(queryArguments, runArgsJson) : runArgsJson; - return runArgs; + return processArguments(queryArguments, runArgsJson); } function initRunArgs(runArgs) {