Transfer .NET unhandled exceptions to JS via dedicated interop call. Fixes #20280 (#20907)

This commit is contained in:
Steve Sanderson 2020-04-17 03:06:12 +01:00
parent e95264f237
commit 03068c9165
4 changed files with 16 additions and 12 deletions

File diff suppressed because one or more lines are too long

View File

@ -191,6 +191,9 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
module.print = line => (suppressMessages.indexOf(line) < 0 && console.log(line));
module.printErr = line => {
// If anything writes to stderr, treat it as a critical exception. The underlying runtime writes
// to stderr if a truly critical problem occurs outside .NET code. Note that .NET unhandled
// exceptions also reach this, but via a different code path - see dotNetCriticalError below.
console.error(line);
showErrorNotification();
};
@ -250,6 +253,10 @@ function createEmscriptenModuleInstance(resourceLoader: WebAssemblyResourceLoade
assembliesBeingLoaded.forEach(r => addResourceAsAssembly(r, changeExtension(r.name, '.dll')));
pdbsBeingLoaded.forEach(r => addResourceAsAssembly(r, r.name));
window['Blazor']._internal.dotNetCriticalError = (message: System_String) => {
module.printErr(BINDING.conv_string(message) || '(null)');
};
// Wire-up callbacks for satellite assemblies. Blazor will call these as part of the application
// startup sequence to load satellite assemblies for the application's culture.
window['Blazor']._internal.getSatelliteAssemblies = (culturesToLoadDotNetArray: System_Array<System_String>) : System_Object => {

View File

@ -6,6 +6,7 @@ using System.Collections.Concurrent;
using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Microsoft.JSInterop.WebAssembly;
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
{
@ -17,7 +18,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
private static readonly StringBuilder _logBuilder = new StringBuilder();
private readonly string _name;
private readonly IJSInProcessRuntime _jsRuntime;
private readonly WebAssemblyJSRuntime _jsRuntime;
static WebAssemblyConsoleLogger()
{
@ -27,11 +28,11 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
}
public WebAssemblyConsoleLogger(IJSRuntime jsRuntime)
: this(string.Empty, (IJSInProcessRuntime)jsRuntime) // Cast for DI
: this(string.Empty, (WebAssemblyJSRuntime)jsRuntime) // Cast for DI
{
}
public WebAssemblyConsoleLogger(string name, IJSInProcessRuntime jsRuntime)
public WebAssemblyConsoleLogger(string name, WebAssemblyJSRuntime jsRuntime)
{
_name = name ?? throw new ArgumentNullException(nameof(name));
_jsRuntime = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
@ -98,12 +99,7 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
_jsRuntime.InvokeVoid("console.error", formattedMessage);
break;
case LogLevel.Critical:
// Writing to Console.Error is even more severe than calling console.error,
// because it also causes the error UI (gold bar) to appear. We use Console.Error
// as the signal for triggering that because it's what the underlying dotnet.wasm
// runtime will do if it encounters a truly severe error outside the Blazor
// code paths.
Console.Error.WriteLine(formattedMessage);
_jsRuntime.InvokeUnmarshalled<string, object>("Blazor._internal.dotNetCriticalError", formattedMessage);
break;
default: // LogLevel.None or invalid enum values
Console.WriteLine(formattedMessage);

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Concurrent;
using Microsoft.Extensions.Logging;
using Microsoft.JSInterop;
using Microsoft.JSInterop.WebAssembly;
namespace Microsoft.AspNetCore.Components.WebAssembly.Services
{
@ -14,12 +15,12 @@ namespace Microsoft.AspNetCore.Components.WebAssembly.Services
internal class WebAssemblyConsoleLoggerProvider : ILoggerProvider
{
private readonly ConcurrentDictionary<string, WebAssemblyConsoleLogger<object>> _loggers;
private readonly IJSInProcessRuntime _jsRuntime;
private readonly WebAssemblyJSRuntime _jsRuntime;
/// <summary>
/// Creates an instance of <see cref="WebAssemblyConsoleLoggerProvider"/>.
/// </summary>
public WebAssemblyConsoleLoggerProvider(IJSInProcessRuntime jsRuntime)
public WebAssemblyConsoleLoggerProvider(WebAssemblyJSRuntime jsRuntime)
{
_loggers = new ConcurrentDictionary<string, WebAssemblyConsoleLogger<object>>();
_jsRuntime = jsRuntime;