Remove uses of JSRuntime.Current (#7599)

* Remove uses of JSRuntime.Current

Prerequisite for https://github.com/aspnet/AspNetCore/issues/6828
This commit is contained in:
Pranav K 2019-02-15 15:14:00 -08:00 committed by GitHub
parent c98c79d255
commit fe1c2c84ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 82 additions and 70 deletions

View File

@ -8,7 +8,6 @@ using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components.Services;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.JSInterop;
using Mono.WebAssembly.Interop;
namespace Microsoft.AspNetCore.Blazor.Hosting
{
@ -88,7 +87,7 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
var services = new ServiceCollection();
services.AddSingleton(_BrowserHostBuilderContext);
services.AddSingleton<IWebAssemblyHost, WebAssemblyHost>();
services.AddSingleton<IJSRuntime, MonoWebAssemblyJSRuntime>();
services.AddSingleton<IJSRuntime>(WebAssemblyJSRuntime.Instance);
services.AddSingleton<IUriHelper>(WebAssemblyUriHelper.Instance);
services.AddSingleton<HttpClient>(s =>
@ -110,4 +109,4 @@ namespace Microsoft.AspNetCore.Blazor.Hosting
_appServices = _serviceProviderFactory.CreateServiceProvider(builder);
}
}
}
}

View File

