Skip to content

Commit 1d8495c

Browse files
committed
Remove JSInvocationInfo from interop bridge communication
1 parent 28c8d39 commit 1d8495c

File tree

22 files changed

+329
-469
lines changed

22 files changed

+329
-469
lines changed

src/Components/Server/src/Circuits/RemoteJSRuntime.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ protected override void BeginInvokeJS(long asyncHandle, string identifier, strin
119119
BeginInvokeJS(invocationInfo);
120120
}
121121

122-
protected override void BeginInvokeJS(JSInvocationInfo invocationInfo)
122+
protected override void BeginInvokeJS(in JSInvocationInfo invocationInfo)
123123
{
124124
if (_clientProxy is null)
125125
{
@@ -138,11 +138,16 @@ protected override void BeginInvokeJS(JSInvocationInfo invocationInfo)
138138
}
139139
}
140140

141-
var invocationInfoJson = invocationInfo.ToJson();
142-
143141
Log.BeginInvokeJS(_logger, invocationInfo.AsyncHandle, invocationInfo.Identifier);
144142

145-
_clientProxy.SendAsync("JS.BeginInvokeJS", invocationInfoJson);
143+
_clientProxy.SendAsync(
144+
"JS.BeginInvokeJS",
145+
invocationInfo.AsyncHandle,
146+
invocationInfo.Identifier,
147+
invocationInfo.ArgsJson,
148+
(int)invocationInfo.ResultType,
149+
invocationInfo.TargetInstanceId,
150+
(int)invocationInfo.CallType);
146151
}
147152

148153
protected override void ReceiveByteArray(int id, byte[] data)

src/Components/Web.JS/src/Boot.WebAssembly.Common.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -264,13 +264,12 @@ async function scheduleAfterStarted(operations: string): Promise<void> {
264264
Blazor._internal.updateRootComponents(operations);
265265
}
266266

