From c281032f35cab04c4ca9e3b5488ea87a11194d55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Rozto=C4=8Dil?= Date: Fri, 9 May 2025 12:55:51 +0200 Subject: [PATCH 1/2] Add default implementations for new interface methods in Blazor JS interop --- .../Internal/IInternalWebJSInProcessRuntime.cs | 3 ++- .../src/IJSInProcessObjectReference.cs | 9 ++++++--- .../src/IJSInProcessRuntime.cs | 9 ++++++--- .../src/IJSObjectReference.cs | 18 ++++++++++++------ .../Microsoft.JSInterop/src/IJSRuntime.cs | 18 ++++++++++++------ .../src/JSInProcessRuntime.cs | 9 ++++++--- .../Microsoft.JSInterop/src/JSRuntime.cs | 8 ++++++-- .../src/PublicAPI.Unshipped.txt | 4 ++-- 8 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/Components/Web/src/Internal/IInternalWebJSInProcessRuntime.cs b/src/Components/Web/src/Internal/IInternalWebJSInProcessRuntime.cs index 86d91a3fb2dd..a68fb052932a 100644 --- a/src/Components/Web/src/Internal/IInternalWebJSInProcessRuntime.cs +++ b/src/Components/Web/src/Internal/IInternalWebJSInProcessRuntime.cs @@ -22,5 +22,6 @@ public interface IInternalWebJSInProcessRuntime /// /// For internal framework use only. /// - string InvokeJS(in JSInvocationInfo invocationInfo); + string InvokeJS(in JSInvocationInfo invocationInfo) + => throw new NotImplementedException(); } diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs index 39f376a11953..d9813f0ddcd0 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessObjectReference.cs @@ -28,7 +28,8 @@ public interface IJSInProcessObjectReference : IJSObjectReference, IDisposable /// JSON-serializable arguments. /// An instance that represents the created JS object. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - IJSInProcessObjectReference InvokeNew(string identifier, object?[]? args); + IJSInProcessObjectReference InvokeNew(string identifier, object?[]? args) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property synchronously. @@ -37,7 +38,8 @@ public interface IJSInProcessObjectReference : IJSObjectReference, IDisposable /// An identifier for the property to read. For example, the value "someScope.someProp" will read the value of the property window.someScope.someProp. /// An instance of obtained by JSON-deserializing the return value. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - TValue GetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier); + TValue GetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property synchronously. If the property is not defined on the target object, it will be created. @@ -46,5 +48,6 @@ public interface IJSInProcessObjectReference : IJSObjectReference, IDisposable /// An identifier for the property to set. For example, the value "someScope.someProp" will update the property window.someScope.someProp. /// JSON-serializable value. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - void SetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value); + void SetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value) + => throw new NotImplementedException(); } diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessRuntime.cs index ed1ea479c8d1..cf3954ce0269 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSInProcessRuntime.cs @@ -28,7 +28,8 @@ public interface IJSInProcessRuntime : IJSRuntime /// JSON-serializable arguments. /// An instance that represents the created JS object. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - IJSInProcessObjectReference InvokeNew(string identifier, params object?[]? args); + IJSInProcessObjectReference InvokeNew(string identifier, params object?[]? args) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property synchronously. @@ -37,7 +38,8 @@ public interface IJSInProcessRuntime : IJSRuntime /// An identifier for the property to read. For example, the value "someScope.someProp" will read the value of the property window.someScope.someProp. /// An instance of obtained by JSON-deserializing the return value. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - TValue GetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier); + TValue GetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property synchronously. If the property is not defined on the target object, it will be created. @@ -46,5 +48,6 @@ public interface IJSInProcessRuntime : IJSRuntime /// An identifier for the property to set. For example, the value "someScope.someProp" will update the property window.someScope.someProp. /// JSON-serializable value. [RequiresUnreferencedCode("JSON serialization and deserialization might require types that cannot be statically analyzed.")] - void SetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value); + void SetValue<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value) + => throw new NotImplementedException(); } diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs index 30df4c46d232..cb8cc03329d1 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSObjectReference.cs @@ -43,7 +43,8 @@ public interface IJSObjectReference : IAsyncDisposable /// An identifier for the constructor function to invoke. For example, the value "someScope.SomeClass" will invoke the constructor someScope.SomeClass on the target instance. /// JSON-serializable arguments. /// An instance that represents the created JS object. - ValueTask InvokeNewAsync(string identifier, object?[]? args); + ValueTask InvokeNewAsync(string identifier, object?[]? args) + => throw new NotImplementedException(); /// /// Invokes the specified JavaScript constructor function asynchronously. The function is invoked with the new operator. @@ -55,7 +56,8 @@ public interface IJSObjectReference : IAsyncDisposable /// /// JSON-serializable arguments. /// An instance that represents the created JS object. - ValueTask InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args); + ValueTask InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property asynchronously. @@ -63,7 +65,8 @@ public interface IJSObjectReference : IAsyncDisposable /// The JSON-serializable return type. /// An identifier for the property to read. For example, the value "someScope.someProp" will read the value of the property someScope.someProp on the target instance. /// An instance of obtained by JSON-deserializing the return value. - ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier); + ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property asynchronously. @@ -75,7 +78,8 @@ public interface IJSObjectReference : IAsyncDisposable /// () from being applied. /// /// An instance of obtained by JSON-deserializing the return value. - ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken); + ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property asynchronously. If the property is not defined on the target object, it will be created. @@ -84,7 +88,8 @@ public interface IJSObjectReference : IAsyncDisposable /// An identifier for the property to set. For example, the value "someScope.someProp" will update the property someScope.someProp on the target instance. /// JSON-serializable value. /// A that represents the asynchronous invocation operation. - ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value); + ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property asynchronously. If the property is not defined on the target object, it will be created. @@ -97,5 +102,6 @@ public interface IJSObjectReference : IAsyncDisposable /// () from being applied. /// /// A that represents the asynchronous invocation operation. - ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken); + ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken) + => throw new NotImplementedException(); } diff --git a/src/JSInterop/Microsoft.JSInterop/src/IJSRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/IJSRuntime.cs index 0050c357c49c..b897245c0da0 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/IJSRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/IJSRuntime.cs @@ -43,7 +43,8 @@ public interface IJSRuntime /// An identifier for the constructor function to invoke. For example, the value "someScope.SomeClass" will invoke the constructor window.someScope.SomeClass. /// JSON-serializable arguments. /// An instance that represents the created JS object. - ValueTask InvokeNewAsync(string identifier, object?[]? args); + ValueTask InvokeNewAsync(string identifier, object?[]? args) + => throw new NotImplementedException(); /// /// Invokes the specified JavaScript constructor function asynchronously. The function is invoked with the new operator. @@ -55,7 +56,8 @@ public interface IJSRuntime /// /// JSON-serializable arguments. /// An instance that represents the created JS object. - ValueTask InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args); + ValueTask InvokeNewAsync(string identifier, CancellationToken cancellationToken, object?[]? args) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property asynchronously. @@ -63,7 +65,8 @@ public interface IJSRuntime /// The JSON-serializable return type. /// An identifier for the property to read. For example, the value "someScope.someProp" will read the value of the property window.someScope.someProp. /// An instance of obtained by JSON-deserializing the return value. - ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier); + ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier) + => throw new NotImplementedException(); /// /// Reads the value of the specified JavaScript property asynchronously. @@ -75,7 +78,8 @@ public interface IJSRuntime /// () from being applied. /// /// An instance of obtained by JSON-deserializing the return value. - ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken); + ValueTask GetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, CancellationToken cancellationToken) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property asynchronously. If the property is not defined on the target object, it will be created. @@ -84,7 +88,8 @@ public interface IJSRuntime /// An identifier for the property to set. For example, the value "someScope.someProp" will update the property window.someScope.someProp. /// JSON-serializable value. /// A that represents the asynchronous invocation operation. - ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value); + ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value) + => throw new NotImplementedException(); /// /// Updates the value of the specified JavaScript property asynchronously. If the property is not defined on the target object, it will be created. @@ -97,5 +102,6 @@ public interface IJSRuntime /// () from being applied. /// /// A that represents the asynchronous invocation operation. - ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken); + ValueTask SetValueAsync<[DynamicallyAccessedMembers(JsonSerialized)] TValue>(string identifier, TValue value, CancellationToken cancellationToken) + => throw new NotImplementedException(); } diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs index 5c8a73b29cd4..990d75c17411 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs @@ -81,8 +81,8 @@ public IJSInProcessObjectReference InvokeNew(string identifier, params object?[] => InvokeJS(identifier, argsJson, JSCallResultType.Default, WindowObjectId); /// - /// Performs a synchronous function invocation. - /// + /// Performs a synchronous function invocation with the call type . + /// For more configuration options, use the overload . /// The identifier for the function to invoke. /// A JSON representation of the arguments. /// The type of result expected from the invocation. @@ -95,5 +95,8 @@ public IJSInProcessObjectReference InvokeNew(string identifier, params object?[] /// /// Configuration of the interop call. /// A JSON representation of the result. - protected abstract string? InvokeJS(in JSInvocationInfo invocationInfo); + protected virtual string? InvokeJS(in JSInvocationInfo invocationInfo) + { + return InvokeJS(invocationInfo.Identifier, invocationInfo.ArgsJson, invocationInfo.ResultType, invocationInfo.TargetInstanceId); + } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs index a970c7900970..f91746f99f50 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs @@ -192,7 +192,8 @@ protected virtual void BeginInvokeJS(long taskId, string identifier, [StringSynt => BeginInvokeJS(taskId, identifier, argsJson, JSCallResultType.Default, WindowObjectId); /// - /// Begins an asynchronous function invocation. + /// Begins an asynchronous function invocation with the call type . + /// For more configuration options, use the overload . /// /// The identifier for the function invocation, or zero if no async callback is required. /// The identifier for the function to invoke. @@ -205,7 +206,10 @@ protected virtual void BeginInvokeJS(long taskId, string identifier, [StringSynt /// Begins an asynchronous function invocation. /// /// Configuration of the interop call from .NET to JavaScript. - protected abstract void BeginInvokeJS(in JSInvocationInfo invocationInfo); + protected virtual void BeginInvokeJS(in JSInvocationInfo invocationInfo) + { + BeginInvokeJS(invocationInfo.AsyncHandle, invocationInfo.Identifier, invocationInfo.ArgsJson, invocationInfo.ResultType, invocationInfo.TargetInstanceId); + } /// /// Completes an async JS interop call from JavaScript to .NET diff --git a/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt b/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt index 3270d74b01a0..b6c32d826997 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt +++ b/src/JSInterop/Microsoft.JSInterop/src/PublicAPI.Unshipped.txt @@ -1,6 +1,4 @@ #nullable enable -abstract Microsoft.JSInterop.JSInProcessRuntime.InvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> string? -abstract Microsoft.JSInterop.JSRuntime.BeginInvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> void Microsoft.JSInterop.IJSInProcessObjectReference.GetValue(string! identifier) -> TValue Microsoft.JSInterop.IJSInProcessObjectReference.InvokeNew(string! identifier, object?[]? args) -> Microsoft.JSInterop.IJSInProcessObjectReference! Microsoft.JSInterop.IJSInProcessObjectReference.SetValue(string! identifier, TValue value) -> void @@ -62,3 +60,5 @@ static Microsoft.JSInterop.JSObjectReferenceExtensions.InvokeNewAsync(this Micro static Microsoft.JSInterop.JSRuntimeExtensions.InvokeNewAsync(this Microsoft.JSInterop.IJSRuntime! jsRuntime, string! identifier, params object?[]? args) -> System.Threading.Tasks.ValueTask static Microsoft.JSInterop.JSRuntimeExtensions.InvokeNewAsync(this Microsoft.JSInterop.IJSRuntime! jsRuntime, string! identifier, System.Threading.CancellationToken cancellationToken, object?[]? args) -> System.Threading.Tasks.ValueTask static Microsoft.JSInterop.JSRuntimeExtensions.InvokeNewAsync(this Microsoft.JSInterop.IJSRuntime! jsRuntime, string! identifier, System.TimeSpan timeout, object?[]? args) -> System.Threading.Tasks.ValueTask +virtual Microsoft.JSInterop.JSInProcessRuntime.InvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> string? +virtual Microsoft.JSInterop.JSRuntime.BeginInvokeJS(in Microsoft.JSInterop.Infrastructure.JSInvocationInfo invocationInfo) -> void From dc11beb0447c6520b5437c077029309476f5a10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Rozto=C4=8Dil?= Date: Fri, 9 May 2025 13:12:49 +0200 Subject: [PATCH 2/2] Fix comment formatting --- src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs index 990d75c17411..2bcc5fa729b9 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs @@ -83,6 +83,7 @@ public IJSInProcessObjectReference InvokeNew(string identifier, params object?[] /// /// Performs a synchronous function invocation with the call type . /// For more configuration options, use the overload . + /// /// The identifier for the function to invoke. /// A JSON representation of the arguments. /// The type of result expected from the invocation.