@ -1,8 +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 Microsoft.JSInterop;
using Mono.WebAssembly.Interop;
using System;
using System.Collections.Generic;
using System.Linq;
@ -10,6 +8,8 @@ using System.Net;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.JSInterop;
namespace Microsoft.AspNetCore.Blazor.Http
{
@ -25,10 +25,10 @@ namespace Microsoft.AspNetCore.Blazor.Http
public static FetchCredentialsOption DefaultCredentials { get; set; }
= FetchCredentialsOption.SameOrigin;
static object _idLock = new object();
static int _nextRequestId = 0;
static IDictionary<int, TaskCompletionSource<HttpResponseMessage>> _pendingRequests
private static readonly object _idLock = new object();
private static readonly IDictionary<int, TaskCompletionSource<HttpResponseMessage>> _pendingRequests
= new Dictionary<int, TaskCompletionSource<HttpResponseMessage>>();
private static int _nextRequestId = 0;
/// <summary>
/// The name of a well-known property that can be added to <see cref="HttpRequestMessage.Properties"/>
@ -64,29 +64,22 @@ namespace Microsoft.AspNetCore.Blazor.Http
};
options.RequestUri = request.RequestUri.ToString();
if (JSRuntime.Current is MonoWebAssemblyJSRuntime mono)
{
mono.InvokeUnmarshalled<int, byte[], string, object>(
"Blazor._internal.http.sendAsync",
id,
request.Content == null ? null : await request.Content.ReadAsByteArrayAsync(),
Json.Serialize(options));
}
else
{
throw new NotImplementedException("WebAssemblyHttpMessageHandler only supports running under Mono WebAssembly.");
}
WebAssemblyJSRuntime.Instance.InvokeUnmarshalled<int, byte[], string, object>(
"Blazor._internal.http.sendAsync",
id,
request.Content == null ? null : await request.Content.ReadAsByteArrayAsync(),
Json.Serialize(options));
return await tcs.Task;
}
private string[][] GetHeadersAsStringArray(HttpRequestMessage request)
=> (from header in request.Headers.Concat(request.Content?.Headers ?? Enumerable.Empty<KeyValuePair<string, IEnumerable<string>>>())
from headerValue in header.Value // There can be more than one value for each name
select new[] { header.Key, headerValue }).ToArray();
/// <remarks>
/// While it may be tempting to remove this method because it appears to be unused,
/// this method is referenced by client code and must persist.
/// </remarks>
#pragma warning disable IDE0051 // Remove unused private members
private static void ReceiveResponse(
#pragma warning restore IDE0051 // Remove unused private members
string id,
string responseDescriptorJson,
byte[] responseBodyData,
@ -113,10 +106,18 @@ namespace Microsoft.AspNetCore.Blazor.Http
}
}
private static byte[] AllocateArray(string length)
{
return new byte[int.Parse(length)];
}
/// <remarks>
/// While it may be tempting to remove this method because it appears to be unused,
/// this method is referenced by client code and must persist.
/// </remarks>
#pragma warning disable IDE0051 // Remove unused private members
private static byte[] AllocateArray(string length) => new byte[int.Parse(length)];
#pragma warning restore IDE0051 // Remove unused private members
private string[][] GetHeadersAsStringArray(HttpRequestMessage request)
=> (from header in request.Headers.Concat(request.Content?.Headers ?? Enumerable.Empty<KeyValuePair<string, IEnumerable<string>>>())
from headerValue in header.Value // There can be more than one value for each name
select new[] { header.Key, headerValue }).ToArray();
private static string GetDefaultCredentialsString()
{
@ -152,11 +153,11 @@ namespace Microsoft.AspNetCore.Blazor.Http
private class ResponseDescriptor
{
#pragma warning disable 0649
#pragma warning disable 0649
public int StatusCode { get; set; }
public string StatusText { get; set; }
public string[][] Headers { get; set; }
#pragma warning restore 0649
#pragma warning restore 0649
public HttpResponseMessage ToResponseMessage(HttpContent content)
{

View File

@ -3,11 +3,10 @@
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Blazor.Services;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Browser;
using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.JSInterop;
using Mono.WebAssembly.Interop;
namespace Microsoft.AspNetCore.Blazor.Rendering
{
@ -23,7 +22,8 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
/// Constructs an instance of <see cref="WebAssemblyRenderer"/>.
/// </summary>
/// <param name="serviceProvider">The <see cref="IServiceProvider"/> to use when initializing components.</param>
public WebAssemblyRenderer(IServiceProvider serviceProvider) : base(serviceProvider)
public WebAssemblyRenderer(IServiceProvider serviceProvider)
: base(serviceProvider)
{
// The browser renderer registers and unregisters itself with the static
// registry. This works well with the WebAssembly runtime, and is simple for the
@ -66,7 +66,8 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
// (otherwise the logged exception will come from UpdateDisplayAsync instead of here)
// When implementing support for out-of-process runtimes, we'll need to call this
// asynchronously and ensure we surface any exceptions correctly.
((IJSInProcessRuntime)JSRuntime.Current).Invoke<object>(
WebAssemblyJSRuntime.Instance.Invoke<object>(
"Blazor._internal.attachRootComponentToElement",
_webAssemblyRendererId,
domElementSelector,
@ -85,19 +86,12 @@ namespace Microsoft.AspNetCore.Blazor.Rendering
/// <inheritdoc />
protected override Task UpdateDisplayAsync(in RenderBatch batch)
{
if (JSRuntime.Current is MonoWebAssemblyJSRuntime mono)
{
mono.InvokeUnmarshalled<int, RenderBatch, object>(
"Blazor._internal.renderBatch",
_webAssemblyRendererId,
batch);
return Task.CompletedTask;
}
else
{
// This renderer is not used for server-side Blazor.
throw new NotImplementedException($"{nameof(WebAssemblyRenderer)} is supported only with in-process JS runtimes.");
}
WebAssemblyJSRuntime.Instance.InvokeUnmarshalled<int, RenderBatch, object>(
"Blazor._internal.renderBatch",
_webAssemblyRendererId,
batch);
return Task.CompletedTask;
}
/// <inheritdoc />

View File

@ -0,0 +1,12 @@
// 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 Mono.WebAssembly.Interop;
namespace Microsoft.AspNetCore.Blazor.Services
{
internal static class WebAssemblyJSRuntime
{
public static readonly MonoWebAssemblyJSRuntime Instance = new MonoWebAssemblyJSRuntime();
}
}

View File

@ -31,15 +31,15 @@ namespace Microsoft.AspNetCore.Blazor.Services
/// </summary>
protected override void InitializeState()
{
((IJSInProcessRuntime)JSRuntime.Current).Invoke<object>(
WebAssemblyJSRuntime.Instance.Invoke<object>(
Interop.EnableNavigationInterception,
typeof(WebAssemblyUriHelper).Assembly.GetName().Name,
nameof(NotifyLocationChanged));
// As described in the comment block above, BrowserUriHelper is only for
// client-side (Mono) use, so it's OK to rely on synchronicity here.
var baseUri = ((IJSInProcessRuntime)JSRuntime.Current).Invoke<string>(Interop.GetBaseUri);
var uri = ((IJSInProcessRuntime)JSRuntime.Current).Invoke<string>(Interop.GetLocationHref);
var baseUri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetBaseUri);
var uri = WebAssemblyJSRuntime.Instance.Invoke<string>(Interop.GetLocationHref);
SetAbsoluteBaseUri(baseUri);
SetAbsoluteUri(uri);
}
@ -52,7 +52,7 @@ namespace Microsoft.AspNetCore.Blazor.Services
throw new ArgumentNullException(nameof(uri));
}
((IJSInProcessRuntime)JSRuntime.Current).Invoke<object>(Interop.NavigateTo, uri, forceLoad);
WebAssemblyJSRuntime.Instance.Invoke<object>(Interop.NavigateTo, uri, forceLoad);
}
/// <summary>

View File

@ -5,10 +5,10 @@ namespace BlazorLibrary_CSharp
{
public class ExampleJsInterop
{
public static Task<string> Prompt(string message)
public static Task<string> Prompt(IJSRuntime jsRuntime, string message)
{
// Implemented in exampleJsInterop.js
return JSRuntime.Current.InvokeAsync<string>(
return jsRuntime.InvokeAsync<string>(
"exampleJsFunctions.showPrompt",
message);
}

View File

@ -1,4 +1,5 @@
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime
<input ref="myInput" value="Value set during render" />
@ -7,6 +8,6 @@
protected override void OnAfterRender()
{
JSRuntime.Current.InvokeAsync<object>("setElementValue", myInput, "Value set after render");
JSRuntime.InvokeAsync<object>("setElementValue", myInput, "Value set after render");
}
}

View File

@ -1,4 +1,5 @@
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime
<h1>Element capture</h1>
@ -31,6 +32,6 @@
async Task MakeInteropCall()
{
await JSRuntime.Current.InvokeAsync<object>("setElementValue", _myInput, $"Clicks: {++_count}");
await JSRuntime.InvokeAsync<object>("setElementValue", _myInput, $"Clicks: {++_count}");
}
}

View File

@ -1,5 +1,8 @@
@addTagHelper *, TestContentPackage
@using TestContentPackage
@using Microsoft.JSInterop
@inject IJSRuntime JSRuntime
<h1>Functionality and content from an external package</h1>
@ -33,6 +36,6 @@
async Task ShowJavaScriptPrompt()
{
result = await MyPrompt.Show("Hello!");
result = await MyPrompt.Show(JSRuntime, "Hello!");
}
}

View File

@ -1,6 +1,7 @@
@using Microsoft.JSInterop
@using BasicTestApp.InteropTest
@using System.Runtime.InteropServices
@inject IJSRuntime JSRuntime
<button id="btn-interop" onclick="@InvokeInteropAsync">Invoke interop!</button>
@ -71,7 +72,7 @@
var instanceMethodsTarget = new JavaScriptInterop();
Console.WriteLine("Starting interop invocations.");
await JSRuntime.Current.InvokeAsync<object>(
await JSRuntime.InvokeAsync<object>(
"jsInteropTests.invokeDotNetInteropMethodsAsync",
shouldSupportSyncInterop,
new DotNetObjectRef(testDTOTOPassByRef),
@ -83,7 +84,7 @@
}
Console.WriteLine("Showing interop invocation results.");
var collectResults = await JSRuntime.Current.InvokeAsync<Dictionary<string,string>>("jsInteropTests.collectInteropResults");
var collectResults = await JSRuntime.InvokeAsync<Dictionary<string,string>>("jsInteropTests.collectInteropResults");
ReturnValues = collectResults.ToDictionary(kvp => kvp.Key,kvp => System.Text.Encoding.UTF8.GetString(Convert.FromBase64String(kvp.Value)));
@ -96,7 +97,7 @@
try
{
await JSRuntime.Current.InvokeAsync<object>("jsInteropTests.asyncFunctionThrowsSyncException");
await JSRuntime.InvokeAsync<object>("jsInteropTests.asyncFunctionThrowsSyncException");
}
catch (JSException e)
{
@ -105,7 +106,7 @@
try
{
await JSRuntime.Current.InvokeAsync<object>("jsInteropTests.asyncFunctionThrowsAsyncException");
await JSRuntime.InvokeAsync<object>("jsInteropTests.asyncFunctionThrowsAsyncException");
}
catch (JSException e)
{
@ -118,15 +119,15 @@
{ "stringValue", "My string" },
{ "testDto", new DotNetObjectRef(passDotNetObjectByRef) },
};
ReceiveDotNetObjectByRefAsyncResult = await JSRuntime.Current.InvokeAsync<Dictionary<string, object>>("receiveDotNetObjectByRefAsync", passDotNetObjectByRefArg);
ReceiveDotNetObjectByRefAsyncResult = await JSRuntime.InvokeAsync<Dictionary<string, object>>("receiveDotNetObjectByRefAsync", passDotNetObjectByRefArg);
ReceiveDotNetObjectByRefAsyncResult["testDto"] = ReceiveDotNetObjectByRefAsyncResult["testDto"] == passDotNetObjectByRef ? "Same" : "Different";
ReturnValues["returnPrimitiveAsync"] = (await JSRuntime.Current.InvokeAsync<int>("returnPrimitiveAsync")).ToString();
ReturnValues["returnArrayAsync"] = string.Join(",", (await JSRuntime.Current.InvokeAsync<Segment[]>("returnArrayAsync")).Select(x => x.Source).ToArray());
ReturnValues["returnPrimitiveAsync"] = (await JSRuntime.InvokeAsync<int>("returnPrimitiveAsync")).ToString();
ReturnValues["returnArrayAsync"] = string.Join(",", (await JSRuntime.InvokeAsync<Segment[]>("returnArrayAsync")).Select(x => x.Source).ToArray());
if (shouldSupportSyncInterop)
{
ReturnValues["returnPrimitive"] = ((IJSInProcessRuntime)JSRuntime.Current).Invoke<int>("returnPrimitive").ToString();
ReturnValues["returnArray"] = string.Join(",", ((IJSInProcessRuntime)JSRuntime.Current).Invoke<Segment[]>("returnArray").Select(x => x.Source).ToArray());
ReturnValues["returnPrimitive"] = ((IJSInProcessRuntime)JSRuntime).Invoke<int>("returnPrimitive").ToString();
ReturnValues["returnArray"] = string.Join(",", ((IJSInProcessRuntime)JSRuntime).Invoke<Segment[]>("returnArray").Select(x => x.Source).ToArray());
}
Invocations = invocations;
@ -135,7 +136,7 @@
public void InvokeInProcessInterop()
{
var inProcRuntime = ((IJSInProcessRuntime)JSRuntime.Current);
var inProcRuntime = ((IJSInProcessRuntime)JSRuntime);
try
{

View File

@ -5,9 +5,9 @@ namespace TestContentPackage
{
public static class MyPrompt
{
public static Task<string> Show(string message)
public static Task<string> Show(IJSRuntime jsRuntime, string message)
{
return JSRuntime.Current.InvokeAsync<string>(
return jsRuntime.InvokeAsync<string>(
"TestContentPackage.showPrompt", // Keep in sync with identifiers in the.js file
message);
}