267-
function invokeJSJson(invocationInfoJson: string): string | null {
268-
const invocationInfo: DotNet.JSInvocationInfo = JSON.parse(invocationInfoJson);
269-
if (invocationInfo.asyncHandle !== 0) {
270-
dispatcher.beginInvokeJSFromDotNet(invocationInfo);
267+
function invokeJSJson(identifier: string, targetInstanceId: number, resultType: number, argsJson: string, asyncHandle: number, callType: number): string | null {
268+
if (asyncHandle !== 0) {
269+
dispatcher.beginInvokeJSFromDotNet(asyncHandle, identifier, argsJson, resultType, targetInstanceId, callType);
271270
return null;
272271
} else {
273-
return dispatcher.invokeJSFromDotNet(invocationInfo);
272+
return dispatcher.invokeJSFromDotNet(identifier, argsJson, resultType, targetInstanceId, callType);
274273
}
275274
}
276275

src/Components/Web.JS/src/GlobalExports.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export interface IBlazor {
5252
forceCloseConnection?: () => Promise<void>;
5353
InputFile?: typeof InputFile;
5454
NavigationLock: typeof NavigationLock;
55-
invokeJSJson?: (invocationInfoString: string) => string | null;
55+
invokeJSJson?: (identifier: string, targetInstanceId: number, resultType: number, argsJson: string, asyncHandle: number, callType: number) => string | null;
5656
endInvokeDotNetFromJS?: (callId: string, success: boolean, resultJsonOrErrorMessage: string) => void;
5757
receiveByteArray?: (id: number, data: Uint8Array) => void;
5858
getPersistedState?: () => string;

src/Components/Web.JS/src/Platform/Circuits/CircuitManager.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ export class CircuitManager implements DotNet.DotNetCallDispatcher {
127127
const connection = connectionBuilder.build();
128128

129129
connection.on('JS.AttachComponent', (componentId, selector) => attachRootComponentToLogicalElement(WebRendererId.Server, this.resolveElement(selector), componentId, false));
130-
connection.on('JS.BeginInvokeJS', (invocationInfoJson: string) => this.beginInvokeJSJson(invocationInfoJson));
130+
connection.on('JS.BeginInvokeJS', this._dispatcher.beginInvokeJSFromDotNet.bind(this._dispatcher));
131131
connection.on('JS.EndInvokeDotNet', this._dispatcher.endInvokeDotNetFromJS.bind(this._dispatcher));
132132
connection.on('JS.ReceiveByteArray', this._dispatcher.receiveByteArray.bind(this._dispatcher));
133133

@@ -232,11 +232,6 @@ export class CircuitManager implements DotNet.DotNetCallDispatcher {
232232
return true;
233233
}
234234

235-
private beginInvokeJSJson(invocationInfoJson: string) {
236-
const invocationInfo: DotNet.JSInvocationInfo = JSON.parse(invocationInfoJson);
237-
this._dispatcher.beginInvokeJSFromDotNet(invocationInfo);
238-
}
239-
240235
// Implements DotNet.DotNetCallDispatcher
241236
public beginInvokeDotNetFromJS(callId: number, assemblyName: string | null, methodIdentifier: string, dotNetObjectId: number | null, argsJson: string): void {
242237
this.throwIfDispatchingWhenDisposed();

src/Components/Web.JS/src/Platform/WebView/WebViewIpcReceiver.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function startIpcReceiver(): void {
3333
showErrorNotification();
3434
},
3535

36-
'BeginInvokeJS': beginInvokeJSJson,
36+
'BeginInvokeJS': dispatcher.beginInvokeJSFromDotNet.bind(dispatcher),
3737

3838
'EndInvokeDotNet': dispatcher.endInvokeDotNetFromJS.bind(dispatcher),
3939

@@ -81,7 +81,3 @@ function base64ToArrayBuffer(base64: string): Uint8Array {
8181
return result;
8282
}
8383

84-
function beginInvokeJSJson(invocationInfoJson: string) {
85-
const invocationInfo = JSON.parse(invocationInfoJson);
86-
dispatcher.beginInvokeJSFromDotNet(invocationInfo);
87-
}

src/Components/Web/src/Internal/IInternalWebJSInProcessRuntime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ public interface IInternalWebJSInProcessRuntime
2222
/// <summary>
2323
/// For internal framework use only.
2424
/// </summary>
25-
string InvokeJS(JSInvocationInfo invocationInfo);
25+
string InvokeJS(in JSInvocationInfo invocationInfo);
2626
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
#nullable enable
2-
Microsoft.AspNetCore.Components.Web.Internal.IInternalWebJSInProcessRuntime.InvokeJS(Microsoft.JSInterop.Infrastructure.JSInvocationInfo! invocationInfo) -> string!
2+
Microsoft.AspNetCore.Components.Web.Internal.IInternalWebJSInProcessRuntime.InvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> string!
33
virtual Microsoft.AspNetCore.Components.Routing.NavLink.ShouldMatch(string! uriAbsolute) -> bool

src/Components/Web/src/WebRenderer.cs

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
using Microsoft.Extensions.DependencyInjection;
1111
using Microsoft.Extensions.Logging;
1212
using Microsoft.JSInterop;
13-
using Microsoft.JSInterop.Infrastructure;
1413
using static Microsoft.AspNetCore.Internal.LinkerFlags;
1514

1615
namespace Microsoft.AspNetCore.Components.RenderTree;
@@ -131,16 +130,7 @@ private void AttachWebRendererInterop(IJSRuntime jsRuntime, JsonSerializerOption
131130
newJsonOptions.TypeInfoResolverChain.Add(WebRendererSerializerContext.Default);
132131
newJsonOptions.TypeInfoResolverChain.Add(JsonConverterFactoryTypeInfoResolver<DotNetObjectReference<WebRendererInteropMethods>>.Instance);
133132
var argsJson = JsonSerializer.Serialize(args, newJsonOptions);
134-
var invocationInfo = new JSInvocationInfo
135-
{
136-
AsyncHandle = 0,
137-
TargetInstanceId = 0,
138-
Identifier = JSMethodIdentifier,
139-
CallType = JSCallType.FunctionCall,
140-
ResultType = JSCallResultType.JSVoidResult,
141-
ArgsJson = argsJson,
142-
};
143-
inProcessRuntime.InvokeJS(invocationInfo);
133+
inProcessRuntime.InvokeJS(JSMethodIdentifier, argsJson, JSCallResultType.JSVoidResult, 0);
144134
}
145135
else
146136
{

src/Components/WebAssembly/JSInterop/src/InternalCalls.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ internal static partial class InternalCalls
1818
public static extern TRes InvokeJS<T0, T1, T2, TRes>(out string exception, ref JSCallInfo callInfo, [AllowNull] T0 arg0, [AllowNull] T1 arg1, [AllowNull] T2 arg2);
1919

2020
[JSImport("Blazor._internal.invokeJSJson", "blazor-internal")]
21-
public static partial string InvokeJSJson(string invocationInfoString);
21+
public static partial string InvokeJSJson(
22+
string identifier,
23+
[JSMarshalAs<JSType.Number>] long targetInstanceId,
24+
int resultType,
25+
string argsJson,
26+
[JSMarshalAs<JSType.Number>] long asyncHandle,
27+
int callType);
2228

2329
[JSImport("Blazor._internal.endInvokeDotNetFromJS", "blazor-internal")]
2430
public static partial void EndInvokeDotNetFromJS(
Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
#nullable enable
2-
override Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.BeginInvokeJS(long taskId, string! identifier, string? argsJson, Microsoft.JSInterop.JSCallResultType resultType, long targetInstanceId) -> void
3-
override Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.BeginInvokeJS(Microsoft.JSInterop.Infrastructure.JSInvocationInfo! invocationInfo) -> void
4-
override Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.InvokeJS(Microsoft.JSInterop.Infrastructure.JSInvocationInfo! invocationInfo) -> string!
2+
override Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.BeginInvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> void
3+
override Microsoft.JSInterop.WebAssembly.WebAssemblyJSRuntime.InvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> string!

src/Components/WebAssembly/JSInterop/src/WebAssemblyJSRuntime.cs

Lines changed: 34 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -25,27 +25,29 @@ protected WebAssemblyJSRuntime()
2525
/// <inheritdoc />
2626
protected override string InvokeJS(string identifier, [StringSyntax(StringSyntaxAttribute.Json)] string? argsJson, JSCallResultType resultType, long targetInstanceId)
2727
{
28-
var invocationInfo = new JSInvocationInfo
29-
{
30-
AsyncHandle = 0,
31-
TargetInstanceId = targetInstanceId,
32-
Identifier = identifier,
33-
CallType = JSCallType.FunctionCall,
34-
ResultType = resultType,
35-
ArgsJson = argsJson,
36-
};
37-
38-
return InvokeJS(invocationInfo);
28+
return InternalCalls.InvokeJSJson(
29+
identifier,
30+
targetInstanceId,
31+
(int)resultType,
32+
argsJson ?? "[]",
33+
0,
34+
(int)JSCallType.FunctionCall
35+
);
3936
}
4037

4138
/// <inheritdoc />
42-
protected override string InvokeJS(JSInvocationInfo invocationInfo)
39+
protected override string InvokeJS(in JSInvocationInfo invocationInfo)
4340
{
44-
var invocationInfoJson = invocationInfo.ToJson();
45-
4641
try
4742
{
48-
return InternalCalls.InvokeJSJson(invocationInfoJson);
43+
return InternalCalls.InvokeJSJson(
44+
invocationInfo.Identifier,
45+
invocationInfo.TargetInstanceId,
46+
(int)invocationInfo.ResultType,
47+
invocationInfo.ArgsJson,
48+
invocationInfo.AsyncHandle,
49+
(int)invocationInfo.CallType
50+
);
4951
}
5052
catch (Exception ex)
5153
{
@@ -56,24 +58,27 @@ protected override string InvokeJS(JSInvocationInfo invocationInfo)
5658
/// <inheritdoc />
5759
protected override void BeginInvokeJS(long asyncHandle, string identifier, [StringSyntax(StringSyntaxAttribute.Json)] string? argsJson, JSCallResultType resultType, long targetInstanceId)
5860
{
59-
var invocationInfo = new JSInvocationInfo
60-
{
61-
AsyncHandle = asyncHandle,
62-
TargetInstanceId = targetInstanceId,
63-
Identifier = identifier,
64-
CallType = JSCallType.FunctionCall,
65-
ResultType = resultType,
66-
ArgsJson = argsJson,
67-
};
68-
69-
BeginInvokeJS(invocationInfo);
61+
InternalCalls.InvokeJSJson(
62+
identifier,
63+
targetInstanceId,
64+
(int)resultType,
65+
argsJson ?? "[]",
66+
asyncHandle,
67+
(int)JSCallType.FunctionCall
68+
);
7069
}
7170

7271
/// <inheritdoc />
73-
protected override void BeginInvokeJS(JSInvocationInfo invocationInfo)
72+
protected override void BeginInvokeJS(in JSInvocationInfo invocationInfo)
7473
{
75-
var invocationInfoJson = invocationInfo.ToJson();
76-
InternalCalls.InvokeJSJson(invocationInfoJson);
74+
InternalCalls.InvokeJSJson(
75+
invocationInfo.Identifier,
76+
invocationInfo.TargetInstanceId,
77+
(int)invocationInfo.ResultType,
78+
invocationInfo.ArgsJson,
79+
invocationInfo.AsyncHandle,
80+
(int)invocationInfo.CallType
81+
);
7782
}
7883

7984
/// <inheritdoc />

src/Components/WebAssembly/WebAssembly/src/Services/DefaultWebAssemblyJSRuntime.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,8 @@ protected override Task TransmitStreamAsync(long streamId, DotNetStreamReference
167167
}
168168

169169
string IInternalWebJSInProcessRuntime.InvokeJS(string identifier, string? argsJson, JSCallResultType resultType, long targetInstanceId)
170-
{
171-
var invocationInfo = new JSInvocationInfo
172-
{
173-
AsyncHandle = 0,
174-
TargetInstanceId = targetInstanceId,
175-
Identifier = identifier,
176-
CallType = JSCallType.FunctionCall,
177-
ResultType = resultType,
178-
ArgsJson = argsJson
179-
};
180-
181-
return InvokeJS(invocationInfo);
182-
}
170+
=> InvokeJS(identifier, argsJson, resultType, targetInstanceId);
183171

184-
string IInternalWebJSInProcessRuntime.InvokeJS(JSInvocationInfo invocationInfo)
172+
string IInternalWebJSInProcessRuntime.InvokeJS(in JSInvocationInfo invocationInfo)
185173
=> InvokeJS(invocationInfo);
186174
}

src/Components/WebView/WebView/src/IpcSender.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,17 @@ public void AttachToDocument(int componentId, string selector)
4949
DispatchMessageWithErrorHandling(IpcCommon.Serialize(IpcCommon.OutgoingMessageType.AttachToDocument, componentId, selector));
5050
}
5151

52-
public void BeginInvokeJS(JSInvocationInfo invocationInfo)
52+
public void BeginInvokeJS(in JSInvocationInfo invocationInfo)
5353
{
54-
var invocationInfoJson = invocationInfo.ToJson();
55-
DispatchMessageWithErrorHandling(IpcCommon.Serialize(IpcCommon.OutgoingMessageType.BeginInvokeJS, invocationInfoJson));
54+
DispatchMessageWithErrorHandling(IpcCommon.Serialize(
55+
IpcCommon.OutgoingMessageType.BeginInvokeJS,
56+
invocationInfo.AsyncHandle,
57+
invocationInfo.Identifier,
58+
invocationInfo.ArgsJson,
59+
invocationInfo.ResultType,
60+
invocationInfo.TargetInstanceId,
61+
invocationInfo.CallType
62+
));
5663
}
5764

5865
public void EndInvokeDotNet(string callId, bool success, string invocationResultOrError)

src/Components/WebView/WebView/src/Services/WebViewJSRuntime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ protected override void BeginInvokeJS(long taskId, string identifier, string arg
4343
BeginInvokeJS(invocationInfo);
4444
}
4545

46-
protected override void BeginInvokeJS(JSInvocationInfo invocationInfo)
46+
protected override void BeginInvokeJS(in JSInvocationInfo invocationInfo)
4747
{
4848
if (_ipcSender is null)
4949
{

src/Components/WebView/WebView/test/Infrastructure/AssertHelpers.cs

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,12 @@ namespace Microsoft.AspNetCore.Components.WebView;
1010

1111
public class AssertHelpers
1212
{
13-
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
14-
{
15-
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
16-
};
17-
1813
internal static void IsAttachWebRendererInteropMessage(string message)
1914
{
2015
Assert.True(IpcCommon.TryDeserializeOutgoing(message, out var messageType, out var args));
2116
Assert.Equal(IpcCommon.OutgoingMessageType.BeginInvokeJS, messageType);
22-
Assert.Equal(1, args.Count);
23-
24-
var invocationInfo = JsonSerializer.Deserialize<JSInvocationInfo>(args[0].GetString(), _jsonSerializerOptions);
25-
Assert.Equal("Blazor._internal.attachWebRendererInterop", invocationInfo.Identifier);
17+
Assert.Equal(6, args.Count);
18+
Assert.Equal("Blazor._internal.attachWebRendererInterop", args[1].GetString());
2619
}
2720

2821
internal static void IsAttachToDocumentMessage(string message, int componentId, string selector)

src/JSInterop/Microsoft.JSInterop.JS/src/src/Microsoft.JSInterop.ts

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -297,23 +297,6 @@ export module DotNet {
297297
SetValue = 4
298298
}
299299

300-
/**
301-
* @param asyncHandle A value identifying an asynchronous operation that is passed back in a later call to endInvokeJSFromDotNet. If the call is synchronous, this value is zero.
302-
* @param targetInstanceId The ID of the target JS object instance.
303-
* @param identifier The identifier of the function to invoke or property to access.
304-
* @param callType The type of operation that should be performed in JS.
305-
* @param resultType The type of result expected from the JS interop call.
306-
* @param argsJson JSON array of arguments to be passed to the operation. First element is used when setting a property value.
307-
*/
308-
export interface JSInvocationInfo {
309-
asyncHandle: number,
310-
targetInstanceId: number,
311-
identifier: string,
312-
callType: JSCallType,
313-
resultType: JSCallResultType,
314-
argsJson: string | null,
315-
}
316-
317300
/**
318301
* Represents the ability to dispatch calls from JavaScript to a .NET runtime.
319302
*/
@@ -364,16 +347,26 @@ export module DotNet {
364347
/**
365348
* Invokes the specified synchronous JavaScript function.
366349
*
367-
* @param invocationInfo Configuration of the interop call.
350+
* @param identifier Identifies the globally-reachable function to invoke.
351+
* @param argsJson JSON representation of arguments to be passed to the function.
352+
* @param resultType The type of result expected from the JS interop call.
353+
* @param targetInstanceId The instance ID of the target JS object.
354+
* @param callType The type of operation that should be performed in JS.
355+
* @returns JSON representation of the invocation result.
368356
*/
369-
invokeJSFromDotNet(invocationInfo: JSInvocationInfo): string | null;
357+
invokeJSFromDotNet(identifier: string, argsJson: string, resultType: JSCallResultType, targetInstanceId: number, callType: JSCallType): string | null;
370358

371359
/**
372360
* Invokes the specified synchronous or asynchronous JavaScript function.
373361
*
374-
* @param invocationInfo Configuration of the interop call.
362+
* @param asyncHandle A value identifying the asynchronous operation. This value will be passed back in a later call to endInvokeJSFromDotNet.
363+
* @param identifier Identifies the globally-reachable function to invoke.
364+
* @param argsJson JSON representation of arguments to be passed to the function.
365+
* @param resultType The type of result expected from the JS interop call.
366+
* @param targetInstanceId The ID of the target JS object instance.
367+
* @param callType The type of operation that should be performed in JS.
375368
*/
376-
beginInvokeJSFromDotNet(invocationInfo: JSInvocationInfo): Promise<any> | null;
369+
beginInvokeJSFromDotNet(asyncHandle: number, identifier: string, argsJson: string | null, resultType: JSCallResultType, targetInstanceId: number, callType: JSCallType): Promise<any>;
377370

378371
/**
379372
* Receives notification that an async call from JS to .NET has completed.
@@ -437,8 +430,7 @@ export module DotNet {
437430
return this._dotNetCallDispatcher;
438431
}
439432

440-
invokeJSFromDotNet(invocationInfo: JSInvocationInfo): string | null {
441-
const { targetInstanceId, identifier, callType, resultType, argsJson } = invocationInfo;
433+
invokeJSFromDotNet(identifier: string, argsJson: string, resultType: JSCallResultType, targetInstanceId: number, callType: JSCallType): string | null {
442434
const returnValue = this.handleJSCall(targetInstanceId, identifier, callType, argsJson);
443435
const result = createJSCallResult(returnValue, resultType);
444436

@@ -447,9 +439,7 @@ export module DotNet {
447439
: stringifyArgs(this, result);
448440
}
449441

450-
async beginInvokeJSFromDotNet(invocationInfo: JSInvocationInfo): Promise<any> {
451-
const { asyncHandle, targetInstanceId, identifier, callType, resultType, argsJson } = invocationInfo;
452-
442+
async beginInvokeJSFromDotNet(asyncHandle: number, identifier: string, argsJson: string | null, resultType: JSCallResultType, targetInstanceId: number, callType: JSCallType): Promise<any> {
453443
try {
454444
const valueOrPromise = this.handleJSCall(targetInstanceId, identifier, callType, argsJson);
455445

0 commit comments

Comments
 (0)