From 93f407d231e31687decdc1f5b7f466af2fb94737 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Aleksey=20Kliger=20=28=CE=BBgeek=29?= Date: Wed, 23 Jun 2021 20:13:37 -0400 Subject: [PATCH] [wasm] Build static components; include hot_reload in runtime (#54568) * [wasm] Build static components; include hot_reload in runtime Workaround until https://github.com/dotnet/runtime/issues/54565 is fixed Build the runtime always with support for hot_reload, and without diagnostics_tracing * Update wasm.proj * Add a browser functional test for hot reload Just check that the capabilities are non-empty which is a good proxy for hot reload being enabled in the runtime. * Turn off trimming for hot reload functional test * Disable test on browser AOT * fix whitespace Co-authored-by: Thays Grazia --- ...on.Metadata.ApplyUpdate.Test.MethodBody1.csproj | 1 + .../System.Runtime.Loader/tests/ApplyUpdateTest.cs | 1 + src/mono/mono.proj | 1 - src/mono/wasm/Makefile | 8 +++ src/mono/wasm/wasm.proj | 3 + .../ApplyUpdateReferencedAssembly.csproj | 30 ++++++++ .../ApplyUpdateReferencedAssembly/MethodBody1.cs | 11 +++ .../MethodBody1_v1.cs | 11 +++ .../MethodBody1_v2.cs | 11 +++ .../ApplyUpdateReferencedAssembly/deltascript.json | 7 ++ .../WebAssembly/Browser/HotReload/Program.cs | 81 ++++++++++++++++++++++ .../WebAssembly.Browser.HotReload.Test.csproj | 52 ++++++++++++++ .../WebAssembly/Browser/HotReload/index.html | 55 +++++++++++++++ .../WebAssembly/Browser/HotReload/runtime.js | 47 +++++++++++++ 14 files changed, 318 insertions(+), 1 deletion(-) create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/ApplyUpdateReferencedAssembly.csproj create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1.cs create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/deltascript.json create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/Program.cs create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/index.html create mode 100644 src/tests/FunctionalTests/WebAssembly/Browser/HotReload/runtime.js diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1.csproj b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1.csproj index f05397e..57ba4f3 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1.csproj +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdate/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1/System.Reflection.Metadata.ApplyUpdate.Test.MethodBody1.csproj @@ -4,6 +4,7 @@ $(NetCoreAppCurrent) true deltascript.json + true diff --git a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs index e533377..2a953d1 100644 --- a/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs +++ b/src/libraries/System.Runtime.Loader/tests/ApplyUpdateTest.cs @@ -18,6 +18,7 @@ namespace System.Reflection.Metadata public class ApplyUpdateTest { [Fact] + [ActiveIssue("https://github.com/dotnet/runtime/issues/54617", typeof(PlatformDetection), nameof(PlatformDetection.IsBrowser), nameof(PlatformDetection.IsMonoAOT))] void StaticMethodBodyUpdate() { ApplyUpdateUtil.TestCase(static () => diff --git a/src/mono/mono.proj b/src/mono/mono.proj index e5d4bb2..e459f87 100644 --- a/src/mono/mono.proj +++ b/src/mono/mono.proj @@ -294,7 +294,6 @@ <_MonoCMakeArgs Include="-DENABLE_INTERP_LIB=1"/> <_MonoCMakeArgs Include="-DDISABLE_ICALL_TABLES=1"/> <_MonoCMakeArgs Include="-DDISABLE_CRASH_REPORTING=1"/> - <_MonoCMakeArgs Include="-DDISABLE_COMPONENTS=1"/> <_MonoCMakeArgs Include="-DENABLE_ICALL_EXPORT=1"/> <_MonoCMakeArgs Include="-DENABLE_LAZY_GC_THREAD_CREATION=1"/> <_MonoCMakeArgs Include="-DENABLE_LLVM_RUNTIME=1"/> diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 9f6d055..86288cd 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -48,12 +48,20 @@ provision-wasm: .stamp-wasm-install-and-select-$(EMSCRIPTEN_VERSION) @echo "----------------------------------------------------------" @echo "Installed emsdk into EMSDK_PATH=$(TOP)/src/mono/wasm/emsdk" +# FIXME: When https://github.com/dotnet/runtime/issues/54565 is fixed, and the WasmApp targets are updated to use mono runtime components, remove this +MONO_COMPONENT_LIBS= \ + $(MONO_BIN_DIR)/libmono-component-hot_reload-static.a \ + $(MONO_BIN_DIR)/libmono-component-diagnostics_tracing-stub-static.a + MONO_OBJ_DIR=$(OBJDIR)/mono/Browser.wasm.$(CONFIG) MONO_INCLUDE_DIR=$(MONO_BIN_DIR)/include/mono-2.0 BUILDS_OBJ_DIR=$(MONO_OBJ_DIR)/wasm +# libmonosgen-2.0 is in MONO_LIBS twice because the components and the runtime are depend on each other MONO_LIBS = \ $(MONO_BIN_DIR)/libmono-ee-interp.a \ $(MONO_BIN_DIR)/libmonosgen-2.0.a \ + $(MONO_COMPONENT_LIBS) \ + $(MONO_BIN_DIR)/libmonosgen-2.0.a \ $(MONO_BIN_DIR)/libmono-ilgen.a \ $(MONO_BIN_DIR)/libmono-icall-table.a \ $(MONO_BIN_DIR)/libmono-profiler-aot.a \ diff --git a/src/mono/wasm/wasm.proj b/src/mono/wasm/wasm.proj index 489d882..ffc2fb9 100644 --- a/src/mono/wasm/wasm.proj +++ b/src/mono/wasm/wasm.proj @@ -189,6 +189,8 @@ + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/ApplyUpdateReferencedAssembly.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/ApplyUpdateReferencedAssembly.csproj new file mode 100644 index 0000000..46e260f --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/ApplyUpdateReferencedAssembly.csproj @@ -0,0 +1,30 @@ + + + true + deltascript.json + library + false + true + + false + true + + false + false + + + + + + + + + + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1.cs b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1.cs new file mode 100644 index 0000000..9e98604 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () { + return "OLD STRING"; + } + } +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs new file mode 100644 index 0000000..4aab1e8 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v1.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () { + return "NEW STRING"; + } + } +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs new file mode 100644 index 0000000..83f0142 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/MethodBody1_v2.cs @@ -0,0 +1,11 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ApplyUpdateReferencedAssembly +{ + public class MethodBody1 { + public static string StaticMethod1 () { + return "NEWEST STRING"; + } + } +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/deltascript.json b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/deltascript.json new file mode 100644 index 0000000..8e73836 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/ApplyUpdateReferencedAssembly/deltascript.json @@ -0,0 +1,7 @@ +{ + "changes": [ + {"document": "MethodBody1.cs", "update": "MethodBody1_v1.cs"}, + {"document": "MethodBody1.cs", "update": "MethodBody1_v2.cs"}, + ] +} + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/Program.cs b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/Program.cs new file mode 100644 index 0000000..cb005b0 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/Program.cs @@ -0,0 +1,81 @@ +// 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.Reflection; +using System.Runtime.CompilerServices; + +namespace Sample +{ + public class Test + { + public static void Main(string[] args) + { + Console.WriteLine ("Hello, World!"); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static int TestMeaning() + { + const int success = 42; + const int failure = 1; + + var ty = typeof(System.Reflection.Metadata.AssemblyExtensions); + var mi = ty.GetMethod("GetApplyUpdateCapabilities", BindingFlags.NonPublic | BindingFlags.Static, Array.Empty()); + + if (mi == null) + return failure; + + var caps = mi.Invoke(null, null) as string; + + if (String.IsNullOrEmpty(caps)) + return failure; + + var assm = typeof (ApplyUpdateReferencedAssembly.MethodBody1).Assembly; + + var r = ApplyUpdateReferencedAssembly.MethodBody1.StaticMethod1(); + if ("OLD STRING" != r) + return failure; + + ApplyUpdate(assm); + + r = ApplyUpdateReferencedAssembly.MethodBody1.StaticMethod1(); + if ("NEW STRING" != r) + return failure; + + ApplyUpdate(assm); + + r = ApplyUpdateReferencedAssembly.MethodBody1.StaticMethod1(); + if ("NEWEST STRING" != r) + return failure; + + return success; + } + + private static System.Collections.Generic.Dictionary assembly_count = new(); + + internal static void ApplyUpdate (System.Reflection.Assembly assm) + { + int count; + if (!assembly_count.TryGetValue(assm, out count)) + count = 1; + else + count++; + assembly_count [assm] = count; + + /* FIXME WASM: Location is empty on wasm. Make up a name based on Name */ + string basename = assm.Location; + if (basename == "") + basename = assm.GetName().Name + ".dll"; + Console.Error.WriteLine($"Apply Delta Update for {basename}, revision {count}"); + + string dmeta_name = $"{basename}.{count}.dmeta"; + string dil_name = $"{basename}.{count}.dil"; + byte[] dmeta_data = System.IO.File.ReadAllBytes(dmeta_name); + byte[] dil_data = System.IO.File.ReadAllBytes(dil_name); + byte[] dpdb_data = null; // TODO also use the dpdb data + + System.Reflection.Metadata.AssemblyExtensions.ApplyUpdate(assm, dmeta_data, dil_data, dpdb_data); + } + } +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj new file mode 100644 index 0000000..2ba0552 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/WebAssembly.Browser.HotReload.Test.csproj @@ -0,0 +1,52 @@ + + + true + false + false + true + WasmTestOnBrowser + 42 + runtime.js + false + + + + + + + Always + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/index.html new file mode 100644 index 0000000..ad7cc21 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/index.html @@ -0,0 +1,55 @@ + + + + + + TESTS + + + + + + Result from Sample.Test.TestMeaning: + + + + + + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/runtime.js b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/runtime.js new file mode 100644 index 0000000..4859991 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/HotReload/runtime.js @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +var Module = { + + config: null, + + preInit: async function() { + Module.config = await MONO.mono_wasm_load_config("./mono-config.json"); + }, + + onRuntimeInitialized: function () { + if (!Module.config || Module.config.error) { + console.log("No config found"); + test_exit(1); + throw(Module.config.error); + } + + Module.config.loaded_cb = function () { + try { + App.init (); + } catch (error) { + test_exit(1); + throw (error); + } + }; + Module.config.fetch_file_cb = function (asset) { + return fetch (asset, { credentials: 'same-origin' }); + } + + if (Module.config.environment_variables !== undefined) { + console.log ("expected environment variables to be undefined, but they're: ", Module.config.environment_variables); + test_exit(1); + } + Module.config.environment_variables = { + "DOTNET_MODIFIABLE_ASSEMBLIES": "debug" + }; + + try + { + MONO.mono_load_runtime_and_bcl_args (Module.config); + } catch (error) { + test_exit(1); + throw(error); + } + }, +}; -- 2.7.4