Skip to content

Commit 2f84ea0

Browse files
committed
Code review fixes
1 parent c13223b commit 2f84ea0

File tree

6 files changed

+62
-100
lines changed

6 files changed

+62
-100
lines changed
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4+
using System.Diagnostics.CodeAnalysis;
45
using Microsoft.JSInterop;
6+
using static Microsoft.AspNetCore.Internal.LinkerFlags;
57

68
namespace Microsoft.AspNetCore.Components.Endpoints;
79

810
internal sealed class UnsupportedJavaScriptRuntime : IJSRuntime
911
{
1012
private const string Message = "JavaScript interop calls cannot be issued during server-side static rendering, because the page has not yet loaded in the browser. Statically-rendered components must wrap any JavaScript interop calls in conditional logic to ensure those interop calls are not attempted during static rendering.";
1113

12-
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object?[]? args)
14+
public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken, object?[]? args)
1315
=> throw new InvalidOperationException(Message);
1416

15-
ValueTask<TValue> IJSRuntime.InvokeAsync<TValue>(string identifier, object?[]? args)
17+
ValueTask<TValue> IJSRuntime.InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, object?[]? args)
1618
=> throw new InvalidOperationException(Message);
1719

1820
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object?[]? args)
@@ -21,15 +23,15 @@ public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object?[]
2123
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args)
2224
=> throw new InvalidOperationException(Message);
2325

24-
public ValueTask<TValue> GetValueAsync<TValue>(string identifier)
26+
public ValueTask<TValue> GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier)
2527
=> throw new InvalidOperationException(Message);
2628

27-
public ValueTask<TValue> GetValueAsync<TValue>(string identifier, CancellationToken cancellationToken)
29+
public ValueTask<TValue> GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken)
2830
=> throw new InvalidOperationException(Message);
2931

30-
public ValueTask SetValueAsync<TValue>(string identifier, TValue value)
32+
public ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value)
3133
=> throw new InvalidOperationException(Message);
3234

33-
public ValueTask SetValueAsync<TValue>(string identifier, TValue value, CancellationToken cancellationToken)
35+
public ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken)
3436
=> throw new InvalidOperationException(Message);
3537
}

src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticationServiceTests.cs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -544,34 +544,22 @@ public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToke
544544
}
545545

546546
public ValueTask<TValue> GetValueAsync<TValue>(string identifier)
547-
{
548-
throw new NotImplementedException();
549-
}
547+
=> throw new NotImplementedException();
550548

551549
public ValueTask<TValue> GetValueAsync<TValue>(string identifier, CancellationToken cancellationToken)
552-
{
553-
throw new NotImplementedException();
554-
}
550+
=> throw new NotImplementedException();
555551

556552
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object[] args)
557-
{
558-
throw new NotImplementedException();
559-
}
553+
=> throw new NotImplementedException();
560554

561555
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, CancellationToken cancellationToken, object[] args)
562-
{
563-
throw new NotImplementedException();
564-
}
556+
=> throw new NotImplementedException();
565557

566558
public ValueTask SetValueAsync<TValue>(string identifier, TValue value)
567-
{
568-
throw new NotImplementedException();
569-
}
559+
=> throw new NotImplementedException();
570560

571561
public ValueTask SetValueAsync<TValue>(string identifier, TValue value, CancellationToken cancellationToken)
572-
{
573-
throw new NotImplementedException();
574-
}
562+
=> throw new NotImplementedException();
575563

576564
private object GetInvocationResult(string identifier)
577565
{

src/Components/WebAssembly/WebAssembly.Authentication/test/RemoteAuthenticatorCoreTests.cs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -791,33 +791,22 @@ public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToke
791791
}
792792

793793
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object[] args)
794-
{
795-
throw new NotImplementedException();
796-
}
794+
=> throw new NotImplementedException();
797795

798796
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, CancellationToken cancellationToken, object[] args)
799-
{
800-
throw new NotImplementedException();
801-
}
797+
=> throw new NotImplementedException();
802798

803799
public ValueTask<TValue> GetValueAsync<TValue>(string identifier)
804-
{
805-
throw new NotImplementedException();
806-
}
800+
=> throw new NotImplementedException();
807801

808802
public ValueTask<TValue> GetValueAsync<TValue>(string identifier, CancellationToken cancellationToken)
809-
{
810-
throw new NotImplementedException();
811-
}
803+
=> throw new NotImplementedException();
804+
812805
public ValueTask SetValueAsync<TValue>(string identifier, TValue value)
813-
{
814-
throw new NotImplementedException();
815-
}
806+
=> throw new NotImplementedException();
816807

