Eliminate framework use of 'IJSUnmarshalledRuntime'#46693
Eliminate framework use of 'IJSUnmarshalledRuntime'#46693MackinnonBuck merged 12 commits intomainfrom
Conversation
pavelsavara
left a comment
There was a problem hiding this comment.
Note there are some E2E test failures. I have not looked into details yet.
| public static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson) | ||
| [JSExport] | ||
| [SupportedOSPlatform("browser")] | ||
| public static void BeginInvokeDotNet(string? callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson) |
There was a problem hiding this comment.
As a next step (could be next PR), this could be replaced by promise/Task instead of Begin/End pattern.
There was a problem hiding this comment.
Yes that would be good. We did the begin/end thing because it predated support for Task in the WebAssembly runtime's interop mechanism.
| { | ||
| #pragma warning disable CS0618 // Type or member is obsolete | ||
| var componentsCount = jsRuntime.InvokeUnmarshalled<int>(RegisteredComponentsInterop.GetRegisteredComponentsCount); | ||
| var componentsCount = jsMethods.RegisteredComponents_GetRegisteredComponentsCount(); |
There was a problem hiding this comment.
I don't know if this is perf critical but if so, it could be re-implemented as passing int[] Ids, string[] assemblies etc.
There was a problem hiding this comment.
Good point. However it's only a one-time thing that happens during startup, so my guess is that we wouldn't be able to observe any difference.
src/Components/WebAssembly/WebAssembly/src/Hosting/WebAssemblyHostBuilder.cs
Show resolved
Hide resolved
src/Components/WebAssembly/WebAssembly/src/HotReload/WebAssemblyHotReload.cs
Outdated
Show resolved
Hide resolved
| import { Blazor } from './GlobalExports'; | ||
| import * as Environment from './Environment'; | ||
| import { byteArrayBeingTransferred, Module, BINDING, monoPlatform } from './Platform/Mono/MonoPlatform'; | ||
| import { Module, BINDING, monoPlatform } from './Platform/Mono/MonoPlatform'; |
There was a problem hiding this comment.
In next PR we could try re-invent how the goal of invokeJSFromDotNet could be achieved otherwise.
To ged rid of things like BINDING.js_string_to_mono_string
src/Components/WebAssembly/WebAssembly/src/Rendering/WebAssemblyRenderer.cs
Show resolved
Hide resolved
| ["ThrowException"] = @"""System.InvalidOperationException: Threw an exception!", | ||
| ["ExceptionFromSyncMethod"] = "Function threw an exception!", | ||
| ["invokeDisposedJSObjectReferenceException"] = @"""Error: JS object instance with ID", | ||
| ["ThrowException"] = @"""Threw an exception!", |
There was a problem hiding this comment.
Is the exception type name still exposed on the JS side somehow? Seems like that would be valuable for debugging.
There was a problem hiding this comment.
Unfortunately, it looks like that information is lost now. The JavaScript errors that get created from exceptions thrown in [JSExport] methods have a message property equivalent to the C# exception's Message property, which excludes the exception type and stack trace. We could fix this by catching exceptions on the .NET side and wrapping them in a new Exception to simulate the old behavior, like:
try
{
return DotNetDispatcher.Invoke(Instance, callInfo, argsJson);
}
catch (Exception ex)
{
throw new Exception(ex.ToString(), ex);
}Or I wonder if there's a way to address this on the runtime side, perhaps by updating ManagedError to include information about the type of exception that got thrown?
There was a problem hiding this comment.
They are just a proxy and could also cross the boundary back to managed.
Collecting stack trace is very very expensive and we do it when you call toString() on it (I think).
There was a problem hiding this comment.
Collecting stack trace is very very expensive and we do it when you call toString() on it (I think)
@pavelsavara Does that mean we could change the JS-side code to call throw new Error(exceptionProxy.toString()), and thereby get back the information we had before? Or is there some other mechanism you'd recommend?
There was a problem hiding this comment.
no, please don't do that. It would be slow as you would pay the cost of stack trace creation also for exceptions which would be caught and handled silently.
We override the implementation of ManagedError.stack property to provide it on demand.
I think error.toString() and console.log(error) would both include stack property (at least on chrome). I'm open to suggestions how to improve it.
Proxy in the other direction is also lazy
If the E2E tests still pass locally but are timing out in CI, that's likely an unrelated issue which we're currently investigating, and you don't need to block this PR on it. TLDR is that the CI machines auto-updated to chromedriver 110, and we don't yet know why, but this suffers connection issues that were not present in chromedriver 109. Please verify locally though! |
SteveSandersonMS
left a comment
There was a problem hiding this comment.
Looks great! I really like the improved simplicity.
…lyRenderer.cs Co-authored-by: Steve Sanderson <SteveSandersonMS@users.noreply.github.com>
src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts
Outdated
Show resolved
Hide resolved
|
I've validated the hot reload changes locally. |
|
I'm going to merge this now and address improvements in a follow-up PR. |
Hey, is this available in the latest .NET 8 preview? I want to be able to use CSP security in blazor wasm, thanks. |
|
Hi @ctigrisht. It looks like you just commented on a closed PR. The team will most probably miss it. If you'd like to bring something important up to their attention, consider filing a new issue and add enough details to build context. |
Eliminate framework use of
IJSUnmarshalledRuntimeRemoves internal usage of
IJSUnmarshalledRuntimeto in favor of[JSImport]-style JavaScript interop.Description
IInternalJSImportMethodsinterface that gives us a layer of abstraction over direct calls to[JSImport]methods:TestInternalJSImportMethodsand updated tests to utilize it[JSImport]methods that only make sense in an E2E context do not appear inIInternalJSImportMethodsIJSUnmarshalledRuntimefor:WebAssemblyNavigationManagerandWebAssemblyNavigationInterception)WebAssemblyHostBuilder)WebAssemblyHotReload)InternalCallsandWebAssemblyJSRuntime)WebAssemblyRenderer)Contributes to #37787 and #46673