public void CanSanitizeDotNetInteropExceptions() { // Arrange var expectedMessage = "An error ocurred while invoking '[Assembly]::Method'. Swapping to 'Development' environment will " + "display more detailed information about the error that occurred."; string GetMessage(DotNetInvocationInfo info) => $"An error ocurred while invoking '[{info.AssemblyName}]::{info.MethodIdentifier}'. Swapping to 'Development' environment will " + "display more detailed information about the error that occurred."; var runtime = new TestJSRuntime() { OnDotNetException = (invocationInfo) => new JSError { Message = GetMessage(invocationInfo) } }; var exception = new Exception("Some really sensitive data in here"); var invocation = new DotNetInvocationInfo("Assembly", "Method", 0, "0"); var result = new DotNetInvocationResult(exception, default); // Act runtime.EndInvokeDotNet(invocation, result); // Assert var call = runtime.EndInvokeDotNetCalls.Single(); Assert.Equal("0", call.CallId); Assert.False(call.Success); var jsError = Assert.IsType <JSError>(call.ResultOrError); Assert.Equal(expectedMessage, jsError.Message); }
public void CanSanitizeDotNetInteropExceptions() { // Arrange var runtime = new TestJSRuntime(); var exception = new Exception("Some really sensitive data in here"); var invocation = new DotNetInvocationInfo("TestAssembly", "TestMethod", 0, "0"); var result = new DotNetInvocationResult(exception, default); // Act runtime.EndInvokeDotNet(invocation, result); // Assert var call = runtime.EndInvokeDotNetCalls.Single(); Assert.Equal("0", call.CallId); Assert.False(call.Success); var error = Assert.IsType <JSError>(call.ResultError); Assert.Same(exception, error.InnerException); Assert.Equal(invocation, error.InvocationInfo); }
// Invoked via Mono's JS interop mechanism (invoke_method) public static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson) { // Figure out whether 'assemblyNameOrDotNetObjectId' is the assembly name or the instance ID // We only need one for any given call. This helps to work around the limitation that we can // only pass a maximum of 4 args in a call from JS to Mono WebAssembly. string?assemblyName; long dotNetObjectId; if (char.IsDigit(assemblyNameOrDotNetObjectId[0])) { dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId, CultureInfo.InvariantCulture); assemblyName = null; } else { dotNetObjectId = default; assemblyName = assemblyNameOrDotNetObjectId; } var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId); WebAssemblyCallQueue.Schedule((callInfo, argsJson), static state =>
// BeginInvokeDotNetFromJS is used in a fire-and-forget context, so it's responsible for its own // error handling. public async Task BeginInvokeDotNetFromJS(string callId, string assemblyName, string methodIdentifier, long dotNetObjectId, string argsJson) { AssertInitialized(); AssertNotDisposed(); try { await Renderer.Dispatcher.InvokeAsync(() => { Log.BeginInvokeDotNet(_logger, callId, assemblyName, methodIdentifier, dotNetObjectId); var invocationInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId); DotNetDispatcher.BeginInvokeDotNet(JSRuntime, invocationInfo, argsJson); }); } catch (Exception ex) { // We don't expect any of this code to actually throw, because DotNetDispatcher.BeginInvoke doesn't throw // however, we still want this to get logged if we do. Log.BeginInvokeDotNetFailed(_logger, callId, assemblyName, methodIdentifier, dotNetObjectId, ex); await TryNotifyClientErrorAsync(Client, GetClientErrorMessage(ex, "Interop call failed.")); UnhandledException?.Invoke(this, new UnhandledExceptionEventArgs(ex, isTerminating: false)); } }
protected override void EndInvokeDotNet(DotNetInvocationInfo invocationInfo, in DotNetInvocationResult invocationResult)
/// <summary> /// Completes an async JS interop call from JavaScript to .NET /// </summary> /// <param name="invocationInfo">The <see cref="DotNetInvocationInfo"/>.</param> /// <param name="invocationResult">The <see cref="DotNetInvocationResult"/>.</param> protected internal abstract void EndInvokeDotNet( DotNetInvocationInfo invocationInfo, in DotNetInvocationResult invocationResult);
protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
public JSError(DotNetInvocationInfo invocationInfo, Exception?innerException) { InvocationInfo = invocationInfo; InnerException = innerException; }