diff --git a/src/Components/WebAssembly/JSInterop/src/Microsoft.JSInterop.WebAssembly.csproj b/src/Components/WebAssembly/JSInterop/src/Microsoft.JSInterop.WebAssembly.csproj index 8b58eb02dd..2d7aabeee7 100644 --- a/src/Components/WebAssembly/JSInterop/src/Microsoft.JSInterop.WebAssembly.csproj +++ b/src/Components/WebAssembly/JSInterop/src/Microsoft.JSInterop.WebAssembly.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) @@ -12,4 +12,8 @@ + + + + diff --git a/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSRuntime.cs b/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSRuntime.cs index 14e1600b9f..cbc07b36a9 100644 --- a/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSRuntime.cs +++ b/src/Components/WebAssembly/JSInterop/src/WebAssemblyJSRuntime.cs @@ -78,7 +78,7 @@ namespace Microsoft.JSInterop.WebAssembly var callInfo = new JSCallInfo { FunctionIdentifier = identifier, - ResultType = ResultTypeFromGeneric() + ResultType = JSCallResultTypeHelper.FromGeneric() }; var result = InternalCalls.InvokeJS(out var exception, ref callInfo, arg0, arg1, arg2); diff --git a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor index b24da1366b..388e745493 100644 --- a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor @@ -137,7 +137,7 @@ ReturnValues["returnArray"] = string.Join(",", ((IJSInProcessRuntime)JSRuntime).Invoke("returnArray").Select(x => x.Source).ToArray()); } - var jsObjectReference = await JSRuntime.InvokeAsync("returnJSObjectReference"); + var jsObjectReference = await JSRuntime.InvokeAsync("returnJSObjectReference"); ReturnValues["jsObjectReference.identity"] = await jsObjectReference.InvokeAsync("identity", "Invoked from JSObjectReference"); ReturnValues["jsObjectReference.nested.add"] = (await jsObjectReference.InvokeAsync("nested.add", 2, 3)).ToString(); ReturnValues["addViaJSObjectReference"] = (await JSRuntime.InvokeAsync("addViaJSObjectReference", jsObjectReference, 2, 3)).ToString(); @@ -151,7 +151,7 @@ JSObjectReferenceInvokeNonFunctionException = e; } - var module = await JSRuntime.InvokeAsync("import", "./js/testmodule.js"); + var module = await JSRuntime.InvokeAsync("import", "./js/testmodule.js"); ReturnValues["jsObjectReferenceModule"] = await module.InvokeAsync("identity", "Returned from module!"); if (shouldSupportSyncInterop) @@ -192,7 +192,7 @@ { var inProcRuntime = ((IJSInProcessRuntime)JSRuntime); - var jsInProcObjectReference = inProcRuntime.Invoke("returnJSObjectReference"); + var jsInProcObjectReference = inProcRuntime.Invoke("returnJSObjectReference"); ReturnValues["jsInProcessObjectReference.identity"] = jsInProcObjectReference.Invoke("identity", "Invoked from JSInProcessObjectReference"); } diff --git a/src/Components/test/testassets/BasicTestApp/InteropTest/JavaScriptInterop.cs b/src/Components/test/testassets/BasicTestApp/InteropTest/JavaScriptInterop.cs index 8667bdc2c6..55fc6e8fc6 100644 --- a/src/Components/test/testassets/BasicTestApp/InteropTest/JavaScriptInterop.cs +++ b/src/Components/test/testassets/BasicTestApp/InteropTest/JavaScriptInterop.cs @@ -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 RoundTripJSObjectReferenceAsync(JSObjectReference jSObjectReference) + public static async Task 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 InvokeDisposedJSObjectReferenceExceptionAsync(JSObjectReference jsObjectReference) + public static async Task InvokeDisposedJSObjectReferenceExceptionAsync(IJSObjectReference jsObjectReference) { try { diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs new file mode 100644 index 0000000000..2c3cbbde69 --- /dev/null +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs @@ -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 +{ + /// + /// Represents a reference to a JavaScript object whose functions can be invoked synchronously. + /// + public interface IJSInProcessObjectReference : IJSObjectReference + { + /// + /// Invokes the specified JavaScript function synchronously. + /// + /// The JSON-serializable return type. + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// JSON-serializable arguments. + /// An instance of obtained by JSON-deserializing the return value. + TValue Invoke(string identifier, params object?[]? args); + } +} diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs new file mode 100644 index 0000000000..43e67f0cb1 --- /dev/null +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs @@ -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 +{ + /// + /// Represents a reference to a JavaScript object. + /// + public interface IJSObjectReference : IAsyncDisposable + { + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// will apply timeouts to this operation based on the value configured in . To dispatch a call with a different, or no timeout, + /// consider using . + /// + /// + /// The JSON-serializable return type. + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// JSON-serializable arguments. + /// An instance of obtained by JSON-deserializing the return value. + ValueTask InvokeAsync(string identifier, object?[]? args); + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The JSON-serializable return type. + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// + /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts + /// () from being applied. + /// + /// JSON-serializable arguments. + /// An instance of obtained by JSON-deserializing the return value. + ValueTask InvokeAsync(string identifier, CancellationToken cancellationToken, object?[]? args); + } +} diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs index f26efa92a1..d18f7092b6 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/JSObjectReferenceJsonConverter.cs @@ -7,17 +7,21 @@ using System.Text.Json.Serialization; namespace Microsoft.JSInterop.Infrastructure { - internal sealed class JSObjectReferenceJsonConverter - : JsonConverter where TJSObjectReference : JSObjectReference + internal sealed class JSObjectReferenceJsonConverter : JsonConverter + where TInterface : class, IJSObjectReference + where TImplementation : JSObjectReference, TInterface { - private readonly Func _jsObjectReferenceFactory; + private readonly Func _jsObjectReferenceFactory; - public JSObjectReferenceJsonConverter(Func jsObjectReferenceFactory) + public JSObjectReferenceJsonConverter(Func 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(); } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReference.cs index bd97a8f7a0..44dcba7287 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReference.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReference.cs @@ -5,10 +5,7 @@ using System.Diagnostics.CodeAnalysis; namespace Microsoft.JSInterop { - /// - /// Represents a reference to a JavaScript object whose functions can be invoked synchronously. - /// - public class JSInProcessObjectReference : JSObjectReference + internal class JSInProcessObjectReference : JSObjectReference, IJSInProcessObjectReference { private readonly JSInProcessRuntime _jsRuntime; @@ -17,15 +14,8 @@ namespace Microsoft.JSInterop _jsRuntime = jsRuntime; } - /// - /// Invokes the specified JavaScript function synchronously. - /// - /// The JSON-serializable return type. - /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. - /// JSON-serializable arguments. - /// An instance of obtained by JSON-deserializing the return value. [return: MaybeNull] - public TValue Invoke(string identifier, params object[] args) + public TValue Invoke(string identifier, params object?[]? args) { ThrowIfDisposed(); diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReferenceExtensions.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReferenceExtensions.cs new file mode 100644 index 0000000000..57b9cc66fe --- /dev/null +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessObjectReferenceExtensions.cs @@ -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 + { + /// + /// Invokes the specified JavaScript function synchronously. + /// + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// JSON-serializable arguments. + public static void InvokeVoid(this IJSInProcessObjectReference jsObjectReference, string identifier, params object?[] args) + { + if (jsObjectReference == null) + { + throw new ArgumentNullException(nameof(jsObjectReference)); + } + + jsObjectReference.Invoke(identifier, args); + } + } +} diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs index 092f295330..2912c2db06 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs @@ -17,7 +17,7 @@ namespace Microsoft.JSInterop /// protected JSInProcessRuntime() { - JsonSerializerOptions.Converters.Add(new JSObjectReferenceJsonConverter( + JsonSerializerOptions.Converters.Add(new JSObjectReferenceJsonConverter( id => new JSInProcessObjectReference(this, id))); } @@ -27,7 +27,7 @@ namespace Microsoft.JSInterop var resultJson = InvokeJS( identifier, JsonSerializer.Serialize(args, JsonSerializerOptions), - ResultTypeFromGeneric(), + JSCallResultTypeHelper.FromGeneric(), targetInstanceId); if (resultJson is null) diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/JSObjectReference.cs index ef98c2dfc9..ea87657a07 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSObjectReference.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSObjectReference.cs @@ -8,77 +8,37 @@ using System.Threading.Tasks; namespace Microsoft.JSInterop { - /// - /// Represents a reference to a JavaScript object. - /// - 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; } - /// - /// Invokes the specified JavaScript function asynchronously. - /// - /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. - /// JSON-serializable arguments. - /// A that represents the asynchronous invocation operation. - public async ValueTask InvokeVoidAsync(string identifier, params object[] args) - { - await InvokeAsync(identifier, args); - } - - /// - /// Invokes the specified JavaScript function asynchronously. - /// - /// will apply timeouts to this operation based on the value configured in . To dispatch a call with a different, or no timeout, - /// consider using . - /// - /// - /// The JSON-serializable return type. - /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. - /// JSON-serializable arguments. - /// An instance of obtained by JSON-deserializing the return value. - public ValueTask InvokeAsync(string identifier, params object[] args) + public ValueTask InvokeAsync(string identifier, object?[]? args) { ThrowIfDisposed(); return _jsRuntime.InvokeAsync(Id, identifier, args); } - /// - /// Invokes the specified JavaScript function asynchronously. - /// - /// The JSON-serializable return type. - /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. - /// - /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts - /// () from being applied. - /// - /// JSON-serializable arguments. - /// An instance of obtained by JSON-deserializing the return value. - public ValueTask InvokeAsync(string identifier, CancellationToken cancellationToken, params object[] args) + public ValueTask InvokeAsync(string identifier, CancellationToken cancellationToken, object?[]? args) { ThrowIfDisposed(); return _jsRuntime.InvokeAsync(Id, identifier, cancellationToken, args); } - /// - /// Disposes the , freeing its resources and disabling it from further use. - /// - /// A representing the completion of the operation. public async ValueTask DisposeAsync() { if (!_disposed) @@ -89,9 +49,6 @@ namespace Microsoft.JSInterop } } - /// - /// Throws an exception if this instance has been disposed. - /// protected void ThrowIfDisposed() { if (_disposed) diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSObjectReferenceExtensions.cs b/src/JSInterop/Microsoft.JSInterop/src/JSObjectReferenceExtensions.cs new file mode 100644 index 0000000000..ee5d658cf6 --- /dev/null +++ b/src/JSInterop/Microsoft.JSInterop/src/JSObjectReferenceExtensions.cs @@ -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 +{ + /// + /// Extensions for . + /// + public static class JSObjectReferenceExtensions + { + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// JSON-serializable arguments. + /// A that represents the asynchronous invocation operation. + 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(identifier, args); + } + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// will apply timeouts to this operation based on the value configured in . To dispatch a call with a different timeout, or no timeout, + /// consider using . + /// + /// + /// The . + /// The JSON-serializable return type. + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// JSON-serializable arguments. + /// An instance of obtained by JSON-deserializing the return value. + public static ValueTask InvokeAsync(this IJSObjectReference jsObjectReference, string identifier, params object?[] args) + { + if (jsObjectReference is null) + { + throw new ArgumentNullException(nameof(jsObjectReference)); + } + + return jsObjectReference.InvokeAsync(identifier, args); + } + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The JSON-serializable return type. + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// + /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts + /// () from being applied. + /// + /// JSON-serializable arguments. + /// An instance of obtained by JSON-deserializing the return value. + public static ValueTask InvokeAsync(this IJSObjectReference jsObjectReference, string identifier, CancellationToken cancellationToken, params object?[] args) + { + if (jsObjectReference is null) + { + throw new ArgumentNullException(nameof(jsObjectReference)); + } + + return jsObjectReference.InvokeAsync(identifier, cancellationToken, args); + } + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// + /// A cancellation token to signal the cancellation of the operation. Specifying this parameter will override any default cancellations such as due to timeouts + /// () from being applied. + /// + /// JSON-serializable arguments. + /// A that represents the asynchronous invocation operation. + 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(identifier, cancellationToken, args); + } + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// The duration after which to cancel the async operation. Overrides default timeouts (). + /// JSON-serializable arguments. + /// A that represents the asynchronous invocation operation. + public static async ValueTask InvokeAsync(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(identifier, cancellationToken, args); + } + + /// + /// Invokes the specified JavaScript function asynchronously. + /// + /// The . + /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function someScope.someFunction on the target instance. + /// The duration after which to cancel the async operation. Overrides default timeouts (). + /// JSON-serializable arguments. + /// A that represents the asynchronous invocation operation. + 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(identifier, cancellationToken, args); + } + } +} diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs index 7e69eb3d21..25a885a7b9 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs @@ -37,7 +37,7 @@ namespace Microsoft.JSInterop Converters = { new DotNetObjectReferenceJsonConverterFactory(this), - new JSObjectReferenceJsonConverter(id => new JSObjectReference(this, id)), + new JSObjectReferenceJsonConverter(id => new JSObjectReference(this, id)), } }; } @@ -52,17 +52,6 @@ namespace Microsoft.JSInterop /// protected TimeSpan? DefaultAsyncTimeout { get; set; } - /// - /// Creates a from the given generic type. - /// - /// - /// The type of the result of the relevant JS interop call. - /// - protected static JSCallResultType ResultTypeFromGeneric() - => typeof(TResult) == typeof(JSObjectReference) || typeof(TResult) == typeof(JSInProcessObjectReference) ? - JSCallResultType.JSObjectReference : - JSCallResultType.Default; - /// /// Invokes the specified JavaScript function asynchronously. /// @@ -134,7 +123,7 @@ namespace Microsoft.JSInterop var argsJson = args?.Any() == true ? JsonSerializer.Serialize(args, JsonSerializerOptions) : null; - var resultType = ResultTypeFromGeneric(); + var resultType = JSCallResultTypeHelper.FromGeneric(); BeginInvokeJS(taskId, identifier, argsJson, resultType, targetInstanceId); diff --git a/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj b/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj index ebdf3cd319..4667991833 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj +++ b/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj @@ -1,4 +1,4 @@ - + $(DefaultNetCoreTargetFramework) @@ -13,6 +13,10 @@ + + + + diff --git a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs index 75f4388c15..0b7948cf56 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/JSObjectReferenceJsonConverterTest.cs @@ -18,7 +18,7 @@ namespace Microsoft.JSInterop.Infrastructure var json = "{}"; // Act & Assert - var ex = Assert.Throws(() => JsonSerializer.Deserialize(json, JsonSerializerOptions)); + var ex = Assert.Throws(() => JsonSerializer.Deserialize(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(() => JsonSerializer.Deserialize(json, JsonSerializerOptions)); + var ex = Assert.Throws(() => JsonSerializer.Deserialize(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(json, JsonSerializerOptions)); + var ex = Record.Exception(() => JsonSerializer.Deserialize(json, JsonSerializerOptions)); Assert.IsAssignableFrom(ex); } @@ -51,7 +51,7 @@ namespace Microsoft.JSInterop.Infrastructure var json = $"{{\"__jsObjectId\":3,\"__jsObjectId\":7}}"; // Act & Assert - var ex = Record.Exception(() => JsonSerializer.Deserialize(json, JsonSerializerOptions)); + var ex = Record.Exception(() => JsonSerializer.Deserialize(json, JsonSerializerOptions)); Assert.IsAssignableFrom(ex); } @@ -63,7 +63,7 @@ namespace Microsoft.JSInterop.Infrastructure var json = $"{{\"__jsObjectId\":{expectedId}}}"; // Act - var deserialized = JsonSerializer.Deserialize(json, JsonSerializerOptions)!; + var deserialized = (JSObjectReference)JsonSerializer.Deserialize(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); diff --git a/src/Shared/JSInterop/JSCallResultTypeHelper.cs b/src/Shared/JSInterop/JSCallResultTypeHelper.cs new file mode 100644 index 0000000000..a03e4308d1 --- /dev/null +++ b/src/Shared/JSInterop/JSCallResultTypeHelper.cs @@ -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() + => typeof(TResult) == typeof(IJSObjectReference) || typeof(TResult) == typeof(IJSInProcessObjectReference) ? + JSCallResultType.JSObjectReference : + JSCallResultType.Default; + } +}