From cda65db665af9d27c4e7ecf50ea69efdf26cb8c7 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 26 Jun 2023 17:15:42 +0200 Subject: [PATCH 1/7] wip --- .../features/timezone-invariant-mode.md | 12 +++ ...rosoft.NET.Sdk.WebAssembly.Browser.targets | 2 + .../sample/wasm/browser-advanced/Program.cs | 20 ++++ .../Wasm.Advanced.Sample.csproj | 1 + src/mono/wasi/build/WasiApp.Native.targets | 3 +- src/mono/wasi/build/WasiApp.targets | 1 + src/mono/wasi/runtime/driver.c | 4 + src/mono/wasi/wasi.proj | 2 +- .../InvariantTimezoneTests.cs | 97 +++++++++++++++++++ src/mono/wasm/build/WasmApp.Native.targets | 1 + src/mono/wasm/build/WasmApp.targets | 1 + src/mono/wasm/runtime/driver.c | 4 + src/mono/wasm/runtime/es6/dotnet.es6.lib.js | 2 +- src/mono/wasm/wasm.proj | 2 +- 14 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 docs/design/features/timezone-invariant-mode.md create mode 100644 src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs diff --git a/docs/design/features/timezone-invariant-mode.md b/docs/design/features/timezone-invariant-mode.md new file mode 100644 index 0000000000000..e66da8ea5407d --- /dev/null +++ b/docs/design/features/timezone-invariant-mode.md @@ -0,0 +1,12 @@ +# Timezone Invariant Mode + +Author: [Pavel Savara](https://github.com/pavelsavara) + +It's currently only available for Browser OS + +- you enable it in project file: + ```xml + + true + + ``` 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 5cf78e89c3c15..60d60e7416898 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 @@ -47,6 +47,8 @@ Copyright (c) .NET Foundation. All rights reserved. false + true + false false true false diff --git a/src/mono/sample/wasm/browser-advanced/Program.cs b/src/mono/sample/wasm/browser-advanced/Program.cs index af6ca78e0bbda..bec9cb3256b4c 100644 --- a/src/mono/sample/wasm/browser-advanced/Program.cs +++ b/src/mono/sample/wasm/browser-advanced/Program.cs @@ -13,6 +13,26 @@ public partial class Test public static int Main(string[] args) { Console.WriteLine ("Hello, World!"); + + var start = DateTime.UtcNow; + var timezonesCount = TimeZoneInfo.GetSystemTimeZones().Count; + var end = DateTime.UtcNow; + Console.WriteLine($"Found {timezonesCount} timezones in the TZ database in {end-start}"); + + TimeZoneInfo utc = TimeZoneInfo.FindSystemTimeZoneById("UTC"); + Console.WriteLine($"{utc.DisplayName} BaseUtcOffset is {utc.BaseUtcOffset}"); + + try + { + TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo"); + Console.WriteLine($"{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}"); + } + catch (TimeZoneNotFoundException tznfe) + { + Console.WriteLine($"Could not find Asia/Tokyo: {tznfe.Message}"); + } + + return 0; } diff --git a/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj b/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj index d37b17495581b..782efa96a8236 100644 --- a/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj +++ b/src/mono/sample/wasm/browser-advanced/Wasm.Advanced.Sample.csproj @@ -14,6 +14,7 @@ <_ServeHeaders>$(_ServeHeaders) -h "Content-Security-Policy: default-src 'self' 'wasm-unsafe-eval'" browser; + true diff --git a/src/mono/wasi/build/WasiApp.Native.targets b/src/mono/wasi/build/WasiApp.Native.targets index e0e43c0edffc4..8fd82eaca343f 100644 --- a/src/mono/wasi/build/WasiApp.Native.targets +++ b/src/mono/wasi/build/WasiApp.Native.targets @@ -168,8 +168,9 @@ <_WasmCommonCFlags Include="-DGEN_PINVOKE=1" /> - <_WasmCommonCFlags Condition="'$(WasmSingleFileBundle)' == 'true'" Include="-DWASM_SINGLE_FILE=1" /> + <_WasmCommonCFlags Condition="'$(WasmSingleFileBundle)' == 'true'" Include="-DWASM_SINGLE_FILE=1" /> <_WasmCommonCFlags Condition="'$(InvariantGlobalization)' == 'true'" Include="-DINVARIANT_GLOBALIZATION=1" /> + <_WasmCommonCFlags Condition="'$(InvariantTimezone)' == 'true'" Include="-DINVARIANT_TIMEZONE=1" /> diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index c39ec3a0a880f..2a711e5eeea2f 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -29,6 +29,7 @@ - $(WasmProfilers) - Profilers to use - $(AOTProfilePath) - profile data file to be used for profile-guided optimization - $(InvariantGlobalization) - Whenever to disable ICU. Defaults to false. + - $(InvariantTimezone) - Whenever to disable Timezone database. Defaults to false. - $(WasmResolveAssembliesBeforeBuild) - Resolve the assembly dependencies. Defaults to false - $(WasmAssemblySearchPaths) - used for resolving assembly dependencies diff --git a/src/mono/wasi/runtime/driver.c b/src/mono/wasi/runtime/driver.c index d6a51f9be51b0..98fbe1fef04bb 100644 --- a/src/mono/wasi/runtime/driver.c +++ b/src/mono/wasi/runtime/driver.c @@ -63,7 +63,9 @@ int32_t monoeg_g_hasenv(const char *variable); void mono_free (void*); int32_t mini_parse_debug_option (const char *option); char *mono_method_get_full_name (MonoMethod *method); +#ifndef INVARIANT_TIMEZONE extern void mono_register_timezones_bundle (void); +#endif /* INVARIANT_TIMEZONE */ #ifdef WASM_SINGLE_FILE extern void mono_register_assemblies_bundle (void); #ifndef INVARIANT_GLOBALIZATION @@ -439,7 +441,9 @@ mono_wasm_load_runtime (const char *unused, int debug_level) mini_parse_debug_option ("top-runtime-invoke-unhandled"); +#ifndef INVARIANT_TIMEZONE mono_register_timezones_bundle (); +#endif /* INVARIANT_TIMEZONE */ #ifdef WASM_SINGLE_FILE mono_register_assemblies_bundle (); #endif diff --git a/src/mono/wasi/wasi.proj b/src/mono/wasi/wasi.proj index fbf434ce4964a..d601f2c9e09ab 100644 --- a/src/mono/wasi/wasi.proj +++ b/src/mono/wasi/wasi.proj @@ -66,7 +66,7 @@ - + <_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data')) <_WasmTimezonesBundleObjectFile>wasm-bundled-timezones.o diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs new file mode 100644 index 0000000000000..1f10c80e14a38 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs @@ -0,0 +1,97 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Collections.Generic; +using System.IO; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class InvariantTimezoneTests : BuildTestBase + { + public InvariantTimezoneTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + public static IEnumerable InvariantTimezoneTestData(bool aot, RunHost host) + => ConfigWithAOTData(aot) + .Multiply( + new object?[] { null }, + new object?[] { false }, + new object?[] { true }) + .WithRunHosts(host) + .UnwrapItemsAsArrays(); + + [Theory] + [MemberData(nameof(InvariantTimezoneTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + [MemberData(nameof(InvariantTimezoneTestData), parameters: new object[] { /*aot*/ true, RunHost.All })] + public void AOT_InvariantTimezone(BuildArgs buildArgs, bool? invariantTimezone, RunHost host, string id) + => TestInvariantTimezone(buildArgs, invariantTimezone, host, id); + + [Theory] + [MemberData(nameof(InvariantTimezoneTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + public void RelinkingWithoutAOT(BuildArgs buildArgs, bool? invariantTimezone, RunHost host, string id) + => TestInvariantTimezone(buildArgs, invariantTimezone, host, id, + extraProperties: "true", + dotnetWasmFromRuntimePack: false); + + private void TestInvariantTimezone(BuildArgs buildArgs, bool? invariantTimezone, + RunHost host, string id, string extraProperties="", bool? dotnetWasmFromRuntimePack=null) + { + string projectName = $"invariant_{invariantTimezone?.ToString() ?? "unset"}"; + if (invariantTimezone != null) + extraProperties = $"{extraProperties}{invariantTimezone}"; + + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, extraProperties); + + if (dotnetWasmFromRuntimePack == null) + dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + + string programText = @" + using System; + + // https://github.com/dotnet/runtime/blob/main/docs/design/features/timezone-invariant-mode.md + + var timezonesCount = TimeZoneInfo.GetSystemTimeZones().Count; + Console.WriteLine($""Found {timezonesCount} timezones in the TZ database""); + + TimeZoneInfo utc = TimeZoneInfo.FindSystemTimeZoneById(""UTC""); + Console.WriteLine($""{utc.DisplayName} BaseUtcOffset is {utc.BaseUtcOffset}""); + + try + { + TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(""Asia/Tokyo""); + Console.WriteLine($""{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}""); + } + catch (TimeZoneNotFoundException tznfe) + { + Console.WriteLine($""Could not find Asia/Tokyo: {tznfe.Message}""); + } + + return 42; + "; + + BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); + + string output = RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id); + Assert.Contains("UTC BaseUtcOffset is 0", output); + if (invariantGlobalization == true) + { + Assert.Contains("Could not find Asia/Tokyo", output); + } + else + { + Assert.Contains("Asia/Tokyo BaseUtcOffset is 09:00:00", output); + } + } + } +} diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 310d77cf36d6d..403096064dd47 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -219,6 +219,7 @@ <_EmccCFlags Include="-DENABLE_AOT=1" Condition="'$(_WasmShouldAOT)' == 'true'" /> <_EmccCFlags Include="-DDRIVER_GEN=1" Condition="'$(_WasmShouldAOT)' == 'true'" /> <_EmccCFlags Include="-DINVARIANT_GLOBALIZATION=1" Condition="'$(InvariantGlobalization)' == 'true'" /> + <_EmccCFlags Include="-DINVARIANT_TIMEZONE=1" Condition="'$(InvariantTimezone)' == 'true'" /> <_EmccCFlags Include="-DLINK_ICALLS=1" Condition="'$(WasmLinkIcalls)' == 'true'" /> <_EmccCFlags Include="-DENABLE_AOT_PROFILER=1" Condition="$(WasmProfilers.Contains('aot'))" /> <_EmccCFlags Include="-DENABLE_BROWSER_PROFILER=1" Condition="$(WasmProfilers.Contains('browser'))" /> diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 929089695e14a..b243b3d64b03d 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -28,6 +28,7 @@ - $(WasmProfilers) - Profilers to use - $(AOTProfilePath) - profile data file to be used for profile-guided optimization - $(InvariantGlobalization) - Whenever to disable ICU. Defaults to false. + - $(InvariantTimezone) - Whenever to disable Timezone database. Defaults to false. - $(HybridGlobalization) - Whenever to enable reduced ICU + native platform functions. Defaults to false and can be set only for InvariantGlobalization=false, WasmIncludeFullIcuData=false and empty WasmIcuDataFileName. - $(WasmResolveAssembliesBeforeBuild) - Resolve the assembly dependencies. Defaults to false diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index 51cd2497a1b9d..551d1b4ca8709 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -54,7 +54,9 @@ int monoeg_g_setenv(const char *variable, const char *value, int overwrite); int32_t mini_parse_debug_option (const char *option); char *mono_method_get_full_name (MonoMethod *method); +#ifndef INVARIANT_TIMEZONE extern void mono_register_timezones_bundle (void); +#endif /* INVARIANT_TIMEZONE */ extern void mono_wasm_set_entrypoint_breakpoint (const char* assembly_name, int method_token); static void mono_wasm_init_finalizer_thread (void); @@ -473,7 +475,9 @@ mono_wasm_load_runtime (const char *unused, int debug_level) mini_parse_debug_option ("top-runtime-invoke-unhandled"); +#ifndef INVARIANT_TIMEZONE mono_register_timezones_bundle (); +#endif /* INVARIANT_TIMEZONE */ mono_dl_fallback_register (wasm_dl_load, wasm_dl_symbol, NULL, NULL); mono_wasm_install_get_native_to_interp_tramp (get_native_to_interp); diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index cea78ac93822a..8ea0b7deb2f89 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -137,6 +137,7 @@ linked_functions = [...linked_functions, "mono_wasm_install_js_worker_interop", "mono_wasm_uninstall_js_worker_interop", ] +#endif if (ENABLE_AOT_PROFILER) { linked_functions = [...linked_functions, @@ -153,7 +154,6 @@ if (ENABLE_AOT_PROFILER) { ] } -#endif if (!DISABLE_LEGACY_JS_INTEROP) { linked_functions = [...linked_functions, "mono_wasm_invoke_js_with_args_ref", diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index c150a1fe09d31..98a62905600f7 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -80,7 +80,7 @@ - + <_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data')) <_WasmTimezonesBundleSourceFile>wasm-bundled-timezones.c From 754499812bed17d2a52c7df6b30610dc2765ca7f Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 26 Jun 2023 18:17:02 +0200 Subject: [PATCH 2/7] fix --- src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs index 1f10c80e14a38..bf14e83da6898 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs @@ -84,7 +84,7 @@ private void TestInvariantTimezone(BuildArgs buildArgs, bool? invariantTimezone, string output = RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id); Assert.Contains("UTC BaseUtcOffset is 0", output); - if (invariantGlobalization == true) + if (invariantTimezone == true) { Assert.Contains("Could not find Asia/Tokyo", output); } From 75a14d174dd8da6a550c82ab01b64eb47145dff0 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 27 Jun 2023 22:35:26 +0200 Subject: [PATCH 3/7] WBT --- eng/testing/scenarios/BuildWasmAppsJobsList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index e84e70c3f8f73..64f6abf5a1a65 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -14,6 +14,7 @@ Wasm.Build.Tests.ConfigSrcTests Wasm.Build.Tests.IcuShardingTests Wasm.Build.Tests.HybridGlobalizationTests Wasm.Build.Tests.InvariantGlobalizationTests +Wasm.Build.Tests.InvariantTimezoneTests Wasm.Build.Tests.MainWithArgsTests Wasm.Build.Tests.NativeBuildTests Wasm.Build.Tests.NativeLibraryTests From 670b5138c6179091b68d8152ca9c2e86278db056 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 28 Jun 2023 13:39:15 +0200 Subject: [PATCH 4/7] feedback --- .../Wasi.Build.Tests/WasiTemplateTests.cs | 34 +++++++++++++++---- .../InvariantGlobalizationTests.cs | 21 +----------- .../InvariantTimezoneTests.cs | 26 +------------- .../InvariantGlobalization.cs | 16 +++++++++ .../InvariantTimezone.cs | 21 ++++++++++++ 5 files changed, 67 insertions(+), 51 deletions(-) create mode 100644 src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantGlobalization.cs create mode 100644 src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantTimezone.cs diff --git a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs index cad7521379378..5a5a485fd8880 100644 --- a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs +++ b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs @@ -74,19 +74,19 @@ public void ConsoleBuildThenPublish(string config) UseCache: false)); } - public static TheoryData TestDataForConsolePublishAndRun() + public static TheoryData TestDataForConsolePublishAndRun() { - var data = new TheoryData(); - data.Add("Debug", false); - data.Add("Debug", true); - data.Add("Release", false); // Release relinks by default + var data = new TheoryData(); + data.Add("Debug", false, false); + data.Add("Debug", true, true); + data.Add("Release", false, false); // Release relinks by default return data; } [ConditionalTheory(typeof(BuildTestBase), nameof(IsUsingWorkloads))] [ActiveIssue("https://github.com/dotnet/runtime/issues/82515", TestPlatforms.Windows)] [MemberData(nameof(TestDataForConsolePublishAndRun))] - public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinking) + public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinking, bool invariantTimezone) { string id = $"{config}_{Path.GetRandomFileName()}"; string projectFile = CreateWasmTemplateProject(id, "wasiconsole"); @@ -96,6 +96,8 @@ public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinkin string extraProperties = "true"; if (relinking) extraProperties += "true"; + if (invariantTimezone) + extraProperties += "true"; AddItemsPropertiesToProject(projectFile, extraProperties); @@ -125,6 +127,15 @@ public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinkin Assert.Contains("args[0] = x", res.Output); Assert.Contains("args[1] = y", res.Output); Assert.Contains("args[2] = z", res.Output); + if(invariantTimezone) + { + Assert.Contains("Could not find Asia/Tokyo", res.Output); + } + else + { + Assert.Contains("Asia/Tokyo BaseUtcOffset is 09:00:00", res.Output); + } + } private static readonly string s_simpleMainWithArgs = """ @@ -133,6 +144,17 @@ public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinkin Console.WriteLine("Hello, Wasi Console!"); for (int i = 0; i < args.Length; i ++) Console.WriteLine($"args[{i}] = {args[i]}"); + + try + { + TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(""Asia/Tokyo""); + Console.WriteLine($""{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}""); + } + catch (TimeZoneNotFoundException tznfe) + { + Console.WriteLine($""Could not find Asia/Tokyo: {tznfe.Message}""); + } + return 42; """; } diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs index 41dac50141cf7..ea5a045e7f6c2 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantGlobalizationTests.cs @@ -54,29 +54,10 @@ private void TestInvariantGlobalization(BuildArgs buildArgs, bool? invariantGlob if (dotnetWasmFromRuntimePack == null) dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); - string programText = @" - using System; - using System.Globalization; - - // https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md#cultures-and-culture-data - try - { - CultureInfo culture = new (""es-ES"", false); - Console.WriteLine($""es-ES: Is Invariant LCID: {culture.LCID == CultureInfo.InvariantCulture.LCID}, NativeName: {culture.NativeName}""); - } - catch (CultureNotFoundException cnfe) - { - Console.WriteLine($""Could not create es-ES culture: {cnfe.Message}""); - } - - Console.WriteLine($""CurrentCulture.NativeName: {CultureInfo.CurrentCulture.NativeName}""); - return 42; - "; - BuildProject(buildArgs, id: id, new BuildProjectOptions( - InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + InitProject: () => File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "InvariantGlobalization.cs"), Path.Combine(_projectDir!, "Program.cs")), DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, GlobalizationMode: invariantGlobalization == true ? GlobalizationMode.Invariant : null)); diff --git a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs index bf14e83da6898..f89e04d508307 100644 --- a/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs @@ -52,34 +52,10 @@ private void TestInvariantTimezone(BuildArgs buildArgs, bool? invariantTimezone, if (dotnetWasmFromRuntimePack == null) dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); - string programText = @" - using System; - - // https://github.com/dotnet/runtime/blob/main/docs/design/features/timezone-invariant-mode.md - - var timezonesCount = TimeZoneInfo.GetSystemTimeZones().Count; - Console.WriteLine($""Found {timezonesCount} timezones in the TZ database""); - - TimeZoneInfo utc = TimeZoneInfo.FindSystemTimeZoneById(""UTC""); - Console.WriteLine($""{utc.DisplayName} BaseUtcOffset is {utc.BaseUtcOffset}""); - - try - { - TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(""Asia/Tokyo""); - Console.WriteLine($""{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}""); - } - catch (TimeZoneNotFoundException tznfe) - { - Console.WriteLine($""Could not find Asia/Tokyo: {tznfe.Message}""); - } - - return 42; - "; - BuildProject(buildArgs, id: id, new BuildProjectOptions( - InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + InitProject: () => File.Copy(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "InvariantTimezone.cs"), Path.Combine(_projectDir!, "Program.cs")), DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack)); string output = RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id); diff --git a/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantGlobalization.cs b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantGlobalization.cs new file mode 100644 index 0000000000000..9237110cbc498 --- /dev/null +++ b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantGlobalization.cs @@ -0,0 +1,16 @@ +using System; +using System.Globalization; + +// https://github.com/dotnet/runtime/blob/main/docs/design/features/globalization-invariant-mode.md#cultures-and-culture-data +try +{ + CultureInfo culture = new ("es-ES", false); + Console.WriteLine($"es-ES: Is Invariant LCID: {culture.LCID == CultureInfo.InvariantCulture.LCID}, NativeName: {culture.NativeName}"); +} +catch (CultureNotFoundException cnfe) +{ + Console.WriteLine($"Could not create es-ES culture: {cnfe.Message}"); +} + +Console.WriteLine($"CurrentCulture.NativeName: {CultureInfo.CurrentCulture.NativeName}"); +return 42; diff --git a/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantTimezone.cs b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantTimezone.cs new file mode 100644 index 0000000000000..deba28c7be27e --- /dev/null +++ b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/InvariantTimezone.cs @@ -0,0 +1,21 @@ +using System; + +// https://github.com/dotnet/runtime/blob/main/docs/design/features/timezone-invariant-mode.md + +var timezonesCount = TimeZoneInfo.GetSystemTimeZones().Count; +Console.WriteLine($"Found {timezonesCount} timezones in the TZ database"); + +TimeZoneInfo utc = TimeZoneInfo.FindSystemTimeZoneById("UTC"); +Console.WriteLine($"{utc.DisplayName} BaseUtcOffset is {utc.BaseUtcOffset}"); + +try +{ + TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo"); + Console.WriteLine($"{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}"); +} +catch (TimeZoneNotFoundException tznfe) +{ + Console.WriteLine($"Could not find Asia/Tokyo: {tznfe.Message}"); +} + +return 42; From d0ae247b8c505ed3d2a1f0307664294920b722b8 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 28 Jun 2023 16:18:34 +0200 Subject: [PATCH 5/7] fix native build --- src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs | 6 +++--- src/mono/wasi/build/WasiApp.Native.targets | 5 +++++ src/mono/wasi/build/WasiApp.targets | 1 + src/mono/wasm/build/WasmApp.Native.targets | 8 ++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs index 5a5a485fd8880..196d9305d1f25 100644 --- a/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs +++ b/src/mono/wasi/Wasi.Build.Tests/WasiTemplateTests.cs @@ -147,12 +147,12 @@ public void ConsolePublishAndRunForSingleFileBundle(string config, bool relinkin try { - TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById(""Asia/Tokyo""); - Console.WriteLine($""{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}""); + TimeZoneInfo tst = TimeZoneInfo.FindSystemTimeZoneById("Asia/Tokyo"); + Console.WriteLine($"{tst.DisplayName} BaseUtcOffset is {tst.BaseUtcOffset}"); } catch (TimeZoneNotFoundException tznfe) { - Console.WriteLine($""Could not find Asia/Tokyo: {tznfe.Message}""); + Console.WriteLine($"Could not find Asia/Tokyo: {tznfe.Message}"); } return 42; diff --git a/src/mono/wasi/build/WasiApp.Native.targets b/src/mono/wasi/build/WasiApp.Native.targets index 8fd82eaca343f..bcc99310d6d89 100644 --- a/src/mono/wasi/build/WasiApp.Native.targets +++ b/src/mono/wasi/build/WasiApp.Native.targets @@ -63,6 +63,8 @@ true true + true + true true @@ -75,6 +77,8 @@ true true true + true + true false @@ -274,6 +278,7 @@ <_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" /> + <_MonoRuntimeComponentDontLink Include="wasm-bundled-timezones.a" Condition="'$(InvariantTimezone)' == 'true'"/> <_WasmNativeFileForLinking Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)*.a" diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index 2a711e5eeea2f..c79e12d2e2b1b 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -120,6 +120,7 @@ false true true + true true wasmtime diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets index 403096064dd47..34736613dd8f6 100644 --- a/src/mono/wasm/build/WasmApp.Native.targets +++ b/src/mono/wasm/build/WasmApp.Native.targets @@ -115,6 +115,10 @@ true + + true + true + true false @@ -129,6 +133,10 @@ true + + true + true + false From d717645f005432e3f7d66a2ad8c7a2fcaeb2dfe7 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 29 Jun 2023 09:13:07 +0200 Subject: [PATCH 6/7] feedback --- docs/design/features/timezone-invariant-mode.md | 8 ++++++-- src/mono/wasi/build/WasiApp.targets | 12 ++++++------ src/mono/wasm/build/WasmApp.targets | 14 +++++++------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/docs/design/features/timezone-invariant-mode.md b/docs/design/features/timezone-invariant-mode.md index e66da8ea5407d..f7be1b06e7f7e 100644 --- a/docs/design/features/timezone-invariant-mode.md +++ b/docs/design/features/timezone-invariant-mode.md @@ -2,9 +2,13 @@ Author: [Pavel Savara](https://github.com/pavelsavara) -It's currently only available for Browser OS +It's currently only available for Browser OS. +The timezone database is not part of the browser environment (as opposed to other operating systems). +Therefore dotnet bundles the timezone database as binary as part of the runtime. +That makes download size larger and application startup slower. +If your application doesn't need to work with time zone information, you could use this feature to make the runtime about 200KB smaller. -- you enable it in project file: +You enable it in project file: ```xml true diff --git a/src/mono/wasi/build/WasiApp.targets b/src/mono/wasi/build/WasiApp.targets index c79e12d2e2b1b..8909c89aa4400 100644 --- a/src/mono/wasi/build/WasiApp.targets +++ b/src/mono/wasi/build/WasiApp.targets @@ -11,9 +11,9 @@ Public properties (optional): - $(WasmAppDir) - AppBundle dir (Defaults to `$(OutputPath)\$(Configuration)\AppBundle`) - $(WasmMainAssemblyFileName)- Defaults to $(TargetFileName) - - $(WasmBuildNative) - Whenever to build the native executable. Defaults to false. - - $(WasmNativeStrip) - Whenever to strip the native executable. Defaults to true. - - $(WasmLinkIcalls) - Whenever to link out unused icalls. Defaults to $(WasmBuildNative). + - $(WasmBuildNative) - Whether to build the native executable. Defaults to false. + - $(WasmNativeStrip) - Whether to strip the native executable. Defaults to true. + - $(WasmLinkIcalls) - Whether to link out unused icalls. Defaults to $(WasmBuildNative). - $(RunAOTCompilation) - Defaults to false. - $(WasmDebugLevel) @@ -24,12 +24,12 @@ - $(WasmNativeDebugSymbols) - Build with native debug symbols, useful only with `$(RunAOTCompilation)`, or `$(WasmBuildNative)` Defaults to true. - $(WasmEmitSymbolMap) - Generates a `dotnet.js.symbols` file with a map of wasm function number to name. - - $(WasmDedup) - Whenever to dedup generic instances when using AOT. Defaults to true. + - $(WasmDedup) - Whether to dedup generic instances when using AOT. Defaults to true. - $(WasmProfilers) - Profilers to use - $(AOTProfilePath) - profile data file to be used for profile-guided optimization - - $(InvariantGlobalization) - Whenever to disable ICU. Defaults to false. - - $(InvariantTimezone) - Whenever to disable Timezone database. Defaults to false. + - $(InvariantGlobalization) - Whether to disable ICU. Defaults to false. + - $(InvariantTimezone) - Whether to disable Timezone database. Defaults to false. - $(WasmResolveAssembliesBeforeBuild) - Resolve the assembly dependencies. Defaults to false - $(WasmAssemblySearchPaths) - used for resolving assembly dependencies diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index ebc945aa5a932..ee93107340dc9 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -10,9 +10,9 @@ Public properties (optional): - $(WasmAppDir) - AppBundle dir (Defaults to `$(OutputPath)\$(Configuration)\AppBundle`) - $(WasmMainAssemblyFileName)- Defaults to $(TargetFileName) - - $(WasmBuildNative) - Whenever to build the native executable. Defaults to false. - - $(WasmNativeStrip) - Whenever to strip the native executable. Defaults to true. - - $(WasmLinkIcalls) - Whenever to link out unused icalls. Defaults to $(WasmBuildNative). + - $(WasmBuildNative) - Whether to build the native executable. Defaults to false. + - $(WasmNativeStrip) - Whether to strip the native executable. Defaults to true. + - $(WasmLinkIcalls) - Whether to link out unused icalls. Defaults to $(WasmBuildNative). - $(RunAOTCompilation) - Defaults to false. - $(WasmDebugLevel) @@ -23,13 +23,13 @@ - $(WasmNativeDebugSymbols) - Build with native debug symbols, useful only with `$(RunAOTCompilation)`, or `$(WasmBuildNative)` Defaults to true. - $(WasmEmitSymbolMap) - Generates a `dotnet.native.js.symbols` file with a map of wasm function number to name. - - $(WasmDedup) - Whenever to dedup generic instances when using AOT. Defaults to true. + - $(WasmDedup) - Whether to dedup generic instances when using AOT. Defaults to true. - $(WasmProfilers) - Profilers to use - $(AOTProfilePath) - profile data file to be used for profile-guided optimization - - $(InvariantGlobalization) - Whenever to disable ICU. Defaults to false. - - $(InvariantTimezone) - Whenever to disable Timezone database. Defaults to false. - - $(HybridGlobalization) - Whenever to enable reduced ICU + native platform functions. Defaults to false and can be set only for InvariantGlobalization=false, WasmIncludeFullIcuData=false and empty WasmIcuDataFileName. + - $(InvariantGlobalization) - Whether to disable ICU. Defaults to false. + - $(InvariantTimezone) - Whether to disable Timezone database. Defaults to false. + - $(HybridGlobalization) - Whether to enable reduced ICU + native platform functions. Defaults to false and can be set only for InvariantGlobalization=false, WasmIncludeFullIcuData=false and empty WasmIcuDataFileName. - $(WasmResolveAssembliesBeforeBuild) - Resolve the assembly dependencies. Defaults to false - $(WasmAssemblySearchPaths) - used for resolving assembly dependencies From 30fc1790860d8bd68b38d75740c98820991edac6 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Thu, 29 Jun 2023 19:07:19 +0200 Subject: [PATCH 7/7] whitespace --- docs/design/features/timezone-invariant-mode.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/features/timezone-invariant-mode.md b/docs/design/features/timezone-invariant-mode.md index f7be1b06e7f7e..4fc3069602d1d 100644 --- a/docs/design/features/timezone-invariant-mode.md +++ b/docs/design/features/timezone-invariant-mode.md @@ -2,7 +2,7 @@ Author: [Pavel Savara](https://github.com/pavelsavara) -It's currently only available for Browser OS. +It's currently only available for Browser OS. The timezone database is not part of the browser environment (as opposed to other operating systems). Therefore dotnet bundles the timezone database as binary as part of the runtime. That makes download size larger and application startup slower.