Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend the JS interop transport contract to allow passing UTF8 bytes instead of JS/.NET strings #35065

Open
SteveSandersonMS opened this issue Aug 5, 2021 · 3 comments
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one Perf
Milestone

Comments

@SteveSandersonMS
Copy link
Member

Currently, the lowest level contract in JS interop is defined in terms of strings. That is:

  • The JS side supplies/receives JS strings to/from Microsoft.JSInterop.JS
  • The .NET side supplies/receives .NET strings to/from Microsoft.JSInterop

This is nice in that all environments have a notion of passing/receiving strings to/from the browser. In the case of WebView2, this is the only thing you can do. However Blazor Server and Blazor WebAssembly could actually exchange UTF8-encoded byte data if they wanted.

This makes things less efficient than they could be, because on the .NET side, JSON (de)serialization is done in terms of UTF8 bytes. So JS interop from JS to .NET currently:

  • Creates a JS JSON string on the JS side which is then passed:
    • For WebAssembly, by UTF16-encoding on the JS side and writing into .NET heap memory as a .NET string
    • For Server, by UTF8-encoding on the JS side and sending via SignalR, which then decodes in .NET from UTF8 bytes to a .NET string
  • Passes this .NET string into Microsoft.JSInterop
  • ... which then encodes it as UTF8 so it can be passed to System.Text.Json

If JSInterop's contract allowed for passing UTF8 bytes instead of a string, then we could:

  • Create a JS JSON string on the JS side, which is then passed:
    • For WebAssembly, by UTF8-encoding on the JS side and writing into .NET heap memory as a byte[]
    • For Server, by UTF8-encoding on the JS side and sending via SignalR, which then supplies that data as a byte[] or maybe a ReadOnlySequence<byte> without even copying
  • Passes this ReadOnlySequence<byte> (UTF8 data) to System.Text.Json

That would reduce 2x copy-and-en/decode transformations to no transformations at all on the .NET side, possibly not even having to copy the data out of the SignalR message buffer, and just JSON-deserializing directly over that buffer.

Drawback

This complicates the underlying JS interop contract as there would be two ways to do the same thing, only one of which we'd be using in Blazor. Or we could do a breaking change and entirely remove the string-based APIs.

This would not affect regular applications since the transport is an internal detail. It would only affect people implementing platforms, which is probably nobody except us. It wouldn't even affect the IJSRuntime contract at all, because that's the contract used by application developers, not by platform authors. It would affect the JSRuntime abstract base class that application developers don't normally use.

For WebView, we'd need to take the byte data we're given on either side of the contract and encode it as a string for transport in/out of the WebView2 then convert back to byte data. This is probably no less efficient than what we have today, since it's the same number of transformations - they would just be happening in different places, and it would seem a bit more complicated inside the WebView2 code. I don't think it would be very difficult though.

I think we should consider doing this for .NET 7, but not in .NET 6 as we haven't budgeted time so late in the process for a significant change like this.

@SteveSandersonMS SteveSandersonMS added the area-blazor Includes: Blazor, Razor Components label Aug 5, 2021
@pranavkm pranavkm added this to the Backlog milestone Aug 5, 2021
@ghost
Copy link

ghost commented Aug 5, 2021

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@pranavkm pranavkm added the enhancement This issue represents an ask for new feature or an enhancement to an existing one label Aug 5, 2021
@pranavkm pranavkm modified the milestones: Backlog, .NET 7-Candidate Aug 5, 2021
@mkArtakMSFT mkArtakMSFT modified the milestones: .NET 7 Planning, Backlog Nov 11, 2021
@ghost
Copy link

ghost commented Nov 11, 2021

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

@mkArtakMSFT mkArtakMSFT modified the milestones: Backlog, BlazorPlanning Nov 5, 2023
@mkArtakMSFT mkArtakMSFT modified the milestones: Planning: WebUI, Backlog Dec 14, 2023
@ghost
Copy link

ghost commented Dec 14, 2023

We've moved this issue to the Backlog milestone. This means that it is not going to be worked on for the coming release. We will reassess the backlog following the current release and consider this item at that time. To learn more about our issue management process and to have better expectation regarding different types of issues you can read our Triage Process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-blazor Includes: Blazor, Razor Components enhancement This issue represents an ask for new feature or an enhancement to an existing one Perf
Projects
None yet
Development

No branches or pull requests

3 participants