817808
public ValueTask SetValueAsync<TValue>(string identifier, TValue value, CancellationToken cancellationToken)
818-
{
819-
throw new NotImplementedException();
820-
}
809+
=> throw new NotImplementedException();
821810
}
822811

823812
public class TestRemoteAuthenticatorView : RemoteAuthenticatorViewCore<RemoteAuthenticationState>

src/Components/WebAssembly/WebAssembly/test/PullFromJSDataStreamTest.cs

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -131,39 +131,25 @@ public virtual ValueTask<TValue> InvokeAsync<TValue>(string identifier, Cancella
131131
}
132132

133133
public async ValueTask<TValue> InvokeAsync<TValue>(string identifier, object[] args)
134-
{
135-
return await InvokeAsync<TValue>(identifier, CancellationToken.None, args);
136-
}
134+
=> await InvokeAsync<TValue>(identifier, CancellationToken.None, args);
137135

138136
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object[] args)
139-
{
140-
throw new NotImplementedException();
141-
}
137+
=> throw new NotImplementedException();
142138

143139
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, CancellationToken cancellationToken, object[] args)
144-
{
145-
throw new NotImplementedException();
146-
}
140+
=> throw new NotImplementedException();
147141

148142
public ValueTask<TValue> GetValueAsync<TValue>(string identifier)
149-
{
150-
throw new NotImplementedException();
151-
}
143+
=> throw new NotImplementedException();
152144

153145
public ValueTask<TValue> GetValueAsync<TValue>(string identifier, CancellationToken cancellationToken)
154-
{
155-
throw new NotImplementedException();
156-
}
146+
=> throw new NotImplementedException();
157147

158148
public ValueTask SetValueAsync<TValue>(string identifier, TValue value)
159-
{
160-
throw new NotImplementedException();
161-
}
149+
=> throw new NotImplementedException();
162150

163151
public ValueTask SetValueAsync<TValue>(string identifier, TValue value, CancellationToken cancellationToken)
164-
{
165-
throw new NotImplementedException();
166-
}
152+
=> throw new NotImplementedException();
167153
}
168154

169155
class TestJSRuntime_ProvidesInsufficientData : TestJSRuntime

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

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -446,36 +446,32 @@ export module DotNet {
446446
: stringifyArgs(this, result);
447447
}
448448

