From c58ab9247c472aa0cb1cb9d71689d044e338c0ee Mon Sep 17 00:00:00 2001 From: Pranav K Date: Tue, 9 Jun 2020 22:39:01 -0700 Subject: [PATCH] Add nullable to JSInterop (#22326) --- .../ref/Microsoft.JSInterop.csproj | 1 + .../ref/Microsoft.JSInterop.netcoreapp.cs | 20 +++++++------- .../ref/Microsoft.JSInterop.netstandard2.0.cs | 19 +++++++------- .../src/DotNetObjectReferenceOfT.cs | 4 +-- .../src/Infrastructure/DotNetDispatcher.cs | 26 +++++++++---------- .../Infrastructure/DotNetInvocationResult.cs | 10 +++---- ...tNetObjectReferenceJsonConverterFactory.cs | 2 +- .../src/Infrastructure/TaskGenericsUtil.cs | 22 ++++++++-------- .../src/JSInProcessRuntime.cs | 4 ++- .../src/JSInvokableAttribute.cs | 2 +- .../Microsoft.JSInterop/src/JSRuntime.cs | 19 +++++--------- .../src/Microsoft.JSInterop.csproj | 3 ++- .../Infrastructure/DotNetDispatcherTest.cs | 1 + .../DotNetObjectReferenceJsonConverterTest.cs | 6 ++--- .../test/JSInProcessRuntimeTest.cs | 16 ++++++------ .../Microsoft.JSInterop/test/JSRuntimeTest.cs | 16 ++++++------ .../test/Microsoft.JSInterop.Tests.csproj | 1 + .../Microsoft.JSInterop/test/TestJSRuntime.cs | 2 +- 18 files changed, 88 insertions(+), 86 deletions(-) diff --git a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.csproj b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.csproj index 52192f2100..dabf98ff45 100644 --- a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.csproj +++ b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.csproj @@ -3,6 +3,7 @@ netstandard2.0;$(DefaultNetCoreTargetFramework) $(DefaultNetCoreTargetFramework) + annotations diff --git a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netcoreapp.cs b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netcoreapp.cs index 3abe22eea0..23eee87818 100644 --- a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netcoreapp.cs +++ b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netcoreapp.cs @@ -30,7 +30,8 @@ namespace Microsoft.JSInterop public abstract partial class JSInProcessRuntime : Microsoft.JSInterop.JSRuntime, Microsoft.JSInterop.IJSInProcessRuntime, Microsoft.JSInterop.IJSRuntime { protected JSInProcessRuntime() { } - protected abstract string InvokeJS(string identifier, string argsJson); + protected abstract string? InvokeJS(string identifier, string? argsJson); + [return: System.Diagnostics.CodeAnalysis.MaybeNullAttribute] public TValue Invoke(string identifier, params object[] args) { throw null; } } public static partial class JSInProcessRuntimeExtensions @@ -42,15 +43,16 @@ namespace Microsoft.JSInterop { public JSInvokableAttribute() { } public JSInvokableAttribute(string identifier) { } - public string Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public string? Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } public abstract partial class JSRuntime : Microsoft.JSInterop.IJSRuntime { protected JSRuntime() { } protected System.TimeSpan? DefaultAsyncTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected internal System.Text.Json.JsonSerializerOptions JsonSerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - protected abstract void BeginInvokeJS(long taskId, string identifier, string argsJson); + protected abstract void BeginInvokeJS(long taskId, string identifier, string? argsJson); protected internal abstract void EndInvokeDotNet(Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, in Microsoft.JSInterop.Infrastructure.DotNetInvocationResult invocationResult); + [System.Diagnostics.DebuggerStepThroughAttribute] public System.Threading.Tasks.ValueTask InvokeAsync(string identifier, object[] args) { throw null; } public System.Threading.Tasks.ValueTask InvokeAsync(string identifier, System.Threading.CancellationToken cancellationToken, object[] args) { throw null; } } @@ -74,7 +76,7 @@ namespace Microsoft.JSInterop.Infrastructure { public static void BeginInvokeDotNet(Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { } public static void EndInvokeJS(Microsoft.JSInterop.JSRuntime jsRuntime, string arguments) { } - public static string Invoke(Microsoft.JSInterop.JSRuntime jsRuntime, in Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { throw null; } + public static string? Invoke(Microsoft.JSInterop.JSRuntime jsRuntime, in Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct DotNetInvocationInfo @@ -92,11 +94,11 @@ namespace Microsoft.JSInterop.Infrastructure { private readonly object _dummy; private readonly int _dummyPrimitive; - public DotNetInvocationResult(System.Exception exception, string errorKind) { throw null; } - public DotNetInvocationResult(object result) { throw null; } - public string ErrorKind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public System.Exception Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public object Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public DotNetInvocationResult(System.Exception exception, string? errorKind) { throw null; } + public DotNetInvocationResult(object? result) { throw null; } + public string? ErrorKind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public System.Exception? Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public object? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool Success { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } } diff --git a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netstandard2.0.cs b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netstandard2.0.cs index 3abe22eea0..b62ccbb677 100644 --- a/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netstandard2.0.cs +++ b/src/JSInterop/Microsoft.JSInterop/ref/Microsoft.JSInterop.netstandard2.0.cs @@ -30,7 +30,7 @@ namespace Microsoft.JSInterop public abstract partial class JSInProcessRuntime : Microsoft.JSInterop.JSRuntime, Microsoft.JSInterop.IJSInProcessRuntime, Microsoft.JSInterop.IJSRuntime { protected JSInProcessRuntime() { } - protected abstract string InvokeJS(string identifier, string argsJson); + protected abstract string? InvokeJS(string identifier, string? argsJson); public TValue Invoke(string identifier, params object[] args) { throw null; } } public static partial class JSInProcessRuntimeExtensions @@ -42,15 +42,16 @@ namespace Microsoft.JSInterop { public JSInvokableAttribute() { } public JSInvokableAttribute(string identifier) { } - public string Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public string? Identifier { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } public abstract partial class JSRuntime : Microsoft.JSInterop.IJSRuntime { protected JSRuntime() { } protected System.TimeSpan? DefaultAsyncTimeout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute] set { } } protected internal System.Text.Json.JsonSerializerOptions JsonSerializerOptions { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - protected abstract void BeginInvokeJS(long taskId, string identifier, string argsJson); + protected abstract void BeginInvokeJS(long taskId, string identifier, string? argsJson); protected internal abstract void EndInvokeDotNet(Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, in Microsoft.JSInterop.Infrastructure.DotNetInvocationResult invocationResult); + [System.Diagnostics.DebuggerStepThroughAttribute] public System.Threading.Tasks.ValueTask InvokeAsync(string identifier, object[] args) { throw null; } public System.Threading.Tasks.ValueTask InvokeAsync(string identifier, System.Threading.CancellationToken cancellationToken, object[] args) { throw null; } } @@ -74,7 +75,7 @@ namespace Microsoft.JSInterop.Infrastructure { public static void BeginInvokeDotNet(Microsoft.JSInterop.JSRuntime jsRuntime, Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { } public static void EndInvokeJS(Microsoft.JSInterop.JSRuntime jsRuntime, string arguments) { } - public static string Invoke(Microsoft.JSInterop.JSRuntime jsRuntime, in Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { throw null; } + public static string? Invoke(Microsoft.JSInterop.JSRuntime jsRuntime, in Microsoft.JSInterop.Infrastructure.DotNetInvocationInfo invocationInfo, string argsJson) { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct DotNetInvocationInfo @@ -92,11 +93,11 @@ namespace Microsoft.JSInterop.Infrastructure { private readonly object _dummy; private readonly int _dummyPrimitive; - public DotNetInvocationResult(System.Exception exception, string errorKind) { throw null; } - public DotNetInvocationResult(object result) { throw null; } - public string ErrorKind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public System.Exception Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } - public object Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public DotNetInvocationResult(System.Exception exception, string? errorKind) { throw null; } + public DotNetInvocationResult(object? result) { throw null; } + public string? ErrorKind { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public System.Exception? Exception { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } + public object? Result { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } public bool Success { [System.Runtime.CompilerServices.CompilerGeneratedAttribute] get { throw null; } } } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/DotNetObjectReferenceOfT.cs b/src/JSInterop/Microsoft.JSInterop/src/DotNetObjectReferenceOfT.cs index 773c2ed9a3..f72a636111 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/DotNetObjectReferenceOfT.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/DotNetObjectReferenceOfT.cs @@ -18,7 +18,7 @@ namespace Microsoft.JSInterop { private readonly TValue _value; private long _objectId; - private JSRuntime _jsRuntime; + private JSRuntime? _jsRuntime; /// /// Initializes a new instance of . @@ -57,7 +57,7 @@ namespace Microsoft.JSInterop } } - internal JSRuntime JSRuntime + internal JSRuntime? JSRuntime { get { diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs index 8d37905980..30c1910143 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetDispatcher.cs @@ -34,14 +34,14 @@ namespace Microsoft.JSInterop.Infrastructure /// The . /// A JSON representation of the parameters. /// A JSON representation of the return value, or null. - public static string Invoke(JSRuntime jsRuntime, in DotNetInvocationInfo invocationInfo, string argsJson) + public static string? Invoke(JSRuntime jsRuntime, in DotNetInvocationInfo invocationInfo, string argsJson) { // This method doesn't need [JSInvokable] because the platform is responsible for having // some way to dispatch calls here. The logic inside here is the thing that checks whether // the targeted method has [JSInvokable]. It is not itself subject to that restriction, // because there would be nobody to police that. This method *is* the police. - IDotNetObjectReference targetInstance = default; + IDotNetObjectReference? targetInstance = default; if (invocationInfo.DotNetObjectId != default) { targetInstance = jsRuntime.GetObjectReference(invocationInfo.DotNetObjectId); @@ -75,9 +75,9 @@ namespace Microsoft.JSInterop.Infrastructure var callId = invocationInfo.CallId; - object syncResult = null; - ExceptionDispatchInfo syncException = null; - IDotNetObjectReference targetInstance = null; + object? syncResult = null; + ExceptionDispatchInfo? syncException = null; + IDotNetObjectReference? targetInstance = null; try { if (invocationInfo.DotNetObjectId != default) @@ -126,7 +126,7 @@ namespace Microsoft.JSInterop.Infrastructure } } - private static object InvokeSynchronously(JSRuntime jsRuntime, in DotNetInvocationInfo callInfo, IDotNetObjectReference objectReference, string argsJson) + private static object? InvokeSynchronously(JSRuntime jsRuntime, in DotNetInvocationInfo callInfo, IDotNetObjectReference? objectReference, string argsJson) { var assemblyName = callInfo.AssemblyName; var methodIdentifier = callInfo.MethodIdentifier; @@ -168,14 +168,14 @@ namespace Microsoft.JSInterop.Infrastructure if (tie.InnerException != null) { ExceptionDispatchInfo.Capture(tie.InnerException).Throw(); - throw null; // unreached + throw tie.InnerException; // Unreachable } throw; } } - internal static object[] ParseArguments(JSRuntime jsRuntime, string methodIdentifier, string arguments, Type[] parameterTypes) + internal static object?[] ParseArguments(JSRuntime jsRuntime, string methodIdentifier, string arguments, Type[] parameterTypes) { if (parameterTypes.Length == 0) { @@ -189,7 +189,7 @@ namespace Microsoft.JSInterop.Infrastructure throw new JsonException("Invalid JSON"); } - var suppliedArgs = new object[parameterTypes.Length]; + var suppliedArgs = new object?[parameterTypes.Length]; var index = 0; while (index < parameterTypes.Length && reader.Read() && reader.TokenType != JsonTokenType.EndArray) @@ -331,7 +331,7 @@ namespace Microsoft.JSInterop.Infrastructure foreach (var method in invokableMethods) { - var identifier = method.GetCustomAttribute(false).Identifier ?? method.Name; + var identifier = method.GetCustomAttribute(false)!.Identifier ?? method.Name!; var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); if (result.ContainsKey(identifier)) @@ -360,7 +360,7 @@ namespace Microsoft.JSInterop.Infrastructure .Where(method => !method.ContainsGenericParameters && method.IsDefined(typeof(JSInvokableAttribute), inherit: false)); foreach (var method in invokableMethods) { - var identifier = method.GetCustomAttribute(false).Identifier ?? method.Name; + var identifier = method.GetCustomAttribute(false)!.Identifier ?? method.Name; var parameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray(); if (result.ContainsKey(identifier)) @@ -400,7 +400,7 @@ namespace Microsoft.JSInterop.Infrastructure public AssemblyKey(Assembly assembly) { Assembly = assembly; - AssemblyName = assembly.GetName().Name; + AssemblyName = assembly.GetName().Name!; } public AssemblyKey(string assemblyName) @@ -409,7 +409,7 @@ namespace Microsoft.JSInterop.Infrastructure AssemblyName = assemblyName; } - public Assembly Assembly { get; } + public Assembly? Assembly { get; } public string AssemblyName { get; } diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetInvocationResult.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetInvocationResult.cs index d62dd532ee..289ba30e61 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetInvocationResult.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetInvocationResult.cs @@ -12,7 +12,7 @@ namespace Microsoft.JSInterop.Infrastructure /// /// The that caused the failure. /// The error kind. - public DotNetInvocationResult(Exception exception, string errorKind) + public DotNetInvocationResult(Exception exception, string? errorKind) { Result = default; Exception = exception ?? throw new ArgumentNullException(nameof(exception)); @@ -24,7 +24,7 @@ namespace Microsoft.JSInterop.Infrastructure /// Constructor for a successful invocation. /// /// The result. - public DotNetInvocationResult(object result) + public DotNetInvocationResult(object? result) { Result = result; Exception = default; @@ -35,17 +35,17 @@ namespace Microsoft.JSInterop.Infrastructure /// /// Gets the that caused the failure. /// - public Exception Exception { get; } + public Exception? Exception { get; } /// /// Gets the error kind. /// - public string ErrorKind { get; } + public string? ErrorKind { get; } /// /// Gets the result of a successful invocation. /// - public object Result { get; } + public object? Result { get; } /// /// if the invocation succeeded, otherwise . diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs index 288bfdd090..e06601ca0a 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/DotNetObjectReferenceJsonConverterFactory.cs @@ -27,7 +27,7 @@ namespace Microsoft.JSInterop.Infrastructure var instanceType = typeToConvert.GetGenericArguments()[0]; var converterType = typeof(DotNetObjectReferenceJsonConverter<>).MakeGenericType(instanceType); - return (JsonConverter)Activator.CreateInstance(converterType, JSRuntime); + return (JsonConverter)Activator.CreateInstance(converterType, JSRuntime)!; } } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs index 4e14d50783..747bc13631 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/Infrastructure/TaskGenericsUtil.cs @@ -16,7 +16,7 @@ namespace Microsoft.JSInterop.Infrastructure private static ConcurrentDictionary _cachedResultSetters = new ConcurrentDictionary(); - public static void SetTaskCompletionSourceResult(object taskCompletionSource, object result) + public static void SetTaskCompletionSourceResult(object taskCompletionSource, object? result) => CreateResultSetter(taskCompletionSource).SetResult(taskCompletionSource, result); public static void SetTaskCompletionSourceException(object taskCompletionSource, Exception exception) @@ -25,7 +25,7 @@ namespace Microsoft.JSInterop.Infrastructure public static Type GetTaskCompletionSourceResultType(object taskCompletionSource) => CreateResultSetter(taskCompletionSource).ResultType; - public static object GetTaskResult(Task task) + public static object? GetTaskResult(Task task) { var getter = _cachedResultGetters.GetOrAdd(task.GetType(), taskInstanceType => { @@ -33,12 +33,12 @@ namespace Microsoft.JSInterop.Infrastructure return resultType == null ? new VoidTaskResultGetter() : (ITaskResultGetter)Activator.CreateInstance( - typeof(TaskResultGetter<>).MakeGenericType(resultType)); + typeof(TaskResultGetter<>).MakeGenericType(resultType))!; }); return getter.GetResult(task); } - private static Type GetTaskResultType(Type taskType) + private static Type? GetTaskResultType(Type taskType) { // It might be something derived from Task or Task, so we have to scan // up the inheritance hierarchy to find the Task or Task @@ -57,23 +57,23 @@ namespace Microsoft.JSInterop.Infrastructure interface ITcsResultSetter { Type ResultType { get; } - void SetResult(object taskCompletionSource, object result); + void SetResult(object taskCompletionSource, object? result); void SetException(object taskCompletionSource, Exception exception); } private interface ITaskResultGetter { - object GetResult(Task task); + object? GetResult(Task task); } private class TaskResultGetter : ITaskResultGetter { - public object GetResult(Task task) => ((Task)task).Result; + public object? GetResult(Task task) => ((Task)task).Result!; } private class VoidTaskResultGetter : ITaskResultGetter { - public object GetResult(Task task) + public object? GetResult(Task task) { task.Wait(); // Throw if the task failed return null; @@ -84,7 +84,7 @@ namespace Microsoft.JSInterop.Infrastructure { public Type ResultType => typeof(T); - public void SetResult(object tcs, object result) + public void SetResult(object tcs, object? result) { var typedTcs = (TaskCompletionSource)tcs; @@ -93,7 +93,7 @@ namespace Microsoft.JSInterop.Infrastructure ? resultT : (T)Convert.ChangeType(result, typeof(T)); - typedTcs.SetResult(typedResult); + typedTcs.SetResult(typedResult!); } public void SetException(object tcs, Exception exception) @@ -109,7 +109,7 @@ namespace Microsoft.JSInterop.Infrastructure { var resultType = tcsType.GetGenericArguments().Single(); return (ITcsResultSetter)Activator.CreateInstance( - typeof(TcsResultSetter<>).MakeGenericType(resultType)); + typeof(TcsResultSetter<>).MakeGenericType(resultType))!; }); } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs index e84ab1b631..5125cbd701 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInProcessRuntime.cs @@ -1,6 +1,7 @@ // 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.Diagnostics.CodeAnalysis; using System.Text.Json; namespace Microsoft.JSInterop @@ -17,6 +18,7 @@ namespace Microsoft.JSInterop /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function window.someScope.someFunction. /// JSON-serializable arguments. /// An instance of obtained by JSON-deserializing the return value. + [return: MaybeNull] public TValue Invoke(string identifier, params object[] args) { var resultJson = InvokeJS(identifier, JsonSerializer.Serialize(args, JsonSerializerOptions)); @@ -34,6 +36,6 @@ namespace Microsoft.JSInterop /// The identifier for the function to invoke. /// A JSON representation of the arguments. /// A JSON representation of the result. - protected abstract string InvokeJS(string identifier, string argsJson); + protected abstract string? InvokeJS(string identifier, string? argsJson); } } diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSInvokableAttribute.cs b/src/JSInterop/Microsoft.JSInterop/src/JSInvokableAttribute.cs index b710d54b2c..9f062af8b8 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSInvokableAttribute.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSInvokableAttribute.cs @@ -20,7 +20,7 @@ namespace Microsoft.JSInterop /// If not set, the identifier is taken from the name of the method. In this case the /// method name must be unique within the assembly. /// - public string Identifier { get; } + public string? Identifier { get; } /// /// Constructs an instance of without setting diff --git a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs index 8a97ada859..b59e987686 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/src/JSRuntime.cs @@ -62,14 +62,16 @@ namespace Microsoft.JSInterop /// An identifier for the function to invoke. For example, the value "someScope.someFunction" will invoke the function window.someScope.someFunction. /// JSON-serializable arguments. /// An instance of obtained by JSON-deserializing the return value. - public ValueTask InvokeAsync(string identifier, object[] args) + public async ValueTask InvokeAsync(string identifier, object[] args) { if (DefaultAsyncTimeout.HasValue) { - return InvokeWithDefaultCancellation(identifier, args); + using var cts = new CancellationTokenSource(DefaultAsyncTimeout.Value); + // We need to await here due to the using + return await InvokeAsync(identifier, cts.Token, args); } - return InvokeAsync(identifier, CancellationToken.None, args); + return await InvokeAsync(identifier, CancellationToken.None, args); } /// @@ -130,22 +132,13 @@ namespace Microsoft.JSInterop } } - private async ValueTask InvokeWithDefaultCancellation(string identifier, object[] args) - { - using (var cts = new CancellationTokenSource(DefaultAsyncTimeout.Value)) - { - // We need to await here due to the using - return await InvokeAsync(identifier, cts.Token, args); - } - } - /// /// Begins an asynchronous function invocation. /// /// The identifier for the function invocation, or zero if no async callback is required. /// The identifier for the function to invoke. /// A JSON representation of the arguments. - protected abstract void BeginInvokeJS(long taskId, string identifier, string argsJson); + protected abstract void BeginInvokeJS(long taskId, string identifier, string? argsJson); /// /// Completes an async JS interop call from JavaScript to .NET diff --git a/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj b/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj index 2c8e56a9eb..07f461121a 100644 --- a/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj +++ b/src/JSInterop/Microsoft.JSInterop/src/Microsoft.JSInterop.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;$(DefaultNetCoreTargetFramework) @@ -8,6 +8,7 @@ true true true + enable diff --git a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetDispatcherTest.cs b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetDispatcherTest.cs index 1f482b2680..9ffbefe864 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetDispatcherTest.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetDispatcherTest.cs @@ -1,6 +1,7 @@ // 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. +#nullable disable using System; using System.Linq; using System.Text.Json; diff --git a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetObjectReferenceJsonConverterTest.cs b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetObjectReferenceJsonConverterTest.cs index 8d055aea2c..b10c5aab81 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetObjectReferenceJsonConverterTest.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/Infrastructure/DotNetObjectReferenceJsonConverterTest.cs @@ -80,7 +80,7 @@ namespace Microsoft.JSInterop.Infrastructure var json = $"{{\"__dotNetObject\":{objectId}}}"; // Act - var deserialized = JsonSerializer.Deserialize>(json, JsonSerializerOptions); + var deserialized = JsonSerializer.Deserialize>(json, JsonSerializerOptions)!; // Assert Assert.Same(input, deserialized.Value); @@ -100,7 +100,7 @@ namespace Microsoft.JSInterop.Infrastructure var json = $"[{{\"__dotNetObject\":{JSRuntime.TrackObjectReference(ref1)}}},{{\"__dotNetObject\":{JSRuntime.TrackObjectReference(ref2)}}}]"; // Act - var deserialized = JsonSerializer.Deserialize[]>(json, JsonSerializerOptions); + var deserialized = JsonSerializer.Deserialize[]>(json, JsonSerializerOptions)!; // Assert Assert.Same(instance1, deserialized[0].Value); @@ -121,7 +121,7 @@ namespace Microsoft.JSInterop.Infrastructure }}"; // Act - var deserialized = JsonSerializer.Deserialize>(json, JsonSerializerOptions); + var deserialized = JsonSerializer.Deserialize>(json, JsonSerializerOptions)!; // Assert Assert.Same(input, deserialized.Value); diff --git a/src/JSInterop/Microsoft.JSInterop/test/JSInProcessRuntimeTest.cs b/src/JSInterop/Microsoft.JSInterop/test/JSInProcessRuntimeTest.cs index f42e0801a0..7d6f341240 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/JSInProcessRuntimeTest.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/JSInProcessRuntimeTest.cs @@ -21,7 +21,7 @@ namespace Microsoft.JSInterop }; // Act - var syncResult = runtime.Invoke("test identifier 1", "arg1", 123, true); + var syncResult = runtime.Invoke("test identifier 1", "arg1", 123, true)!; var call = runtime.InvokeCalls.Single(); // Assert @@ -80,7 +80,7 @@ namespace Microsoft.JSInterop "test identifier", DotNetObjectReference.Create(obj1), "some other arg", - DotNetObjectReference.Create(obj2)); + DotNetObjectReference.Create(obj2))!; var call = runtime.InvokeCalls.Single(); // Assert @@ -90,16 +90,16 @@ namespace Microsoft.JSInterop class TestDTO { public int IntValue { get; set; } - public string StringValue { get; set; } + public string? StringValue { get; set; } } class TestJSInProcessRuntime : JSInProcessRuntime { public List InvokeCalls { get; set; } = new List(); - public string NextResultJson { get; set; } + public string? NextResultJson { get; set; } - protected override string InvokeJS(string identifier, string argsJson) + protected override string? InvokeJS(string identifier, string? argsJson) { InvokeCalls.Add(new InvokeArgs { Identifier = identifier, ArgsJson = argsJson }); return NextResultJson; @@ -107,11 +107,11 @@ namespace Microsoft.JSInterop public class InvokeArgs { - public string Identifier { get; set; } - public string ArgsJson { get; set; } + public string? Identifier { get; set; } + public string? ArgsJson { get; set; } } - protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson) + protected override void BeginInvokeJS(long asyncHandle, string identifier, string? argsJson) => throw new NotImplementedException("This test only covers sync calls"); protected internal override void EndInvokeDotNet(DotNetInvocationInfo invocationInfo, in DotNetInvocationResult invocationResult) diff --git a/src/JSInterop/Microsoft.JSInterop/test/JSRuntimeTest.cs b/src/JSInterop/Microsoft.JSInterop/test/JSRuntimeTest.cs index 66e0033d2a..7710ba0e8e 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/JSRuntimeTest.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/JSRuntimeTest.cs @@ -322,14 +322,14 @@ namespace Microsoft.JSInterop private class JSError { - public string Message { get; set; } + public string? Message { get; set; } } private class TestPoco { public int Id { get; set; } - public string Name { get; set; } + public string? Name { get; set; } } class TestJSRuntime : JSRuntime @@ -348,18 +348,18 @@ namespace Microsoft.JSInterop public class BeginInvokeAsyncArgs { public long AsyncHandle { get; set; } - public string Identifier { get; set; } - public string ArgsJson { get; set; } + public string? Identifier { get; set; } + public string? ArgsJson { get; set; } } public class EndInvokeDotNetArgs { - public string CallId { get; set; } + public string? CallId { get; set; } public bool Success { get; set; } - public object ResultOrError { get; set; } + public object? ResultOrError { get; set; } } - public Func OnDotNetException { get; set; } + public Func? OnDotNetException { get; set; } protected internal override void EndInvokeDotNet(DotNetInvocationInfo invocationInfo, in DotNetInvocationResult invocationResult) { @@ -377,7 +377,7 @@ namespace Microsoft.JSInterop }); } - protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson) + protected override void BeginInvokeJS(long asyncHandle, string identifier, string? argsJson) { BeginInvokeCalls.Add(new BeginInvokeAsyncArgs { diff --git a/src/JSInterop/Microsoft.JSInterop/test/Microsoft.JSInterop.Tests.csproj b/src/JSInterop/Microsoft.JSInterop/test/Microsoft.JSInterop.Tests.csproj index ba3a91a94e..41e378682e 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/Microsoft.JSInterop.Tests.csproj +++ b/src/JSInterop/Microsoft.JSInterop/test/Microsoft.JSInterop.Tests.csproj @@ -2,6 +2,7 @@ $(DefaultNetCoreTargetFramework);net472 + enable diff --git a/src/JSInterop/Microsoft.JSInterop/test/TestJSRuntime.cs b/src/JSInterop/Microsoft.JSInterop/test/TestJSRuntime.cs index db9c5ddd36..d2e9cc3ba6 100644 --- a/src/JSInterop/Microsoft.JSInterop/test/TestJSRuntime.cs +++ b/src/JSInterop/Microsoft.JSInterop/test/TestJSRuntime.cs @@ -8,7 +8,7 @@ namespace Microsoft.JSInterop { internal class TestJSRuntime : JSRuntime { - protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson) + protected override void BeginInvokeJS(long asyncHandle, string identifier, string? argsJson) { throw new NotImplementedException(); }