JSObjectReference API review follow-up (#25476)
* API review changes. * Fixed JSObjectReferenceJsonConverter * CR feedback * Update JSObjectReferenceExtensions.cs
This commit is contained in:
parent
6ec1b48118
commit
2a0b7dc43e
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
|
|
@ -12,4 +12,8 @@
|
|||
<Reference Include="Microsoft.JSInterop" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)JSInterop\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ namespace Microsoft.JSInterop.WebAssembly
|
|||
var callInfo = new JSCallInfo
|
||||
{
|
||||
FunctionIdentifier = identifier,
|
||||
ResultType = ResultTypeFromGeneric<TResult>()
|
||||
ResultType = JSCallResultTypeHelper.FromGeneric<TResult>()
|
||||
};
|
||||
|
||||
var result = InternalCalls.InvokeJS<T0, T1, T2, TResult>(out var exception, ref callInfo, arg0, arg1, arg2);
|
||||
|
|
|
|||
|
|
@ -137,7 +137,7 @@
|
|||
ReturnValues["returnArray"] = string.Join(",", ((IJSInProcessRuntime)JSRuntime).Invoke<Segment[]>("returnArray").Select(x => x.Source).ToArray());
|
||||
}
|
||||
|
||||
var jsObjectReference = await JSRuntime.InvokeAsync<JSObjectReference>("returnJSObjectReference");
|
||||
var jsObjectReference = await JSRuntime.InvokeAsync<IJSObjectReference>("returnJSObjectReference");
|
||||
ReturnValues["jsObjectReference.identity"] = await jsObjectReference.InvokeAsync<string>("identity", "Invoked from JSObjectReference");
|
||||
ReturnValues["jsObjectReference.nested.add"] = (await jsObjectReference.InvokeAsync<int>("nested.add", 2, 3)).ToString();
|
||||
ReturnValues["addViaJSObjectReference"] = (await JSRuntime.InvokeAsync<int>("addViaJSObjectReference", jsObjectReference, 2, 3)).ToString();
|
||||
|
|
@ -151,7 +151,7 @@
|
|||
JSObjectReferenceInvokeNonFunctionException = e;
|
||||
}
|
||||
|
||||
var module = await JSRuntime.InvokeAsync<JSObjectReference>("import", "./js/testmodule.js");
|
||||
var module = await JSRuntime.InvokeAsync<IJSObjectReference>("import", "./js/testmodule.js");
|
||||
ReturnValues["jsObjectReferenceModule"] = await module.InvokeAsync<string>("identity", "Returned from module!");
|
||||
|
||||
if (shouldSupportSyncInterop)
|
||||
|
|
@ -192,7 +192,7 @@
|
|||
{
|
||||
var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
|
||||
|
||||
var jsInProcObjectReference = inProcRuntime.Invoke<JSInProcessObjectReference>("returnJSObjectReference");
|
||||
var jsInProcObjectReference = inProcRuntime.Invoke<IJSInProcessObjectReference>("returnJSObjectReference");
|
||||
ReturnValues["jsInProcessObjectReference.identity"] = jsInProcObjectReference.Invoke<string>("identity", "Invoked from JSInProcessObjectReference");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -415,20 +415,20 @@ namespace BasicTestApp.InteropTest
|
|||
}
|
||||
|
||||
[JSInvokable]
|
||||
public static JSObjectReference RoundTripJSObjectReference(JSObjectReference jsObjectReference)
|
||||
public static IJSObjectReference RoundTripJSObjectReference(IJSObjectReference jsObjectReference)
|
||||
{
|
||||
return jsObjectReference;
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public static async Task<JSObjectReference> RoundTripJSObjectReferenceAsync(JSObjectReference jSObjectReference)
|
||||
public static async Task<IJSObjectReference> RoundTripJSObjectReferenceAsync(IJSObjectReference jSObjectReference)
|
||||
{
|
||||
await Task.Yield();
|
||||
return jSObjectReference;
|
||||
}
|
||||
|
||||
[JSInvokable]
|
||||
public static string InvokeDisposedJSObjectReferenceException(JSInProcessObjectReference jsObjectReference)
|
||||
public static string InvokeDisposedJSObjectReferenceException(IJSInProcessObjectReference jsObjectReference)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -442,7 +442,7 @@ namespace BasicTestApp.InteropTest
|
|||
}
|
||||
|
||||
[JSInvokable]
|
||||
public static async Task<string> InvokeDisposedJSObjectReferenceExceptionAsync(JSObjectReference jsObjectReference)
|
||||
public static async Task<string> InvokeDisposedJSObjectReferenceExceptionAsync(IJSObjectReference jsObjectReference)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reference to a JavaScript object whose functions can be invoked synchronously.
|
||||
/// </summary>
|
||||
public interface IJSInProcessObjectReference : IJSObjectReference
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function synchronously.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
TValue Invoke<TValue>(string identifier, params object?[]? args);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reference to a JavaScript object.
|
||||
/// </summary>
|
||||
public interface IJSObjectReference : IAsyncDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// <para>
|
||||
/// <see cref="JSRuntime"/> will apply timeouts to this operation based on the value configured in <see cref="JSRuntime.DefaultAsyncTimeout"/>. To dispatch a call with a different, or no timeout,
|
||||
/// consider using <see cref="InvokeAsync{TValue}(string, CancellationToken, object[])" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
ValueTask<TValue> InvokeAsync<TValue>(string identifier, object?[]? args);
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
|
||||
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
|
||||
/// </param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object?[]? args);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,17 +7,21 @@ using System.Text.Json.Serialization;
|
|||
|
||||
namespace Microsoft.JSInterop.Infrastructure
|
||||
{
|
||||
internal sealed class JSObjectReferenceJsonConverter<TJSObjectReference>
|
||||
: JsonConverter<TJSObjectReference> where TJSObjectReference : JSObjectReference
|
||||
internal sealed class JSObjectReferenceJsonConverter<TInterface, TImplementation> : JsonConverter<TInterface>
|
||||
where TInterface : class, IJSObjectReference
|
||||
where TImplementation : JSObjectReference, TInterface
|
||||
{
|
||||
private readonly Func<long, TJSObjectReference> _jsObjectReferenceFactory;
|
||||
private readonly Func<long, TImplementation> _jsObjectReferenceFactory;
|
||||
|
||||
public JSObjectReferenceJsonConverter(Func<long, TJSObjectReference> jsObjectReferenceFactory)
|
||||
public JSObjectReferenceJsonConverter(Func<long, TImplementation> jsObjectReferenceFactory)
|
||||
{
|
||||
_jsObjectReferenceFactory = jsObjectReferenceFactory;
|
||||
}
|
||||
|
||||
public override TJSObjectReference? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
public override bool CanConvert(Type typeToConvert)
|
||||
=> typeToConvert == typeof(TInterface) || typeToConvert == typeof(TImplementation);
|
||||
|
||||
public override TInterface? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
long id = -1;
|
||||
|
||||
|
|
@ -49,10 +53,10 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
return _jsObjectReferenceFactory(id);
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, TJSObjectReference value, JsonSerializerOptions options)
|
||||
public override void Write(Utf8JsonWriter writer, TInterface value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
writer.WriteNumber(JSObjectReference.IdKey, value.Id);
|
||||
writer.WriteNumber(JSObjectReference.IdKey, ((TImplementation)value).Id);
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reference to a JavaScript object whose functions can be invoked synchronously.
|
||||
/// </summary>
|
||||
public class JSInProcessObjectReference : JSObjectReference
|
||||
internal class JSInProcessObjectReference : JSObjectReference, IJSInProcessObjectReference
|
||||
{
|
||||
private readonly JSInProcessRuntime _jsRuntime;
|
||||
|
||||
|
|
@ -17,15 +14,8 @@ namespace Microsoft.JSInterop
|
|||
_jsRuntime = jsRuntime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function synchronously.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
[return: MaybeNull]
|
||||
public TValue Invoke<TValue>(string identifier, params object[] args)
|
||||
public TValue Invoke<TValue>(string identifier, params object?[]? args)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
public static class JSInProcessObjectReferenceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function synchronously.
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSInProcessObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
public static void InvokeVoid(this IJSInProcessObjectReference jsObjectReference, string identifier, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
jsObjectReference.Invoke<object>(identifier, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ namespace Microsoft.JSInterop
|
|||
/// </summary>
|
||||
protected JSInProcessRuntime()
|
||||
{
|
||||
JsonSerializerOptions.Converters.Add(new JSObjectReferenceJsonConverter<JSInProcessObjectReference>(
|
||||
JsonSerializerOptions.Converters.Add(new JSObjectReferenceJsonConverter<IJSInProcessObjectReference, JSInProcessObjectReference>(
|
||||
id => new JSInProcessObjectReference(this, id)));
|
||||
}
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ namespace Microsoft.JSInterop
|
|||
var resultJson = InvokeJS(
|
||||
identifier,
|
||||
JsonSerializer.Serialize(args, JsonSerializerOptions),
|
||||
ResultTypeFromGeneric<TValue>(),
|
||||
JSCallResultTypeHelper.FromGeneric<TValue>(),
|
||||
targetInstanceId);
|
||||
|
||||
if (resultJson is null)
|
||||
|
|
|
|||
|
|
@ -8,77 +8,37 @@ using System.Threading.Tasks;
|
|||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a reference to a JavaScript object.
|
||||
/// </summary>
|
||||
public class JSObjectReference : IAsyncDisposable
|
||||
internal class JSObjectReference : IJSObjectReference
|
||||
{
|
||||
internal static readonly JsonEncodedText IdKey = JsonEncodedText.Encode("__jsObjectId");
|
||||
public static readonly JsonEncodedText IdKey = JsonEncodedText.Encode("__jsObjectId");
|
||||
|
||||
private readonly JSRuntime _jsRuntime;
|
||||
|
||||
private bool _disposed;
|
||||
|
||||
internal long Id { get; }
|
||||
public long Id { get; }
|
||||
|
||||
internal JSObjectReference(JSRuntime jsRuntime, long id)
|
||||
public JSObjectReference(JSRuntime jsRuntime, long id)
|
||||
{
|
||||
_jsRuntime = jsRuntime;
|
||||
|
||||
Id = id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>
|
||||
public async ValueTask InvokeVoidAsync(string identifier, params object[] args)
|
||||
{
|
||||
await InvokeAsync<object>(identifier, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// <para>
|
||||
/// <see cref="JSRuntime"/> will apply timeouts to this operation based on the value configured in <see cref="JSRuntime.DefaultAsyncTimeout"/>. To dispatch a call with a different, or no timeout,
|
||||
/// consider using <see cref="InvokeAsync{TValue}(string, CancellationToken, object[])" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, params object[] args)
|
||||
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, object?[]? args)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _jsRuntime.InvokeAsync<TValue>(Id, identifier, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
|
||||
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
|
||||
/// </param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, params object[] args)
|
||||
public ValueTask<TValue> InvokeAsync<TValue>(string identifier, CancellationToken cancellationToken, object?[]? args)
|
||||
{
|
||||
ThrowIfDisposed();
|
||||
|
||||
return _jsRuntime.InvokeAsync<TValue>(Id, identifier, cancellationToken, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disposes the <see cref="JSObjectReference"/>, freeing its resources and disabling it from further use.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the completion of the operation.</returns>
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (!_disposed)
|
||||
|
|
@ -89,9 +49,6 @@ namespace Microsoft.JSInterop
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Throws an exception if this instance has been disposed.
|
||||
/// </summary>
|
||||
protected void ThrowIfDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="IJSObjectReference"/>.
|
||||
/// </summary>
|
||||
public static class JSObjectReferenceExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>
|
||||
public static async ValueTask InvokeVoidAsync(this IJSObjectReference jsObjectReference, string identifier, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
await jsObjectReference.InvokeAsync<object>(identifier, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// <para>
|
||||
/// <see cref="JSRuntime"/> will apply timeouts to this operation based on the value configured in <see cref="JSRuntime.DefaultAsyncTimeout"/>. To dispatch a call with a different timeout, or no timeout,
|
||||
/// consider using <see cref="IJSObjectReference.InvokeAsync{TValue}(string, CancellationToken, object[])" />.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
public static ValueTask<TValue> InvokeAsync<TValue>(this IJSObjectReference jsObjectReference, string identifier, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
return jsObjectReference.InvokeAsync<TValue>(identifier, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The JSON-serializable return type.</typeparam>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
|
||||
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
|
||||
/// </param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>An instance of <typeparamref name="TValue"/> obtained by JSON-deserializing the return value.</returns>
|
||||
public static ValueTask<TValue> InvokeAsync<TValue>(this IJSObjectReference jsObjectReference, string identifier, CancellationToken cancellationToken, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
return jsObjectReference.InvokeAsync<TValue>(identifier, cancellationToken, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="cancellationToken">
|
||||
/// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts
|
||||
/// (<see cref="JSRuntime.DefaultAsyncTimeout"/>) from being applied.
|
||||
/// </param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>
|
||||
public static async ValueTask InvokeVoidAsync(this IJSObjectReference jsObjectReference, string identifier, CancellationToken cancellationToken, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
await jsObjectReference.InvokeAsync<object>(identifier, cancellationToken, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="timeout">The duration after which to cancel the async operation. Overrides default timeouts (<see cref="JSRuntime.DefaultAsyncTimeout"/>).</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>
|
||||
public static async ValueTask<TValue> InvokeAsync<TValue>(this IJSObjectReference jsObjectReference, string identifier, TimeSpan timeout, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
using var cancellationTokenSource = timeout == Timeout.InfiniteTimeSpan ? null : new CancellationTokenSource(timeout);
|
||||
var cancellationToken = cancellationTokenSource?.Token ?? CancellationToken.None;
|
||||
|
||||
return await jsObjectReference.InvokeAsync<TValue>(identifier, cancellationToken, args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// </summary>
|
||||
/// <param name="jsObjectReference">The <see cref="IJSObjectReference"/>.</param>
|
||||
/// <param name="identifier">An identifier for the function to invoke. For example, the value <c>"someScope.someFunction"</c> will invoke the function <c>someScope.someFunction</c> on the target instance.</param>
|
||||
/// <param name="timeout">The duration after which to cancel the async operation. Overrides default timeouts (<see cref="JSRuntime.DefaultAsyncTimeout"/>).</param>
|
||||
/// <param name="args">JSON-serializable arguments.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> that represents the asynchronous invocation operation.</returns>
|
||||
public static async ValueTask InvokeVoidAsync(this IJSObjectReference jsObjectReference, string identifier, TimeSpan timeout, params object?[] args)
|
||||
{
|
||||
if (jsObjectReference is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(jsObjectReference));
|
||||
}
|
||||
|
||||
using var cancellationTokenSource = timeout == Timeout.InfiniteTimeSpan ? null : new CancellationTokenSource(timeout);
|
||||
var cancellationToken = cancellationTokenSource?.Token ?? CancellationToken.None;
|
||||
|
||||
await jsObjectReference.InvokeAsync<object>(identifier, cancellationToken, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,7 @@ namespace Microsoft.JSInterop
|
|||
Converters =
|
||||
{
|
||||
new DotNetObjectReferenceJsonConverterFactory(this),
|
||||
new JSObjectReferenceJsonConverter<JSObjectReference>(id => new JSObjectReference(this, id)),
|
||||
new JSObjectReferenceJsonConverter<IJSObjectReference, JSObjectReference>(id => new JSObjectReference(this, id)),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
@ -52,17 +52,6 @@ namespace Microsoft.JSInterop
|
|||
/// </summary>
|
||||
protected TimeSpan? DefaultAsyncTimeout { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="JSCallResultType"/> from the given generic type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">
|
||||
/// The type of the result of the relevant JS interop call.
|
||||
/// </typeparam>
|
||||
protected static JSCallResultType ResultTypeFromGeneric<TResult>()
|
||||
=> typeof(TResult) == typeof(JSObjectReference) || typeof(TResult) == typeof(JSInProcessObjectReference) ?
|
||||
JSCallResultType.JSObjectReference :
|
||||
JSCallResultType.Default;
|
||||
|
||||
/// <summary>
|
||||
/// Invokes the specified JavaScript function asynchronously.
|
||||
/// <para>
|
||||
|
|
@ -134,7 +123,7 @@ namespace Microsoft.JSInterop
|
|||
var argsJson = args?.Any() == true ?
|
||||
JsonSerializer.Serialize(args, JsonSerializerOptions) :
|
||||
null;
|
||||
var resultType = ResultTypeFromGeneric<TValue>();
|
||||
var resultType = JSCallResultTypeHelper.FromGeneric<TValue>();
|
||||
|
||||
BeginInvokeJS(taskId, identifier, argsJson, resultType, targetInstanceId);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>$(DefaultNetCoreTargetFramework)</TargetFramework>
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
<Reference Include="System.Text.Json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedSourceRoot)JSInterop\*.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="Microsoft.JSInterop.Tests" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var json = "{}";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<JSObjectReference>(json, JsonSerializerOptions));
|
||||
var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions));
|
||||
Assert.Equal("Required property __jsObjectId not found.", ex.Message);
|
||||
}
|
||||
|
||||
|
|
@ -29,7 +29,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var json = "{\"foo\":2}";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<JSObjectReference>(json, JsonSerializerOptions));
|
||||
var ex = Assert.Throws<JsonException>(() => JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions));
|
||||
Assert.Equal("Unexcepted JSON property foo.", ex.Message);
|
||||
}
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var json = $"{{\"__jsObjectId\":5";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Record.Exception(() => JsonSerializer.Deserialize<JSObjectReference>(json, JsonSerializerOptions));
|
||||
var ex = Record.Exception(() => JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions));
|
||||
Assert.IsAssignableFrom<JsonException>(ex);
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var json = $"{{\"__jsObjectId\":3,\"__jsObjectId\":7}}";
|
||||
|
||||
// Act & Assert
|
||||
var ex = Record.Exception(() => JsonSerializer.Deserialize<JSObjectReference>(json, JsonSerializerOptions));
|
||||
var ex = Record.Exception(() => JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions));
|
||||
Assert.IsAssignableFrom<JsonException>(ex);
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +63,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var json = $"{{\"__jsObjectId\":{expectedId}}}";
|
||||
|
||||
// Act
|
||||
var deserialized = JsonSerializer.Deserialize<JSObjectReference>(json, JsonSerializerOptions)!;
|
||||
var deserialized = (JSObjectReference)JsonSerializer.Deserialize<IJSObjectReference>(json, JsonSerializerOptions)!;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(expectedId, deserialized?.Id);
|
||||
|
|
@ -76,7 +76,7 @@ namespace Microsoft.JSInterop.Infrastructure
|
|||
var jsObjectRef = new JSObjectReference(JSRuntime, 7);
|
||||
|
||||
// Act
|
||||
var json = JsonSerializer.Serialize(jsObjectRef, JsonSerializerOptions);
|
||||
var json = JsonSerializer.Serialize((IJSObjectReference)jsObjectRef, JsonSerializerOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Equal($"{{\"__jsObjectId\":{jsObjectRef.Id}}}", json);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright (c) .NET Foundation. All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
|
||||
namespace Microsoft.JSInterop
|
||||
{
|
||||
internal static class JSCallResultTypeHelper
|
||||
{
|
||||
public static JSCallResultType FromGeneric<TResult>()
|
||||
=> typeof(TResult) == typeof(IJSObjectReference) || typeof(TResult) == typeof(IJSInProcessObjectReference) ?
|
||||
JSCallResultType.JSObjectReference :
|
||||
JSCallResultType.Default;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue