Skip to content

Commit 85c5f68

Browse files
Transfer .NET unhandled exceptions to JS via dedicated interop call. Fixes #20280 (#20907)
1 parent 52afc53 commit 85c5f68

File tree

4 files changed

+16
-12
lines changed

4 files changed

+16
-12
lines changed

src/Components/Web.JS/dist/Release/blazor.webassembly.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
191191
module.print = line => (suppressMessages.indexOf(line) < 0 && console.log(line));
192192

193193
module.printErr = line => {
194+
// If anything writes to stderr, treat it as a critical exception. The underlying runtime writes
195+
// to stderr if a truly critical problem occurs outside .NET code. Note that .NET unhandled
196+
// exceptions also reach this, but via a different code path - see dotNetCriticalError below.
194197
console.error(line);
195198
showErrorNotification();
196199
};
@@ -250,6 +253,10 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
250253
assembliesBeingLoaded.forEach(r => addResourceAsAssembly(r, changeExtension(r.name, '.dll')));
251254
pdbsBeingLoaded.forEach(r => addResourceAsAssembly(r, r.name));
252255

256+
window['Blazor']._internal.dotNetCriticalError = (message: System_String) => {
257+
module.printErr(BINDING.conv_string(message) || '(null)');
258+
};
259+
253260
// Wire-up callbacks for satellite assemblies. Blazor will call these as part of the application
254261
// startup sequence to load satellite assemblies for the application's culture.
255262
window['Blazor']._internal.getSatelliteAssemblies = (culturesToLoadDotNetArray: System_Array<System_String>) : System_Object => {

src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLogger.cs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Text;
77
using Microsoft.Extensions.Logging;
88
using Microsoft.JSInterop;
9+
using Microsoft.JSInterop.WebAssembly;
910

1011
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
1112
{
@@ -17,7 +18,7 @@ internal class WebAssemblyConsoleLogger<T> : ILogger<T>, ILogger
1718
private static readonly StringBuilder _logBuilder = new StringBuilder();
1819

1920
private readonly string _name;
20-
private readonly IJSInProcessRuntime _jsRuntime;
21+
private readonly WebAssemblyJSRuntime _jsRuntime;
2122

2223
static WebAssemblyConsoleLogger()
2324
{
@@ -27,11 +28,11 @@ static WebAssemblyConsoleLogger()
2728
}
2829

2930
public WebAssemblyConsoleLogger(IJSRuntime jsRuntime)
30-
: this(string.Empty, (IJSInProcessRuntime)jsRuntime) // Cast for DI
31+
: this(string.Empty, (WebAssemblyJSRuntime)jsRuntime) // Cast for DI
3132
{
3233
}
3334

34-
public WebAssemblyConsoleLogger(string name, IJSInProcessRuntime jsRuntime)
35+
public WebAssemblyConsoleLogger(string name, WebAssemblyJSRuntime jsRuntime)
3536
{
3637
_name = name ?? throw new ArgumentNullException(nameof(name));
3738
_jsRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
@@ -98,12 +99,7 @@ private void WriteMessage(LogLevel logLevel, string logName, int eventId, string
9899
_jsRuntime.InvokeVoid("console.error", formattedMessage);
99100
break;
100101
case LogLevel.Critical:
101-
// Writing to Console.Error is even more severe than calling console.error,
102-
// because it also causes the error UI (gold bar) to appear. We use Console.Error
103-
// as the signal for triggering that because it's what the underlying dotnet.wasm
104-
// runtime will do if it encounters a truly severe error outside the Blazor
105-
// code paths.
106-
Console.Error.WriteLine(formattedMessage);
102+
_jsRuntime.InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
107103
break;
108104
default: // LogLevel.None or invalid enum values
109105
Console.WriteLine(formattedMessage);

src/Components/WebAssembly/WebAssembly/src/Services/WebAssemblyConsoleLoggerProvider.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Collections.Concurrent;
66
using Microsoft.Extensions.Logging;
77
using Microsoft.JSInterop;
8+
using Microsoft.JSInterop.WebAssembly;
89

910
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
1011
{
@@ -14,12 +15,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
1415
internal class WebAssemblyConsoleLoggerProvider : ILoggerProvider
1516
{
1617
private readonly ConcurrentDictionary<string, WebAssemblyConsoleLogger<object>> _loggers;
17-
private readonly IJSInProcessRuntime _jsRuntime;
18+
private readonly WebAssemblyJSRuntime _jsRuntime;
1819

1920
/// <summary>
2021
/// Creates an instance of <see cref="WebAssemblyConsoleLoggerProvider"/>.
2122
/// </summary>
22-
public WebAssemblyConsoleLoggerProvider(IJSInProcessRuntime jsRuntime)
23+
public WebAssemblyConsoleLoggerProvider(WebAssemblyJSRuntime jsRuntime)
2324
{
2425
_loggers = new ConcurrentDictionary<string, WebAssemblyConsoleLogger<object>>();
2526
_jsRuntime = jsRuntime;

0 commit comments

Comments
 (0)