Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
pavelsavara committed Jun 26, 2023
1 parent f08f488 commit cda65db
Show file tree
Hide file tree
Showing 14 changed files with 148 additions and 4 deletions.
12 changes: 12 additions & 0 deletions docs/design/features/timezone-invariant-mode.md
Original file line number Diff line number Diff line change
@@ -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
<PropertyGroup>
<InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>
```
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ Copyright (c) .NET Foundation. All rights reserved.

<!-- Runtime feature defaults to trim unnecessary code -->
<InvariantGlobalization Condition="'$(InvariantGlobalization)' == ''">false</InvariantGlobalization>
<InvariantTimezone Condition="'$(BlazorEnableTimeZoneSupport)' == 'false'">true</InvariantTimezone>
<InvariantTimezone Condition="'$(InvariantTimezone)' == ''">false</InvariantTimezone>
<EventSourceSupport Condition="'$(EventSourceSupport)' == ''">false</EventSourceSupport>
<UseSystemResourceKeys Condition="'$(UseSystemResourceKeys)' == ''">true</UseSystemResourceKeys>
<EnableUnsafeUTF7Encoding Condition="'$(EnableUnsafeUTF7Encoding)' == ''">false</EnableUnsafeUTF7Encoding>
Expand Down
20 changes: 20 additions & 0 deletions src/mono/sample/wasm/browser-advanced/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
<_ServeHeaders>$(_ServeHeaders) -h &quot;Content-Security-Policy: default-src 'self' 'wasm-unsafe-eval'&quot;</_ServeHeaders>
<!-- enable reporting to profiler in browser dev tools -->
<WasmProfilers>browser;</WasmProfilers>
<InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>
<ItemGroup>
<WasmExtraFilesToDeploy Include="main.js" />
Expand Down
3 changes: 2 additions & 1 deletion src/mono/wasi/build/WasiApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -168,8 +168,9 @@

<ItemGroup>
<_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" />

<!-- Adding optimization flag at the top, so it gets precedence -->
<!--<_EmccCFlags Include="$(EmccCompileOptimizationFlag)" />-->
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasi/build/WasiApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/mono/wasi/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasi/wasi.proj
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
</Target>

<UsingTask TaskName="EmitBundleObjectFiles" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
<Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)">
<Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)" Condition="'$(InvariantTimezone)' != 'true'">
<PropertyGroup>
<_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data'))</_WasmTimezonesPath>
<_WasmTimezonesBundleObjectFile>wasm-bundled-timezones.o</_WasmTimezonesBundleObjectFile>
Expand Down
97 changes: 97 additions & 0 deletions src/mono/wasm/Wasm.Build.Tests/InvariantTimezoneTests.cs
Original file line number Diff line number Diff line change
@@ -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<object?[]> 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: "<WasmBuildNative>true</WasmBuildNative>",
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>{invariantTimezone}</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);
}
}
}
}
1 change: 1 addition & 0 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -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'))" />
Expand Down
1 change: 1 addition & 0 deletions src/mono/wasm/build/WasmApp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions src/mono/wasm/runtime/driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasm/runtime/es6/dotnet.es6.lib.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/mono/wasm/wasm.proj
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@
</Target>

<UsingTask TaskName="EmitBundleSourceFiles" AssemblyFile="$(MonoTargetsTasksAssemblyPath)" />
<Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)">
<Target Name="GenerateTimezonesArchive" Returns="@(_WasmArchivedTimezones)" Condition="'$(InvariantTimezone)' != 'true'">
<PropertyGroup>
<_WasmTimezonesPath>$([MSBuild]::NormalizePath('$(PkgSystem_Runtime_TimeZoneData)', 'contentFiles', 'any', 'any', 'data'))</_WasmTimezonesPath>
<_WasmTimezonesBundleSourceFile>wasm-bundled-timezones.c</_WasmTimezonesBundleSourceFile>
Expand Down

0 comments on commit cda65db

Please sign in to comment.