From 14dd1326e3aabfc5397033418a32d3fdc8d18d7a Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 29 Aug 2022 14:27:07 +0200 Subject: [PATCH 1/3] add internal test handler for unhandled exceptions on browser --- src/mono/wasm/runtime/run-outer.ts | 29 +++++++++++++++++++++++++++++ src/mono/wasm/runtime/run.ts | 14 ++++++++------ src/mono/wasm/test-main.js | 3 ++- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index eb0a83a12c54a..d6a39a39555d9 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -57,6 +57,35 @@ class HostBuilder implements DotnetHostBuilder { } } + // internal + withExitOnUnhandledError(): DotnetHostBuilder { + try { + // it seems that emscripten already does the right thing for NodeJs and that there is no good solution for V8 shell. + if (ENVIRONMENT_IS_WEB) { + window.addEventListener("unhandledrejection", (event: PromiseRejectionEvent) => { + event.preventDefault(); + try { + mono_exit(1, event.reason); + } catch (err) { + // no not re-throw from the unhandledrejection handler + } + }); + window.addEventListener("error", (event: ErrorEvent) => { + event.preventDefault(); + try { + mono_exit(1, event.error); + } catch (err) { + // no not re-throw from the error handler + } + }); + } + return this; + } catch (err) { + mono_exit(1, err); + throw err; + } + } + // internal withAsyncFlushOnExit(): DotnetHostBuilder { try { diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index 2dca623792ad4..493f92aeb09a2 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -108,12 +108,14 @@ async function flush_node_streams() { function set_exit_code_and_quit_now(exit_code: number, reason?: any): void { if (runtimeHelpers.ExitStatus) { if (reason && !(reason instanceof runtimeHelpers.ExitStatus)) { - if (reason instanceof Error) - Module.printErr(INTERNAL.mono_wasm_stringify_as_error_with_stack(reason)); - else if (typeof reason == "string") - Module.printErr(reason); - else - Module.printErr(JSON.stringify(reason)); + if (!runtimeHelpers.config.logExitCode) { + if (reason instanceof Error) + Module.printErr(INTERNAL.mono_wasm_stringify_as_error_with_stack(reason)); + else if (typeof reason == "string") + Module.printErr(reason); + else + Module.printErr(JSON.stringify(reason)); + } } else { reason = new runtimeHelpers.ExitStatus(exit_code); diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index bac3f856160c5..8d9c391c98190 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -259,6 +259,7 @@ async function run() { .withVirtualWorkingDirectory(runArgs.workingDirectory) .withEnvironmentVariables(runArgs.environmentVariables) .withDiagnosticTracing(runArgs.diagnosticTracing) + .withExitOnUnhandledError() .withExitCodeLogging() .withElementOnExit(); @@ -266,7 +267,7 @@ async function run() { dotnet .withEnvironmentVariable("NodeJSPlatform", process.platform) .withAsyncFlushOnExit(); - + const modulesToLoad = runArgs.environmentVariables["NPM_MODULES"]; if (modulesToLoad) { dotnet.withModuleConfig({ From 34c1c9f8e3314a40d96a756982f407ea376d60c4 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 29 Aug 2022 15:15:33 +0200 Subject: [PATCH 2/3] wip --- src/mono/wasm/runtime/run.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/wasm/runtime/run.ts b/src/mono/wasm/runtime/run.ts index 493f92aeb09a2..1e224837222ca 100644 --- a/src/mono/wasm/runtime/run.ts +++ b/src/mono/wasm/runtime/run.ts @@ -1,7 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -import { ENVIRONMENT_IS_WEB, INTERNAL, Module, runtimeHelpers } from "./imports"; +import { ENVIRONMENT_IS_WEB, Module, runtimeHelpers } from "./imports"; import { mono_wasm_wait_for_debugger } from "./debug"; import { abort_startup, mono_wasm_set_main_args } from "./startup"; import cwraps from "./cwraps"; @@ -110,7 +110,7 @@ function set_exit_code_and_quit_now(exit_code: number, reason?: any): void { if (reason && !(reason instanceof runtimeHelpers.ExitStatus)) { if (!runtimeHelpers.config.logExitCode) { if (reason instanceof Error) - Module.printErr(INTERNAL.mono_wasm_stringify_as_error_with_stack(reason)); + Module.printErr(mono_wasm_stringify_as_error_with_stack(reason)); else if (typeof reason == "string") Module.printErr(reason); else From 6a717ee225df404d8bce104d9b02ecee5c9ef415 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 30 Aug 2022 15:53:51 +0200 Subject: [PATCH 3/3] feedback --- .../Wasm.Build.Tests/WasmTemplateTests.cs | 2 +- src/mono/wasm/runtime/run-outer.ts | 26 +++++++------------ 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs index 08fc1180c849b..5b41e3a1b0302 100644 --- a/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/WasmTemplateTests.cs @@ -41,7 +41,7 @@ private void UpdateBrowserMainJs() string mainJsPath = Path.Combine(_projectDir!, "main.js"); string mainJsContent = File.ReadAllText(mainJsPath); - mainJsContent = mainJsContent.Replace(".create()", ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().create()"); + mainJsContent = mainJsContent.Replace(".create()", ".withConsoleForwarding().withElementOnExit().withExitCodeLogging().withExitOnUnhandledError().create()"); File.WriteAllText(mainJsPath, mainJsContent); } diff --git a/src/mono/wasm/runtime/run-outer.ts b/src/mono/wasm/runtime/run-outer.ts index d6a39a39555d9..4ff468fce4bb6 100644 --- a/src/mono/wasm/runtime/run-outer.ts +++ b/src/mono/wasm/runtime/run-outer.ts @@ -59,25 +59,19 @@ class HostBuilder implements DotnetHostBuilder { // internal withExitOnUnhandledError(): DotnetHostBuilder { + const handler = function fatal_handler(event: Event, error: any) { + event.preventDefault(); + try { + mono_exit(1, error); + } catch (err) { + // no not re-throw from the fatal handler + } + }; try { // it seems that emscripten already does the right thing for NodeJs and that there is no good solution for V8 shell. if (ENVIRONMENT_IS_WEB) { - window.addEventListener("unhandledrejection", (event: PromiseRejectionEvent) => { - event.preventDefault(); - try { - mono_exit(1, event.reason); - } catch (err) { - // no not re-throw from the unhandledrejection handler - } - }); - window.addEventListener("error", (event: ErrorEvent) => { - event.preventDefault(); - try { - mono_exit(1, event.error); - } catch (err) { - // no not re-throw from the error handler - } - }); + window.addEventListener("unhandledrejection", (event) => handler(event, event.reason)); + window.addEventListener("error", (event) => handler(event, event.error)); } return this; } catch (err) {