diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 38a666c61e7341..6995c5db62758c 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -47,3 +47,5 @@ Wasm.Build.Tests.WorkloadTests Wasm.Build.Tests.MT.Blazor.SimpleMultiThreadedTests Wasm.Build.Tests.DebugLevelTests Wasm.Build.Tests.PreloadingTests +Wasm.Build.Tests.EnvVariablesTests +Wasm.Build.Tests.HttpTests diff --git a/src/mono/browser/browser.proj b/src/mono/browser/browser.proj index de5f97ca003809..83e4c3ca3f8e4e 100644 --- a/src/mono/browser/browser.proj +++ b/src/mono/browser/browser.proj @@ -335,7 +335,6 @@ "PropertiesThatTriggerRelinking": [ { "identity": "InvariantTimezone", "defaultValueInRuntimePack": "$(InvariantTimezone)" }, { "identity": "InvariantGlobalization", "defaultValueInRuntimePack": "$(InvariantGlobalization)" }, - { "identity": "WasmEnableStreamingResponse", "defaultValueInRuntimePack": "$(WasmEnableStreamingResponse)" }, { "identity": "WasmNativeStrip", "defaultValueInRuntimePack": "$(WasmNativeStrip)" }, { "identity": "WasmSingleFileBundle", "defaultValueInRuntimePack": "$(WasmSingleFileBundle)" }, { "identity": "WasmEnableSIMD", "defaultValueInRuntimePack": "$(WasmEnableSIMD)" }, diff --git a/src/mono/browser/build/BrowserWasmApp.targets b/src/mono/browser/build/BrowserWasmApp.targets index d73b97ec616e92..d5c3925ff068a5 100644 --- a/src/mono/browser/build/BrowserWasmApp.targets +++ b/src/mono/browser/build/BrowserWasmApp.targets @@ -181,7 +181,7 @@ WasmIcuDataFileName="$(WasmIcuDataFileName)" RuntimeAssetsLocation="$(WasmRuntimeAssetsLocation)" CacheBootResources="$(BlazorCacheBootResources)" - RuntimeConfigJsonPath="$(_WasmRuntimeConfigFilePath)" + RuntimeConfigJsonPath="$(ProjectRuntimeConfigFilePath)" IsAot="$(RunAOTCompilation)" IsMultiThreaded="$(WasmEnableThreads)" > diff --git a/src/mono/browser/build/WasmApp.InTree.targets b/src/mono/browser/build/WasmApp.InTree.targets index 580fed8bf8f2fb..76de4a1b97410a 100644 --- a/src/mono/browser/build/WasmApp.InTree.targets +++ b/src/mono/browser/build/WasmApp.InTree.targets @@ -2,7 +2,6 @@ - diff --git a/src/mono/browser/runtime/cwraps.ts b/src/mono/browser/runtime/cwraps.ts index 72da390f74f8d1..74cf261bc5e1ec 100644 --- a/src/mono/browser/runtime/cwraps.ts +++ b/src/mono/browser/runtime/cwraps.ts @@ -46,7 +46,7 @@ const fn_signatures: SigLine[] = [ [true, "mono_wasm_load_icu_data", "number", ["number"]], [false, "mono_wasm_add_assembly", "number", ["string", "number", "number"]], [true, "mono_wasm_add_satellite_assembly", "void", ["string", "string", "number", "number"]], - [false, "mono_wasm_load_runtime", null, ["number"]], + [false, "mono_wasm_load_runtime", null, ["number", "number", "number", "number"]], [true, "mono_wasm_change_debugger_log_level", "void", ["number"]], [true, "mono_wasm_assembly_load", "number", ["string"]], @@ -173,7 +173,7 @@ export interface t_Cwraps { mono_wasm_load_icu_data(offset: VoidPtr): number; mono_wasm_add_assembly(name: string, data: VoidPtr, size: number): number; mono_wasm_add_satellite_assembly(name: string, culture: string, data: VoidPtr, size: number): void; - mono_wasm_load_runtime(debugLevel: number): void; + mono_wasm_load_runtime(debugLevel: number, propertyCount:number, propertyKeys:CharPtrPtr, propertyValues:CharPtrPtr): void; mono_wasm_change_debugger_log_level(value: number): void; mono_wasm_assembly_load(name: string): MonoAssembly; diff --git a/src/mono/browser/runtime/dotnet.d.ts b/src/mono/browser/runtime/dotnet.d.ts index 85cc8a6b7106e7..07428895e9d44f 100644 --- a/src/mono/browser/runtime/dotnet.d.ts +++ b/src/mono/browser/runtime/dotnet.d.ts @@ -192,6 +192,16 @@ type MonoConfig = { environmentVariables?: { [i: string]: string; }; + /** + * Subset of runtimeconfig.json + */ + runtimeConfig?: { + runtimeOptions?: { + configProperties?: { + [i: string]: string | number | boolean; + }; + }; + }; /** * initial number of workers to add to the emscripten pthread pool */ diff --git a/src/mono/browser/runtime/driver.c b/src/mono/browser/runtime/driver.c index 5a49b7753aa583..120abb1dff92a1 100644 --- a/src/mono/browser/runtime/driver.c +++ b/src/mono/browser/runtime/driver.c @@ -63,8 +63,6 @@ int mono_regression_test_step (int verbose_level, char *image, char *method_name static MonoDomain *root_domain; -#define RUNTIMECONFIG_BIN_FILE "runtimeconfig.bin" - extern void mono_wasm_trace_logger (const char *log_domain, const char *log_level, const char *message, mono_bool fatal, void *user_data); static void @@ -184,7 +182,7 @@ cleanup_runtime_config (MonovmRuntimeConfigArguments *args, void *user_data) static int runtime_initialized = 0; EMSCRIPTEN_KEEPALIVE void -mono_wasm_load_runtime (int debug_level) +mono_wasm_load_runtime (int debug_level, int propertyCount, const char **propertyKeys, const char **propertyValues) { runtime_initialized = 1; const char *interp_opts = ""; @@ -193,34 +191,7 @@ mono_wasm_load_runtime (int debug_level) mono_wasm_link_icu_shim (); #endif - // When the list of app context properties changes, please update RuntimeConfigReservedProperties for - // target _WasmGenerateRuntimeConfig in BrowserWasmApp.targets file - const char *appctx_keys[2]; - appctx_keys [0] = "APP_CONTEXT_BASE_DIRECTORY"; - appctx_keys [1] = "RUNTIME_IDENTIFIER"; - - const char *appctx_values[2]; - appctx_values [0] = "/"; - appctx_values [1] = "browser-wasm"; - - char *file_name = RUNTIMECONFIG_BIN_FILE; - int str_len = strlen (file_name) + 1; // +1 is for the "/" - char *file_path = (char *)malloc (sizeof (char) * (str_len +1)); // +1 is for the terminating null character - int num_char = snprintf (file_path, (str_len + 1), "/%s", file_name); - struct stat buffer; - - assert (num_char > 0 && num_char == str_len); - - if (stat (file_path, &buffer) == 0) { - MonovmRuntimeConfigArguments *arg = (MonovmRuntimeConfigArguments *)malloc (sizeof (MonovmRuntimeConfigArguments)); - arg->kind = 0; - arg->runtimeconfig.name.path = file_path; - monovm_runtimeconfig_initialize (arg, cleanup_runtime_config, file_path); - } else { - free (file_path); - } - - monovm_initialize (2, appctx_keys, appctx_values); + monovm_initialize (propertyCount, propertyKeys, propertyValues); #ifndef INVARIANT_TIMEZONE char* invariant_timezone = monoeg_g_getenv ("DOTNET_SYSTEM_TIMEZONE_INVARIANT"); @@ -237,7 +208,17 @@ int initialize_runtime() { if (runtime_initialized == 1) return 0; - mono_wasm_load_runtime (0); + + const char *appctx_keys[2]; + appctx_keys [0] = "APP_CONTEXT_BASE_DIRECTORY"; + appctx_keys [1] = "RUNTIME_IDENTIFIER"; + + const char *appctx_values[2]; + appctx_values [0] = "/"; + appctx_values [1] = "browser-wasm"; + + // this does not support loading runtimeConfig.json part of boot.config.json + mono_wasm_load_runtime (0, 2, appctx_keys, appctx_values); return 0; } diff --git a/src/mono/browser/runtime/startup.ts b/src/mono/browser/runtime/startup.ts index 60ab49bc0f6611..325caeb4cd1a98 100644 --- a/src/mono/browser/runtime/startup.ts +++ b/src/mono/browser/runtime/startup.ts @@ -13,10 +13,10 @@ import { mono_wasm_init_aot_profiler, mono_wasm_init_devtools_profiler, mono_was import { initialize_marshalers_to_cs } from "./marshal-to-cs"; import { initialize_marshalers_to_js } from "./marshal-to-js"; import { init_polyfills_async } from "./polyfills"; -import { strings_init, utf8ToString } from "./strings"; +import { strings_init, stringToUTF8Ptr, utf8ToString } from "./strings"; import { init_managed_exports } from "./managed-exports"; import { cwraps_internal } from "./exports-internal"; -import { CharPtr, EmscriptenModule, InstantiateWasmCallBack, InstantiateWasmSuccessCallback } from "./types/emscripten"; +import { CharPtr, CharPtrPtr, EmscriptenModule, InstantiateWasmCallBack, InstantiateWasmSuccessCallback, VoidPtr } from "./types/emscripten"; import { wait_for_all_assets } from "./assets"; import { replace_linker_placeholders } from "./exports-binding"; import { endMeasure, MeasuredBlock, startMeasure } from "./profiler"; @@ -28,7 +28,7 @@ import { populateEmscriptenPool, mono_wasm_init_threads } from "./pthreads"; import { currentWorkerThreadEvents, dotnetPthreadCreated, initWorkerThreadEvents, monoThreadInfo } from "./pthreads"; import { mono_wasm_pthread_ptr, update_thread_info } from "./pthreads"; import { jiterpreter_allocate_tables } from "./jiterpreter-support"; -import { localHeapViewU8, malloc } from "./memory"; +import { localHeapViewU8, malloc, setU32 } from "./memory"; import { assertNoProxies } from "./gc-handles"; import { runtimeList } from "./exports"; import { nativeAbort, nativeExit } from "./run"; @@ -617,7 +617,41 @@ export function mono_wasm_load_runtime (): void { if (!loaderHelpers.isDebuggingSupported() || !runtimeHelpers.config.resources!.pdb) { debugLevel = 0; } - cwraps.mono_wasm_load_runtime(debugLevel); + + const runtimeConfigProperties = new Map(); + if (runtimeHelpers.config.runtimeConfig?.runtimeOptions?.configProperties) { + for (const [key, value] of Object.entries(runtimeHelpers.config.runtimeConfig?.runtimeOptions?.configProperties)) { + runtimeConfigProperties.set(key, "" + value); + } + } + runtimeConfigProperties.set("APP_CONTEXT_BASE_DIRECTORY", "/"); + runtimeConfigProperties.set("RUNTIME_IDENTIFIER", "browser-wasm"); + const propertyCount = runtimeConfigProperties.size; + + const buffers:VoidPtr[] = []; + const appctx_keys = malloc(4 * runtimeConfigProperties.size) as any as CharPtrPtr; + const appctx_values = malloc(4 * runtimeConfigProperties.size) as any as CharPtrPtr; + buffers.push(appctx_keys as any); + buffers.push(appctx_values as any); + + let position = 0; + for (const [key, value] of runtimeConfigProperties.entries()) { + const keyPtr = stringToUTF8Ptr(key); + const valuePtr = stringToUTF8Ptr(value); + setU32((appctx_keys as any) + (position * 4), keyPtr); + setU32((appctx_values as any) + (position * 4), valuePtr); + position++; + buffers.push(keyPtr as any); + buffers.push(valuePtr as any); + } + + cwraps.mono_wasm_load_runtime(debugLevel, propertyCount, appctx_keys, appctx_values); + + // free the buffers + for (const buffer of buffers) { + Module._free(buffer); + } + endMeasure(mark, MeasuredBlock.loadRuntime); } catch (err: any) { diff --git a/src/mono/browser/runtime/types/index.ts b/src/mono/browser/runtime/types/index.ts index b651b6828e210f..2be4b9be28ea2e 100644 --- a/src/mono/browser/runtime/types/index.ts +++ b/src/mono/browser/runtime/types/index.ts @@ -144,6 +144,16 @@ export type MonoConfig = { environmentVariables?: { [i: string]: string; }, + /** + * Subset of runtimeconfig.json + */ + runtimeConfig?: { + runtimeOptions?: { + configProperties?: { + [i: string]: string | number | boolean; + } + } + }, /** * initial number of workers to add to the emscripten pthread pool */ diff --git a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets index 6d84ca64f64f23..ba6e8b09fdecc1 100644 --- a/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets +++ b/src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/build/Microsoft.NET.Sdk.WebAssembly.Browser.targets @@ -130,6 +130,7 @@ Copyright (c) .NET Foundation. All rights reserved. $(GenerateBuildWasmBootJsonDependsOn); + GenerateBuildRuntimeConfigurationFiles; ResolveWasmOutputs; @@ -403,6 +404,7 @@ Copyright (c) .NET Foundation. All rights reserved. Extensions="@(WasmBootConfigExtension)" EnvVariables="@(WasmEnvironmentVariable)" Profilers="$(_WasmProfilers)" + RuntimeConfigJsonPath="$(ProjectRuntimeConfigFilePath)" TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" ModuleAfterRuntimeReady="@(WasmModuleAfterRuntimeReady)" @@ -810,6 +812,7 @@ Copyright (c) .NET Foundation. All rights reserved. RuntimeOptions="$(_BlazorWebAssemblyRuntimeOptions)" EnvVariables="@(WasmEnvironmentVariable)" Profilers="$(_WasmProfilers)" + RuntimeConfigJsonPath="$(ProjectRuntimeConfigFilePath)" Extensions="@(WasmBootConfigExtension)" TargetFrameworkVersion="$(TargetFrameworkVersion)" ModuleAfterConfigLoaded="@(WasmModuleAfterConfigLoaded)" diff --git a/src/mono/wasi/build/WasiApp.props b/src/mono/wasi/build/WasiApp.props index b2f79014de3ec3..fed1e144913b91 100644 --- a/src/mono/wasi/build/WasiApp.props +++ b/src/mono/wasi/build/WasiApp.props @@ -10,4 +10,16 @@ + + + + _PrepareForNestedPublish; + $(WasmNestedPublishAppDependsOn); + + + $(PrepareInputsForWasmBuildDependsOn); + _WasmGetRuntimeConfigPath; + + + diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index 8eaf68c07bd1eb..a0133219afb7cb 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -11,12 +11,14 @@ + _WasmGenerateRuntimeConfig; $(WasmLinkDotNetDependsOn); _WasiLinkDotNet; $(WasmGenerateAppBundleDependsOn); + _WasmGenerateRuntimeConfig; _GetWasiGenerateAppBundleDependencies; _WasiGenerateAppBundle; _GenerateRunWasmtimeScript; @@ -46,6 +48,44 @@ + + + <_RuntimeConfigReservedProperties Include="RUNTIME_IDENTIFIER"/> + <_RuntimeConfigReservedProperties Include="APP_CONTEXT_BASE_DIRECTORY"/> + + + + + + + + + + + + + <_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == '$(AssemblyName)' and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity) + <_WasmRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' == '' and $(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) + <_ParsedRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' != ''">$([System.IO.Path]::GetDirectoryName($(_WasmRuntimeConfigFilePath)))\runtimeconfig.bin + + + + + + <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) + + + + <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) + + + diff --git a/src/mono/wasm/Wasm.Build.Tests/HttpTests.cs b/src/mono/wasm/Wasm.Build.Tests/HttpTests.cs new file mode 100644 index 00000000000000..c33e68ffd32c22 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/HttpTests.cs @@ -0,0 +1,36 @@ +// 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 System.Text.RegularExpressions; +using Xunit.Abstractions; +using Xunit; + +#nullable enable + +namespace Wasm.Build.Tests; + +public class HttpTests : WasmTemplateTestsBase +{ + public HttpTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + [Fact] + // testing that WasmEnableStreamingResponse=false MSbuild prop is passed to the app and HTTP behaves as expected + public async Task HttpNoStreamingTest() + { + Configuration config = Configuration.Release; + ProjectInfo info = CopyTestAsset(config, false, TestAsset.WasmBasicTestApp, "HttpTest"); + + BuildProject(info, config, new BuildOptions(ExtraMSBuildArgs: "-p:WasmEnableStreamingResponse=false",AssertAppBundle: false), isNativeBuild: false); + + var result = await RunForBuildWithDotnetRun(new BrowserRunOptions(Configuration: config, TestScenario: "HttpNoStreamingTest")); + Assert.Contains("AppContext WasmEnableStreamingResponse=false", result.TestOutput); + Assert.Contains("baz=boo", result.TestOutput); + } +} diff --git a/src/mono/wasm/build/WasmApp.Common.props b/src/mono/wasm/build/WasmApp.Common.props index f74fa9acda0be1..9884d97b1d20bf 100644 --- a/src/mono/wasm/build/WasmApp.Common.props +++ b/src/mono/wasm/build/WasmApp.Common.props @@ -18,7 +18,6 @@ - _PrepareForNestedPublish; _WasmBuildAppCore; diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index 7941eba7030a0c..a65a79440aafcd 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -125,12 +125,10 @@ _ReadWasmProps; _SetWasmBuildNativeDefaults; _GetDefaultWasmAssembliesToBundle; - _WasmGetRuntimeConfigPath; $(WasmGenerateAppBundleDependsOn); - _WasmGenerateRuntimeConfig; @@ -152,7 +150,6 @@ _WasmSelectRuntimeComponentsForLinking; _WasmCompileAssemblyBitCodeFilesForAOT; _WasmCalculateInitialHeapSizeFromBitcodeFiles; - _WasmGenerateRuntimeConfig; _WasmWriteRspForCompilingNativeSourceFiles; _WasmCompileNativeSourceFiles; _GenerateObjectFilesForSingleFileBundle; @@ -350,14 +347,6 @@ - - - <_MainAssemblyPath Condition="'%(WasmAssembliesToBundle.FileName)' == '$(AssemblyName)' and '%(WasmAssembliesToBundle.Extension)' == '.dll' and $(WasmGenerateAppBundle) == 'true'">%(WasmAssembliesToBundle.Identity) - <_WasmRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' == '' and $(_MainAssemblyPath) != ''">$([System.IO.Path]::ChangeExtension($(_MainAssemblyPath), '.runtimeconfig.json')) - <_ParsedRuntimeConfigFilePath Condition="'$(_WasmRuntimeConfigFilePath)' != ''">$([System.IO.Path]::GetDirectoryName($(_WasmRuntimeConfigFilePath)))\runtimeconfig.bin - - - - - - <_RuntimeConfigReservedProperties Include="RUNTIME_IDENTIFIER"/> - <_RuntimeConfigReservedProperties Include="APP_CONTEXT_BASE_DIRECTORY"/> - - - - - - - - - - @@ -482,16 +451,6 @@ - - - <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) - - - - <_WasmRuntimeConfigFilePath Condition="$([System.String]::new(%(PublishItemsOutputGroupOutputs.Identity)).EndsWith('$(AssemblyName).runtimeconfig.json'))">@(PublishItemsOutputGroupOutputs) - - - diff --git a/src/mono/wasm/build/WasmApp.LocalBuild.targets b/src/mono/wasm/build/WasmApp.LocalBuild.targets index bedbba30750c07..31dcd68be03259 100644 --- a/src/mono/wasm/build/WasmApp.LocalBuild.targets +++ b/src/mono/wasm/build/WasmApp.LocalBuild.targets @@ -24,7 +24,6 @@ - true diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/HttpTest.cs b/src/mono/wasm/testassets/WasmBasicTestApp/App/HttpTest.cs new file mode 100644 index 00000000000000..4a24a3ca39d3db --- /dev/null +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/HttpTest.cs @@ -0,0 +1,48 @@ +// 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.Net.Http; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices.JavaScript; + +public partial class HttpTest +{ + private static bool FeatureEnableStreamingResponse { get; } = AppContext.TryGetSwitch("System.Net.Http.WasmEnableStreamingResponse", out bool value) ? value : true; + + [JSExport] + public static async Task HttpNoStreamingTest() + { + Console.WriteLine($"AppContext FeatureEnableStreamingResponse={FeatureEnableStreamingResponse}"); + if(FeatureEnableStreamingResponse) + { + Console.WriteLine("FeatureEnableStreamingResponse is true, this test is not valid."); + return -1; + } + + var uri = GetOriginUrl() + "/main.js"; + using var client = new HttpClient(); + using var response = await client.GetAsync(uri); + + var contentType = response.Content.GetType(); + + Console.WriteLine("response.Content is " + contentType.FullName); + if (contentType == typeof(StreamContent)) + { + Console.WriteLine($"response.Content is {contentType.FullName}"); + return -2; + } + + return 42; + } + + public static string GetOriginUrl() + { + using var globalThis = JSHost.GlobalThis; + using var document = globalThis.GetPropertyAsJSObject("document"); + using var location = globalThis.GetPropertyAsJSObject("location"); + return location.GetPropertyAsString("origin"); + } +} diff --git a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js index b4a5b04d5af5c6..5d8213a12ab908 100644 --- a/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js +++ b/src/mono/wasm/testassets/WasmBasicTestApp/App/wwwroot/main.js @@ -166,6 +166,8 @@ switch (testCase) { case "EnvVariablesTest": dotnet.withEnvironmentVariable("foo", "bar"); break; + case "HttpNoStreamingTest": + break; case "BrowserProfilerTest": break; case "OverrideBootConfigName": @@ -256,6 +258,29 @@ try { exports.MemoryTest.Run(); exit(0); break; + case "HttpNoStreamingTest": + console.log("not ready yet") + const myExportsHttp = await getAssemblyExports(config.mainAssemblyName); + const httpNoStreamingTest = myExportsHttp.HttpTest.HttpNoStreamingTest; + console.log("ready"); + if (config.runtimeConfig.runtimeOptions.configProperties) { + const configProperties = config.runtimeConfig.runtimeOptions.configProperties; + console.log("configProperties: " + Object.keys(configProperties).length); + const wasmEnableStreamingResponse = configProperties["System.Net.Http.WasmEnableStreamingResponse"]; + if (wasmEnableStreamingResponse === undefined) { + exit(2); + } + if (wasmEnableStreamingResponse === true) { + exit(3); + } + } + + const retHttp = await httpNoStreamingTest(); + document.getElementById("out").innerHTML = retHttp; + console.debug(`ret: ${retHttp}`); + + exit(retHttp == 42 ? 0 : 1); + break; case "EnvVariablesTest": console.log("not ready yet") const myExportsEnv = await getAssemblyExports(config.mainAssemblyName); diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs index f8c0761c76494b..846a7b3bfe65c6 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs @@ -104,6 +104,10 @@ public class BootJsonData /// Gets or sets environment variables. /// public System.Collections.Generic.Dictionary environmentVariables { get; set; } + /// + /// Subset of runtimeconfig.json + /// + public RuntimeConfigData runtimeConfig { get; set; } /// /// Gets or sets diagnostic tracing. @@ -121,6 +125,25 @@ public class BootJsonData public int? pthreadPoolUnusedSize { get; set; } } +/// +/// Subset of runtimeconfig.json +/// +public class RuntimeConfigData +{ + /// + /// Runtime options + /// + public RuntimeOptionsData runtimeOptions { get; set; } +} + +public class RuntimeOptionsData +{ + /// + /// Config properties for the runtime + /// + public Dictionary configProperties { get; set; } +} + public class ResourcesData { /// 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 b84b5a3109b9dd..b48a733b739ae1 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -62,6 +62,8 @@ public class GenerateWasmBootJson : Task public string[]? Profilers { get; set; } + public string? RuntimeConfigJsonPath { get; set; } + public string StartupMemoryCache { get; set; } public string Jiterpreter { get; set; } @@ -435,6 +437,14 @@ private void WriteBootConfig(string entryAssemblyName) result.extensions[key] = config; } } + + if (RuntimeConfigJsonPath != null && File.Exists(RuntimeConfigJsonPath)) + { + using var fs = File.OpenRead(RuntimeConfigJsonPath); + var runtimeConfig = JsonSerializer.Deserialize(fs, BootJsonBuilderHelper.JsonOptions); + result.runtimeConfig = runtimeConfig; + } + Profilers ??= Array.Empty(); var browserProfiler = Profilers.FirstOrDefault(p => p.StartsWith("browser:")); if (browserProfiler != null) diff --git a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs index bea5d8fbf7eb67..87980f370ff824 100644 --- a/src/tasks/WasmAppBuilder/WasmAppBuilder.cs +++ b/src/tasks/WasmAppBuilder/WasmAppBuilder.cs @@ -397,7 +397,7 @@ protected override bool ExecuteInternal() var envs = (JsonElement)valueObject!; foreach (var env in envs.EnumerateObject()) { - bootConfig.environmentVariables[env.Name] = env.Value.GetString(); + bootConfig.environmentVariables[env.Name] = env.Value.GetString()!; } } else if (string.Equals(name, nameof(BootJsonData.diagnosticTracing), StringComparison.OrdinalIgnoreCase)) @@ -421,6 +421,13 @@ protected override bool ExecuteInternal() bootConfig.environmentVariables["DOTNET_WasmPerfInstrumentation"] = browserProfiler.Substring("browser:".Length); } + if (RuntimeConfigJsonPath != null && File.Exists(RuntimeConfigJsonPath)) + { + using var fs = File.OpenRead(RuntimeConfigJsonPath); + var runtimeConfig = JsonSerializer.Deserialize(fs, BootJsonBuilderHelper.JsonOptions); + bootConfig.runtimeConfig = runtimeConfig; + } + foreach (ITaskItem env in EnvVariables ?? Enumerable.Empty()) { bootConfig.environmentVariables ??= new();