diff --git a/src/coreclr/System.Private.CoreLib/CreateRuntimeRootILLinkDescriptorFile.targets b/src/coreclr/System.Private.CoreLib/CreateRuntimeRootILLinkDescriptorFile.targets index 516ecad2864fd1..cf8be3e4e906b6 100644 --- a/src/coreclr/System.Private.CoreLib/CreateRuntimeRootILLinkDescriptorFile.targets +++ b/src/coreclr/System.Private.CoreLib/CreateRuntimeRootILLinkDescriptorFile.targets @@ -19,7 +19,6 @@ <_ILLinkDescriptorsFilePaths Include="$(ILLinkDirectory)ILLink.Descriptors.Debug.xml" Condition="'$(Configuration)' == 'Debug' or '$(Configuration)' == 'Checked'" /> <_ILLinkDescriptorsFilePaths Include="$(CoreLibSharedDir)ILLink\ILLink.Descriptors.Shared.xml" /> - <_ILLinkDescriptorsFilePaths Include="$(CoreLibSharedDir)ILLink\ILLink.Descriptors.EventSource.xml" /> + + + diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index dd904a92269f65..d5049ab1eb647b 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -2148,4 +2148,7 @@ mono_string_instance_is_interned (MonoString *str); gpointer mono_method_get_unmanaged_wrapper_ftnptr_internal (MonoMethod *method, gboolean only_unmanaged_callers_only, MonoError *error); +void +mono_runtime_run_startup_hooks (void); + #endif /* __MONO_OBJECT_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index ea784236040158..d2e6db64a40ed2 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -8124,6 +8124,25 @@ mono_runtime_get_managed_cmd_line (void) return cmd_line ? g_string_free (cmd_line, FALSE) : NULL; } +void +mono_runtime_run_startup_hooks (void) +{ + if (mono_runtime_get_no_exec ()) + return; + + MonoClass *klass = mono_class_try_load_from_name (mono_defaults.corlib, "System", "StartupHookProvider"); + if (!klass) + return; // Linked away + ERROR_DECL (error); + MonoMethod *method = mono_class_get_method_from_name_checked (klass, "ProcessStartupHooks", -1, 0, error); + mono_error_cleanup (error); + if (!method) + return; + mono_runtime_invoke_checked (method, NULL, NULL, error); + // runtime hooks design doc says not to catch exceptions from the hooks + mono_error_raise_exception_deprecated (error); +} + #if NEVER_DEFINED /* * The following section is purely to declare prototypes and diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 4972e1b1391513..b726edc23f9f41 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -4729,6 +4729,8 @@ mini_init (const char *filename) MONO_PROFILER_RAISE (runtime_initialized, ()); + mono_runtime_run_startup_hooks (); + MONO_VES_INIT_END (); return domain; diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Android.Device_Emulator.StartupHook.Test.csproj b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Android.Device_Emulator.StartupHook.Test.csproj new file mode 100644 index 00000000000000..16635288c9c9b1 --- /dev/null +++ b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Android.Device_Emulator.StartupHook.Test.csproj @@ -0,0 +1,19 @@ + + + Exe + true + $(NetCoreAppCurrent) + Android.Device_Emulator.StartupHook.Test.dll + false + 42 + true + + + + + + + + + + diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Program.cs b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Program.cs new file mode 100644 index 00000000000000..d4bfdecf7f63a5 --- /dev/null +++ b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/Program.cs @@ -0,0 +1,23 @@ +// 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.Threading; +using System.Threading.Tasks; +using System.Runtime.InteropServices; + +public static class Program +{ + public static int Main() + { + string appContextKey = "Test.StartupHookForFunctionalTest.DidRun"; + var data = (string) AppContext.GetData (appContextKey); + + if (data != "Yes") { + string msg = $"Expected startup hook to set {appContextKey} to 'Yes', got '{data}'"; + Console.Error.WriteLine(msg); + return 104; + } + return 42; + } +} diff --git a/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/runtimeconfig.template.json b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/runtimeconfig.template.json new file mode 100644 index 00000000000000..892c7b04ba3450 --- /dev/null +++ b/src/tests/FunctionalTests/Android/Device_Emulator/StartupHook/runtimeconfig.template.json @@ -0,0 +1,5 @@ +{ + "configProperties": { + "STARTUP_HOOKS": "StartupHookForFunctionalTest" + } +} diff --git a/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.cs b/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.cs new file mode 100644 index 00000000000000..d96a64b5953092 --- /dev/null +++ b/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.cs @@ -0,0 +1,9 @@ +using System; + +internal class StartupHook +{ + public static void Initialize() + { + AppContext.SetData("Test.StartupHookForFunctionalTest.DidRun", "Yes"); + } +} diff --git a/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj b/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj new file mode 100644 index 00000000000000..60a8062556e62e --- /dev/null +++ b/src/tests/FunctionalTests/TestAssets/StartupHookForFunctionalTest/StartupHookForFunctionalTest.csproj @@ -0,0 +1,12 @@ + + + Library + $(NetCoreAppCurrent) + false + false + + + + + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/Program.cs b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/Program.cs new file mode 100644 index 00000000000000..0b7d8d6a2bdc11 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/Program.cs @@ -0,0 +1,30 @@ +// 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.Runtime.CompilerServices; +using System.Runtime.InteropServices.JavaScript; + +namespace Sample +{ + public partial class Test + { + public static void Main() + { + } + + [JSExport] + public static int TestMeaning() + { + string appContextKey = "Test.StartupHookForFunctionalTest.DidRun"; + var data = (string) AppContext.GetData (appContextKey); + + if (data != "Yes") { + string msg = $"Expected startup hook to set {appContextKey} to 'Yes', got '{data}'"; + Console.Error.WriteLine(msg); + return 104; + } + return 42; + } + } +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/WebAssembly.Browser.StartupHook.Test.csproj b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/WebAssembly.Browser.StartupHook.Test.csproj new file mode 100644 index 00000000000000..80d3df9875d74b --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/WebAssembly.Browser.StartupHook.Test.csproj @@ -0,0 +1,28 @@ + + + true + WasmTestOnBrowser + $(TestArchiveRoot)browseronly/ + $(TestArchiveTestsRoot)$(OSPlatformConfig)/ + $(DefineConstants);TARGET_BROWSER + 42 + main.js + true + + + + + + + + + + + + + + + + + + diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/index.html b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/index.html new file mode 100644 index 00000000000000..7d64c79aec98d9 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/index.html @@ -0,0 +1,18 @@ + + + + + + + Runtime config test + + + + + + + + Answer to the Ultimate Question of Life, the Universe, and Everything is : + + + \ No newline at end of file diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/main.js b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/main.js new file mode 100644 index 00000000000000..a7323e1a89a925 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/main.js @@ -0,0 +1,24 @@ +import { dotnet } from './dotnet.js' + +function wasm_exit(exit_code) { + var tests_done_elem = document.createElement("label"); + tests_done_elem.id = "tests_done"; + tests_done_elem.innerHTML = exit_code.toString(); + document.body.appendChild(tests_done_elem); + + console.log(`WASM EXIT ${exit_code}`); +} + +try { + const { getAssemblyExports } = await dotnet.create(); + const exports = await getAssemblyExports("WebAssembly.Browser.StartupHook.Test.dll"); + const testMeaning = exports.Sample.Test.TestMeaning; + const ret = testMeaning(); + document.getElementById("out").innerHTML = `${ret}`; + console.debug(`ret: ${ret}`); + + let exit_code = ret; + wasm_exit(exit_code); +} catch (err) { + console.log(`WASM ERROR ${err}`); +} diff --git a/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/runtimeconfig.template.json b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/runtimeconfig.template.json new file mode 100644 index 00000000000000..892c7b04ba3450 --- /dev/null +++ b/src/tests/FunctionalTests/WebAssembly/Browser/StartupHook/runtimeconfig.template.json @@ -0,0 +1,5 @@ +{ + "configProperties": { + "STARTUP_HOOKS": "StartupHookForFunctionalTest" + } +} diff --git a/src/tests/FunctionalTests/iOS/Simulator/StartupHook/Program.cs b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/Program.cs new file mode 100644 index 00000000000000..04d30df669c95a --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/Program.cs @@ -0,0 +1,33 @@ + +// 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.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Threading.Tasks; + +public static class Program +{ + [DllImport("__Internal")] + public static extern void mono_ios_set_summary (string value); + + public static async Task Main(string[] args) + { + string appContextKey = "Test.StartupHookForFunctionalTest.DidRun"; + mono_ios_set_summary($"Starting functional test"); + + await Task.Delay(10); + + var data = (string) AppContext.GetData (appContextKey); + + if (data != "Yes") { + string msg = $"Expected startup hook to set {appContextKey} to 'Yes', got '{data}'"; + mono_ios_set_summary(msg); + Console.Error.WriteLine(msg); + return 104; + } + return 42; + } +} diff --git a/src/tests/FunctionalTests/iOS/Simulator/StartupHook/iOS.Simulator.StartupHook.Test.csproj b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/iOS.Simulator.StartupHook.Test.csproj new file mode 100644 index 00000000000000..96e17135a3d1c6 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/iOS.Simulator.StartupHook.Test.csproj @@ -0,0 +1,22 @@ + + + + Exe + true + $(NetCoreAppCurrent) + iOSSimulator + iOS.Simulator.StartupHook.Test.dll + false + 42 + true + + + + + + + + + + + diff --git a/src/tests/FunctionalTests/iOS/Simulator/StartupHook/runtimeconfig.template.json b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/runtimeconfig.template.json new file mode 100644 index 00000000000000..892c7b04ba3450 --- /dev/null +++ b/src/tests/FunctionalTests/iOS/Simulator/StartupHook/runtimeconfig.template.json @@ -0,0 +1,5 @@ +{ + "configProperties": { + "STARTUP_HOOKS": "StartupHookForFunctionalTest" + } +}