449-
beginInvokeJSFromDotNet(invocationInfo: JSInvocationInfo): Promise<any> | null {
449+
async beginInvokeJSFromDotNet(invocationInfo: JSInvocationInfo): Promise<any> {
450450
const { asyncHandle, targetInstanceId, identifier, callType, resultType, argsJson } = invocationInfo;
451451

452-
// Coerce synchronous functions into async ones, plus treat
453-
// synchronous exceptions the same as async ones
454-
const promise = new Promise<any>(resolve => {
455-
const valueOrPromise = this.handleJSCall(targetInstanceId, identifier, callType, argsJson);
456-
resolve(valueOrPromise);
457-
});
458-
459-
// We only listen for a result if the caller wants to be notified about it
460-
if (asyncHandle) {
461-
// On completion, dispatch result back to .NET
462-
// Not using "await" because it codegens a lot of boilerplate
463-
return promise.
464-
then(result => stringifyArgs(this, [
465-
asyncHandle,
466-
true,
467-
createJSCallResult(result, resultType)
468-
])).
469-
then(
470-
result => this._dotNetCallDispatcher.endInvokeJSFromDotNet(asyncHandle, true, result),
471-
error => this._dotNetCallDispatcher.endInvokeJSFromDotNet(asyncHandle, false, JSON.stringify([
472-
asyncHandle,
473-
false,
474-
formatError(error)
475-
]))
476-
);
477-
} else {
478-
return null;
452+
try {
453+
const valueOrPromise = this.handleJSCall(targetInstanceId, identifier, callType, argsJson);
454+
455+
// We only listen for a result if the caller wants to be notified about it
456+
if (asyncHandle) {
457+
// On completion, dispatch result back to .NET
458+
const result = await valueOrPromise;
459+
const serializedResult = stringifyArgs(this, [
460+
asyncHandle,
461+
true,
462+
createJSCallResult(result, resultType)
463+
]);
464+
this._dotNetCallDispatcher.endInvokeJSFromDotNet(asyncHandle, true, serializedResult);
465+
}
466+
} catch(error: any) {
467+
if (asyncHandle) {
468+
const serializedError = JSON.stringify([
469+
asyncHandle,
470+
false,
471+
formatError(error)
472+
]);
473+
this._dotNetCallDispatcher.endInvokeJSFromDotNet(asyncHandle, false, serializedError);
474+
}
479475
}
480476
}
481477

src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace Microsoft.JSInterop;
1515
/// </summary>
1616
public abstract partial class JSRuntime : IJSRuntime, IDisposable
1717
{
18+
private const long WindowObjectId = 0;
1819
private long _nextObjectReferenceId; // Initial value of 0 signals no object, but we increment prior to assignment. The first tracked object should have id 1
1920
private long _nextPendingTaskId = 1; // Start at 1 because zero signals "no response needed"
2021
private readonly ConcurrentDictionary<long, object> _pendingTasks = new();
@@ -66,7 +67,7 @@ protected JSRuntime()
6667
/// <param name="args">JSON-serializable arguments.</param>
6768
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
6869
public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, object?[]? args)
69-
=> InvokeAsync<TValue>(0, identifier, JSCallType.FunctionCall, args);
70+
=> InvokeAsync<TValue>(WindowObjectId, identifier, JSCallType.FunctionCall, args);
7071

7172
/// <summary>
7273
/// Invokes the specified JavaScript function asynchronously.
@@ -80,31 +81,31 @@ protected JSRuntime()
8081
/// <param name="args">JSON-serializable arguments.</param>
8182
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
8283
public ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken, object?[]? args)
83-
=> InvokeAsync<TValue>(0, identifier, JSCallType.FunctionCall, cancellationToken, args);
84+
=> InvokeAsync<TValue>(WindowObjectId, identifier, JSCallType.FunctionCall, cancellationToken, args);
8485

8586
/// <inheritdoc />
8687
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, object?[]? args)
87-
=> InvokeAsync<IJSObjectReference>(0, identifier, JSCallType.NewCall, args);
88+
=> InvokeAsync<IJSObjectReference>(WindowObjectId, identifier, JSCallType.NewCall, args);
8889

8990
/// <inheritdoc />
9091
public ValueTask<IJSObjectReference> InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args)
91-
=> InvokeAsync<IJSObjectReference>(0, identifier, JSCallType.NewCall, cancellationToken, args);
92+
=> InvokeAsync<IJSObjectReference>(WindowObjectId, identifier, JSCallType.NewCall, cancellationToken, args);
9293

9394
/// <inheritdoc />
9495
public ValueTask<TValue> GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier)
95-
=> InvokeAsync<TValue>(0, identifier, JSCallType.GetValue, null);
96+
=> InvokeAsync<TValue>(WindowObjectId, identifier, JSCallType.GetValue, null);
9697

9798
/// <inheritdoc />
9899
public ValueTask<TValue> GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken)
99-
=> InvokeAsync<TValue>(0, identifier, JSCallType.GetValue, cancellationToken, null);
100+
=> InvokeAsync<TValue>(WindowObjectId, identifier, JSCallType.GetValue, cancellationToken, null);
100101

101102
/// <inheritdoc />
102103
public async ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value)
103-
=> await InvokeAsync<IJSVoidResult>(0, identifier, JSCallType.SetValue, [value]);
104+
=> await InvokeAsync<IJSVoidResult>(WindowObjectId, identifier, JSCallType.SetValue, [value]);
104105

105106
/// <inheritdoc />
106107
public async ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken)
107-
=> await InvokeAsync<IJSVoidResult>(0, identifier, JSCallType.SetValue, cancellationToken, [value]);
108+
=> await InvokeAsync<IJSVoidResult>(WindowObjectId, identifier, JSCallType.SetValue, cancellationToken, [value]);
108109

109110
internal async ValueTask<TValue> InvokeAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(long targetInstanceId, string identifier, JSCallType callType, object?[]? args)
110111
{
@@ -191,7 +192,7 @@ protected virtual void BeginInvokeJS(long taskId, string identifier, [StringSynt
191192
var invocationInfo = new JSInvocationInfo
192193
{
193194
AsyncHandle = taskId,
194-
TargetInstanceId = 0,
195+
TargetInstanceId = WindowObjectId,
195196
Identifier = identifier,
196197
CallType = JSCallType.FunctionCall,
197198
ResultType = JSCallResultType.Default,

0 commit comments

Comments
 (0)