From 0dd4b3be86432097d3cb4bfebe35d880a06c6559 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Fri, 4 Sep 2020 11:41:14 -0700 Subject: [PATCH 1/3] Update JSCallResultTypeHelper.cs and PublicAPI.Unshipped.txt --- .../src/PublicAPI.Unshipped.txt | 16 ++++++++++ .../JSInterop/JSCallResultTypeHelper.cs | 32 ++++++++++++++++--- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt b/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt index cbb05786f46b..8baa99e23137 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt +++ b/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt @@ -13,11 +13,27 @@ Microsoft.JSInterop.IJSObjectReference.InvokeAsync(string! identifier, o Microsoft.JSInterop.IJSRuntime Microsoft.JSInterop.IJSRuntime.InvokeAsync(string! identifier, System.Threading.CancellationToken cancellationToken, object?[]? args) -> System.Threading.Tasks.ValueTask Microsoft.JSInterop.IJSRuntime.InvokeAsync(string! identifier, object?[]? args) -> System.Threading.Tasks.ValueTask +Microsoft.JSInterop.IJSUnmarshalledObjectReference +Microsoft.JSInterop.IJSUnmarshalledObjectReference.InvokeUnmarshalled(string! identifier, T0 arg0, T1 arg1, T2 arg2) -> TResult +Microsoft.JSInterop.IJSUnmarshalledObjectReference.InvokeUnmarshalled(string! identifier, T0 arg0, T1 arg1) -> TResult +Microsoft.JSInterop.IJSUnmarshalledObjectReference.InvokeUnmarshalled(string! identifier, T0 arg0) -> TResult +Microsoft.JSInterop.IJSUnmarshalledObjectReference.InvokeUnmarshalled(string! identifier) -> TResult Microsoft.JSInterop.IJSUnmarshalledRuntime Microsoft.JSInterop.IJSUnmarshalledRuntime.InvokeUnmarshalled(string! identifier, T0 arg0, T1 arg1, T2 arg2) -> TResult Microsoft.JSInterop.IJSUnmarshalledRuntime.InvokeUnmarshalled(string! identifier, T0 arg0, T1 arg1) -> TResult Microsoft.JSInterop.IJSUnmarshalledRuntime.InvokeUnmarshalled(string! identifier, T0 arg0) -> TResult Microsoft.JSInterop.IJSUnmarshalledRuntime.InvokeUnmarshalled(string! identifier) -> TResult +Microsoft.JSInterop.Implementation.JSInProcessObjectReference +Microsoft.JSInterop.Implementation.JSInProcessObjectReference.Dispose() -> void +Microsoft.JSInterop.Implementation.JSInProcessObjectReference.Invoke(string! identifier, params object?[]? args) -> TValue +Microsoft.JSInterop.Implementation.JSInProcessObjectReference.JSInProcessObjectReference(Microsoft.JSInterop.JSInProcessRuntime! jsRuntime, long id) -> void +Microsoft.JSInterop.Implementation.JSObjectReference +Microsoft.JSInterop.Implementation.JSObjectReference.DisposeAsync() -> System.Threading.Tasks.ValueTask +Microsoft.JSInterop.Implementation.JSObjectReference.Id.get -> long +Microsoft.JSInterop.Implementation.JSObjectReference.InvokeAsync(string! identifier, System.Threading.CancellationToken cancellationToken, object?[]? args) -> System.Threading.Tasks.ValueTask +Microsoft.JSInterop.Implementation.JSObjectReference.InvokeAsync(string! identifier, object?[]? args) -> System.Threading.Tasks.ValueTask +Microsoft.JSInterop.Implementation.JSObjectReference.JSObjectReference(Microsoft.JSInterop.JSRuntime! jsRuntime, long id) -> void +Microsoft.JSInterop.Implementation.JSObjectReference.ThrowIfDisposed() -> void Microsoft.JSInterop.Infrastructure.DotNetDispatcher Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo.AssemblyName.get -> string? diff --git a/src/Shared/JSInterop/JSCallResultTypeHelper.cs b/src/Shared/JSInterop/JSCallResultTypeHelper.cs index 82c3920c7210..b62b9700c45f 100644 --- a/src/Shared/JSInterop/JSCallResultTypeHelper.cs +++ b/src/Shared/JSInterop/JSCallResultTypeHelper.cs @@ -1,15 +1,37 @@ // 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.Reflection; + namespace Microsoft.JSInterop { internal static class JSCallResultTypeHelper { + // We avoid using Assembly.GetExecutingAssembly() because this is shared code. + private static readonly Assembly _currentAssembly = typeof(JSCallResultType).Assembly; + public static JSCallResultType FromGeneric() - => typeof(TResult) == typeof(IJSObjectReference) - || typeof(TResult) == typeof(IJSInProcessObjectReference) - || typeof(TResult) == typeof(IJSUnmarshalledObjectReference) ? - JSCallResultType.JSObjectReference : - JSCallResultType.Default; + { + var resultType = typeof(TResult); + + if (resultType.Assembly == _currentAssembly) + { + if (resultType == typeof(IJSObjectReference) + || resultType == typeof(IJSInProcessObjectReference) + || resultType == typeof(IJSUnmarshalledObjectReference)) + { + return JSCallResultType.JSObjectReference; + } + else + { + throw new ArgumentException($"JS interop cannot supply an instance of type '{resultType}'."); + } + } + else + { + return JSCallResultType.Default; + } + } } } From d986e73c021eb3435b7871668fe6a0f54d81dc44 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Fri, 4 Sep 2020 13:21:46 -0700 Subject: [PATCH 2/3] CR feedback. --- src/Components/test/E2ETest/Tests/InteropTest.cs | 1 + .../testassets/BasicTestApp/InteropComponent.razor | 12 ++++++++++++ src/Shared/JSInterop/JSCallResultTypeHelper.cs | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Components/test/E2ETest/Tests/InteropTest.cs b/src/Components/test/E2ETest/Tests/InteropTest.cs index ef763452a949..e9368d7a732d 100644 --- a/src/Components/test/E2ETest/Tests/InteropTest.cs +++ b/src/Components/test/E2ETest/Tests/InteropTest.cs @@ -62,6 +62,7 @@ public void CanInvokeDotNetMethods() ["SyncExceptionFromAsyncMethod"] = "Function threw a sync exception!", ["AsyncExceptionFromAsyncMethod"] = "Function threw an async exception!", ["JSObjectReferenceInvokeNonFunctionException"] = "The value 'nonFunction' is not a function.", + ["JSObjectReferenceInvalidTypeArgumentException"] = "JS interop cannot supply an instance of type", ["resultReturnDotNetObjectByRefAsync"] = "1001", ["instanceMethodThisTypeNameAsync"] = @"""JavaScriptInterop""", ["instanceMethodStringValueUpperAsync"] = @"""MY STRING""", diff --git a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor index 788a8bda2067..1d2ba6378a5b 100644 --- a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor @@ -48,6 +48,8 @@

@AsyncExceptionFromAsyncMethod?.Message

@nameof(JSObjectReferenceInvokeNonFunctionException)

@JSObjectReferenceInvokeNonFunctionException?.Message

+

@nameof(JSObjectReferenceInvalidTypeArgumentException)

+

@JSObjectReferenceInvalidTypeArgumentException?.Message

@if (DoneWithInterop) { @@ -62,6 +64,7 @@ public JSException SyncExceptionFromAsyncMethod { get; set; } public JSException AsyncExceptionFromAsyncMethod { get; set; } public JSException JSObjectReferenceInvokeNonFunctionException { get; set; } + public ArgumentException JSObjectReferenceInvalidTypeArgumentException { get; set; } public IDictionary ReceiveDotNetObjectByRefResult { get; set; } = new Dictionary(); public IDictionary ReceiveDotNetObjectByRefAsyncResult { get; set; } = new Dictionary(); @@ -154,6 +157,15 @@ var module = await JSRuntime.InvokeAsync("import", "./js/testmodule.js"); ReturnValues["jsObjectReferenceModule"] = await module.InvokeAsync("identity", "Returned from module!"); + try + { + await JSRuntime.InvokeAsync("returnJSObjectReference"); + } + catch (ArgumentException e) + { + JSObjectReferenceInvalidTypeArgumentException = e; + } + if (shouldSupportSyncInterop) { InvokeInProcessJSInterop(); diff --git a/src/Shared/JSInterop/JSCallResultTypeHelper.cs b/src/Shared/JSInterop/JSCallResultTypeHelper.cs index b62b9700c45f..b552297008ea 100644 --- a/src/Shared/JSInterop/JSCallResultTypeHelper.cs +++ b/src/Shared/JSInterop/JSCallResultTypeHelper.cs @@ -25,7 +25,9 @@ public static JSCallResultType FromGeneric() } else { - throw new ArgumentException($"JS interop cannot supply an instance of type '{resultType}'."); + throw new ArgumentException( + $"JS interop cannot supply an instance of type '{resultType}'. Consider using " + + $"'{typeof(IJSObjectReference)}' instead."); } } else From 8eb03251679e6fbfe230355663896f66bd887ef6 Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Wed, 9 Sep 2020 09:49:08 -0700 Subject: [PATCH 3/3] Removed exception message --- .../test/E2ETest/Tests/InteropTest.cs | 1 - .../BasicTestApp/InteropComponent.razor | 12 ----------- .../JSInterop/JSCallResultTypeHelper.cs | 21 +++++-------------- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/src/Components/test/E2ETest/Tests/InteropTest.cs b/src/Components/test/E2ETest/Tests/InteropTest.cs index e9368d7a732d..ef763452a949 100644 --- a/src/Components/test/E2ETest/Tests/InteropTest.cs +++ b/src/Components/test/E2ETest/Tests/InteropTest.cs @@ -62,7 +62,6 @@ public void CanInvokeDotNetMethods() ["SyncExceptionFromAsyncMethod"] = "Function threw a sync exception!", ["AsyncExceptionFromAsyncMethod"] = "Function threw an async exception!", ["JSObjectReferenceInvokeNonFunctionException"] = "The value 'nonFunction' is not a function.", - ["JSObjectReferenceInvalidTypeArgumentException"] = "JS interop cannot supply an instance of type", ["resultReturnDotNetObjectByRefAsync"] = "1001", ["instanceMethodThisTypeNameAsync"] = @"""JavaScriptInterop""", ["instanceMethodStringValueUpperAsync"] = @"""MY STRING""", diff --git a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor index 1d2ba6378a5b..788a8bda2067 100644 --- a/src/Components/test/testassets/BasicTestApp/InteropComponent.razor +++ b/src/Components/test/testassets/BasicTestApp/InteropComponent.razor @@ -48,8 +48,6 @@

@AsyncExceptionFromAsyncMethod?.Message

@nameof(JSObjectReferenceInvokeNonFunctionException)

@JSObjectReferenceInvokeNonFunctionException?.Message

-

@nameof(JSObjectReferenceInvalidTypeArgumentException)

-

@JSObjectReferenceInvalidTypeArgumentException?.Message

@if (DoneWithInterop) { @@ -64,7 +62,6 @@ public JSException SyncExceptionFromAsyncMethod { get; set; } public JSException AsyncExceptionFromAsyncMethod { get; set; } public JSException JSObjectReferenceInvokeNonFunctionException { get; set; } - public ArgumentException JSObjectReferenceInvalidTypeArgumentException { get; set; } public IDictionary ReceiveDotNetObjectByRefResult { get; set; } = new Dictionary(); public IDictionary ReceiveDotNetObjectByRefAsyncResult { get; set; } = new Dictionary(); @@ -157,15 +154,6 @@ var module = await JSRuntime.InvokeAsync("import", "./js/testmodule.js"); ReturnValues["jsObjectReferenceModule"] = await module.InvokeAsync("identity", "Returned from module!"); - try - { - await JSRuntime.InvokeAsync("returnJSObjectReference"); - } - catch (ArgumentException e) - { - JSObjectReferenceInvalidTypeArgumentException = e; - } - if (shouldSupportSyncInterop) { InvokeInProcessJSInterop(); diff --git a/src/Shared/JSInterop/JSCallResultTypeHelper.cs b/src/Shared/JSInterop/JSCallResultTypeHelper.cs index b552297008ea..8bf1a547fc1b 100644 --- a/src/Shared/JSInterop/JSCallResultTypeHelper.cs +++ b/src/Shared/JSInterop/JSCallResultTypeHelper.cs @@ -1,7 +1,6 @@ // 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.Reflection; namespace Microsoft.JSInterop @@ -13,22 +12,12 @@ internal static class JSCallResultTypeHelper public static JSCallResultType FromGeneric() { - var resultType = typeof(TResult); - - if (resultType.Assembly == _currentAssembly) + if (typeof(TResult).Assembly == _currentAssembly + && (typeof(TResult) == typeof(IJSObjectReference) + || typeof(TResult) == typeof(IJSInProcessObjectReference) + || typeof(TResult) == typeof(IJSUnmarshalledObjectReference))) { - if (resultType == typeof(IJSObjectReference) - || resultType == typeof(IJSInProcessObjectReference) - || resultType == typeof(IJSUnmarshalledObjectReference)) - { - return JSCallResultType.JSObjectReference; - } - else - { - throw new ArgumentException( - $"JS interop cannot supply an instance of type '{resultType}'. Consider using " + - $"'{typeof(IJSObjectReference)}' instead."); - } + return JSCallResultType.JSObjectReference; } else {