Просмотр исходного кода

Move Mono.WebAssembly.Interop to blazor-wasm branch

Pranav K 6 лет назад
Родитель
Сommit
3c06726d77

+ 1 - 0
eng/ProjectReferences.props

@@ -15,6 +15,7 @@
     <ProjectReferenceProvider Include="GetDocument.Insider" ProjectPath="$(RepoRoot)src\Tools\GetDocumentInsider\src\GetDocumentInsider.csproj"  />
     <ProjectReferenceProvider Include="Microsoft.AspNetCore.SignalR.Specification.Tests" ProjectPath="$(RepoRoot)src\SignalR\server\Specification.Tests\src\Microsoft.AspNetCore.SignalR.Specification.Tests.csproj"  />
     <ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.Build" ProjectPath="$(RepoRoot)src\Components\Blazor\Build\src\Microsoft.AspNetCore.Blazor.Build.csproj"  />
+    <ProjectReferenceProvider Include="Mono.WebAssembly.Interop" ProjectPath="$(RepoRoot)src\Components\Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj"  />
     <ProjectReferenceProvider Include="Microsoft.AspNetCore.Blazor.DataAnnotations.Validation" ProjectPath="$(RepoRoot)src\Components\Blazor\Validation\src\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj"  />
     <ProjectReferenceProvider Include="Ignitor" ProjectPath="$(RepoRoot)src\Components\Ignitor\src\Ignitor.csproj"  />
     <ProjectReferenceProvider Include="BlazorServerApp" ProjectPath="$(RepoRoot)src\Components\Samples\BlazorServerApp\BlazorServerApp.csproj"  />

+ 0 - 4
eng/Version.Details.xml

@@ -289,10 +289,6 @@
       <Uri>https://github.com/aspnet/Extensions</Uri>
       <Sha>4ebd75b961136c7ca331866eed3403becda75681</Sha>
     </Dependency>
-    <Dependency Name="Mono.WebAssembly.Interop" Version="3.1.0-preview4.19568.3" CoherentParentDependency="Microsoft.EntityFrameworkCore">
-      <Uri>https://github.com/aspnet/Extensions</Uri>
-      <Sha>4ebd75b961136c7ca331866eed3403becda75681</Sha>
-    </Dependency>
     <Dependency Name="Microsoft.Bcl.AsyncInterfaces" Version="1.1.0" CoherentParentDependency="Microsoft.NETCore.App.Runtime.win-x64">
       <Uri>https://github.com/dotnet/corefx</Uri>
       <Sha>0f7f38c4fd323b26da10cce95f857f77f0f09b48</Sha>

+ 0 - 1
eng/Versions.props

@@ -158,7 +158,6 @@
     <MicrosoftExtensionsWebEncodersPackageVersion>3.1.0</MicrosoftExtensionsWebEncodersPackageVersion>
     <MicrosoftInternalExtensionsRefsPackageVersion>3.1.0-rtm.19568.3</MicrosoftInternalExtensionsRefsPackageVersion>
     <MicrosoftJSInteropPackageVersion>3.1.0</MicrosoftJSInteropPackageVersion>
-    <MonoWebAssemblyInteropPackageVersion>3.1.0-preview4.19568.3</MonoWebAssemblyInteropPackageVersion>
     <!-- Packages from aspnet/EntityFrameworkCore -->
     <dotnetefPackageVersion>3.1.0</dotnetefPackageVersion>
     <MicrosoftEntityFrameworkCoreInMemoryPackageVersion>3.1.0</MicrosoftEntityFrameworkCoreInMemoryPackageVersion>

+ 1 - 1
src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netstandard2.1</TargetFramework>
+    <TargetFramework>netstandard2.0</TargetFramework>
     <Description>Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly.</Description>
     <IsShippingPackage>true</IsShippingPackage>
   </PropertyGroup>

+ 25 - 0
src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs

@@ -0,0 +1,25 @@
+// 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.Runtime.CompilerServices;
+
+namespace WebAssembly.JSInterop
+{
+    /// <summary>
+    /// Methods that map to the functions compiled into the Mono WebAssembly runtime,
+    /// as defined by 'mono_add_internal_call' calls in driver.c
+    /// </summary>
+    internal class InternalCalls
+    {
+        // The exact namespace, type, and method names must match the corresponding entries
+        // in driver.c in the Mono distribution
+
+        // We're passing asyncHandle by ref not because we want it to be writable, but so it gets
+        // passed as a pointer (4 bytes). We can pass 4-byte values, but not 8-byte ones.
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        public static extern string InvokeJSMarshalled(out string exception, ref long asyncHandle, string functionIdentifier, string argsJson);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        public static extern TRes InvokeJSUnmarshalled<T0, T1, T2, TRes>(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2);
+    }
+}

+ 17 - 0
src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj

@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>netstandard2.1</TargetFramework>
+    <Description>Abstractions and features for interop between Mono WebAssembly and JavaScript code.</Description>
+    <PackageTags>wasm;javascript;interop</PackageTags>
+    <GenerateDocumentationFile>true</GenerateDocumentationFile>
+    <IsPackable>true</IsPackable>
+    <IsShipping>true</IsShipping>
+    <HasReferenceAssembly>false</HasReferenceAssembly>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <Reference Include="Microsoft.JSInterop" />
+  </ItemGroup>
+
+</Project>

+ 157 - 0
src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs

@@ -0,0 +1,157 @@
+// 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.Text.Json;
+using Microsoft.JSInterop;
+using Microsoft.JSInterop.Infrastructure;
+using WebAssembly.JSInterop;
+
+namespace Mono.WebAssembly.Interop
+{
+    /// <summary>
+    /// Provides methods for invoking JavaScript functions for applications running
+    /// on the Mono WebAssembly runtime.
+    /// </summary>
+    public class MonoWebAssemblyJSRuntime : JSInProcessRuntime
+    {
+        /// <summary>
+        /// Gets the <see cref="MonoWebAssemblyJSRuntime"/> used to perform operations using <see cref="DotNetDispatcher"/>.
+        /// </summary>
+        private static MonoWebAssemblyJSRuntime Instance { get; set; }
+
+        /// <summary>
+        /// Initializes the <see cref="MonoWebAssemblyJSRuntime"/> to be used to perform operations using <see cref="DotNetDispatcher"/>.
+        /// </summary>
+        /// <param name="jsRuntime">The <see cref="MonoWebAssemblyJSRuntime"/> instance.</param>
+        protected static void Initialize(MonoWebAssemblyJSRuntime jsRuntime)
+        {
+            if (Instance != null)
+            {
+                throw new InvalidOperationException("MonoWebAssemblyJSRuntime has already been initialized.");
+            }
+
+            Instance = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
+        }
+
+        /// <inheritdoc />
+        protected override string InvokeJS(string identifier, string argsJson)
+        {
+            var noAsyncHandle = default(long);
+            var result = InternalCalls.InvokeJSMarshalled(out var exception, ref noAsyncHandle, identifier, argsJson);
+            return exception != null
+                ? throw new JSException(exception)
+                : result;
+        }
+
+        /// <inheritdoc />
+        protected override void BeginInvokeJS(long asyncHandle, string identifier, string argsJson)
+        {
+            InternalCalls.InvokeJSMarshalled(out _, ref asyncHandle, identifier, argsJson);
+        }
+
+        // Invoked via Mono's JS interop mechanism (invoke_method)
+        private static string InvokeDotNet(string assemblyName, string methodIdentifier, string dotNetObjectId, string argsJson)
+        {
+            var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId == null ? default : long.Parse(dotNetObjectId), callId: null);
+            return DotNetDispatcher.Invoke(Instance, callInfo, argsJson);
+        }
+
+        // Invoked via Mono's JS interop mechanism (invoke_method)
+        private static void EndInvokeJS(string argsJson)
+            => DotNetDispatcher.EndInvokeJS(Instance, argsJson);
+
+        // Invoked via Mono's JS interop mechanism (invoke_method)
+        private static void BeginInvokeDotNet(string callId, string assemblyNameOrDotNetObjectId, string methodIdentifier, string argsJson)
+        {
+            // Figure out whether 'assemblyNameOrDotNetObjectId' is the assembly name or the instance ID
+            // We only need one for any given call. This helps to work around the limitation that we can
+            // only pass a maximum of 4 args in a call from JS to Mono WebAssembly.
+            string assemblyName;
+            long dotNetObjectId;
+            if (char.IsDigit(assemblyNameOrDotNetObjectId[0]))
+            {
+                dotNetObjectId = long.Parse(assemblyNameOrDotNetObjectId);
+                assemblyName = null;
+            }
+            else
+            {
+                dotNetObjectId = default;
+                assemblyName = assemblyNameOrDotNetObjectId;
+            }
+
+            var callInfo = new DotNetInvocationInfo(assemblyName, methodIdentifier, dotNetObjectId, callId);
+            DotNetDispatcher.BeginInvokeDotNet(Instance, callInfo, argsJson);
+        }
+
+        protected override void EndInvokeDotNet(DotNetInvocationInfo callInfo, in DotNetInvocationResult dispatchResult)
+        {
+            // For failures, the common case is to call EndInvokeDotNet with the Exception object.
+            // For these we'll serialize as something that's useful to receive on the JS side.
+            // If the value is not an Exception, we'll just rely on it being directly JSON-serializable.
+            var resultOrError = dispatchResult.Success ? dispatchResult.Result : dispatchResult.Exception.ToString();
+
+            // We pass 0 as the async handle because we don't want the JS-side code to
+            // send back any notification (we're just providing a result for an existing async call)
+            var args = JsonSerializer.Serialize(new[] { callInfo.CallId, dispatchResult.Success, resultOrError }, JsonSerializerOptions);
+            BeginInvokeJS(0, "DotNet.jsCallDispatcher.endInvokeDotNetFromJS", args);
+        }
+
+        #region Custom MonoWebAssemblyJSRuntime methods
+
+        /// <summary>
+        /// Invokes the JavaScript function registered with the specified identifier.
+        /// </summary>
+        /// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
+        /// <param name="identifier">The identifier used when registering the target function.</param>
+        /// <returns>The result of the function invocation.</returns>
+        public TRes InvokeUnmarshalled<TRes>(string identifier)
+            => InvokeUnmarshalled<object, object, object, TRes>(identifier, null, null, null);
+
+        /// <summary>
+        /// Invokes the JavaScript function registered with the specified identifier.
+        /// </summary>
+        /// <typeparam name="T0">The type of the first argument.</typeparam>
+        /// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
+        /// <param name="identifier">The identifier used when registering the target function.</param>
+        /// <param name="arg0">The first argument.</param>
+        /// <returns>The result of the function invocation.</returns>
+        public TRes InvokeUnmarshalled<T0, TRes>(string identifier, T0 arg0)
+            => InvokeUnmarshalled<T0, object, object, TRes>(identifier, arg0, null, null);
+
+        /// <summary>
+        /// Invokes the JavaScript function registered with the specified identifier.
+        /// </summary>
+        /// <typeparam name="T0">The type of the first argument.</typeparam>
+        /// <typeparam name="T1">The type of the second argument.</typeparam>
+        /// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
+        /// <param name="identifier">The identifier used when registering the target function.</param>
+        /// <param name="arg0">The first argument.</param>
+        /// <param name="arg1">The second argument.</param>
+        /// <returns>The result of the function invocation.</returns>
+        public TRes InvokeUnmarshalled<T0, T1, TRes>(string identifier, T0 arg0, T1 arg1)
+            => InvokeUnmarshalled<T0, T1, object, TRes>(identifier, arg0, arg1, null);
+
+        /// <summary>
+        /// Invokes the JavaScript function registered with the specified identifier.
+        /// </summary>
+        /// <typeparam name="T0">The type of the first argument.</typeparam>
+        /// <typeparam name="T1">The type of the second argument.</typeparam>
+        /// <typeparam name="T2">The type of the third argument.</typeparam>
+        /// <typeparam name="TRes">The .NET type corresponding to the function's return value type.</typeparam>
+        /// <param name="identifier">The identifier used when registering the target function.</param>
+        /// <param name="arg0">The first argument.</param>
+        /// <param name="arg1">The second argument.</param>
+        /// <param name="arg2">The third argument.</param>
+        /// <returns>The result of the function invocation.</returns>
+        public TRes InvokeUnmarshalled<T0, T1, T2, TRes>(string identifier, T0 arg0, T1 arg1, T2 arg2)
+        {
+            var result = InternalCalls.InvokeJSUnmarshalled<T0, T1, T2, TRes>(out var exception, identifier, arg0, arg1, arg2);
+            return exception != null
+                ? throw new JSException(exception)
+                : result;
+        }
+
+        #endregion
+    }
+}

+ 18 - 0
src/Components/Components.sln

@@ -246,6 +246,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests", "Blazor\Validation\test\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj", "{A5617A9D-C71E-44DE-936C-27611EB40A02}"
 EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Mono.WebAssembly.Interop", "Mono.WebAssembly.Interop", "{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.WebAssembly.Interop", "Blazor\Mono.WebAssembly.Interop\src\Mono.WebAssembly.Interop.csproj", "{D141CFEE-D10A-406B-8963-F86FA13732E3}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -1516,6 +1520,18 @@ Global
 		{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x64.Build.0 = Release|Any CPU
 		{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.ActiveCfg = Release|Any CPU
 		{A5617A9D-C71E-44DE-936C-27611EB40A02}.Release|x86.Build.0 = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x64.Build.0 = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Debug|x86.Build.0 = Debug|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.ActiveCfg = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x64.Build.0 = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.ActiveCfg = Release|Any CPU
+		{D141CFEE-D10A-406B-8963-F86FA13732E3}.Release|x86.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -1629,6 +1645,8 @@ Global
 		{FD9BD646-9D50-42ED-A3E1-90558BA0C6B2} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{B70F90C7-2696-4050-B24E-BF0308F4E059} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
 		{A5617A9D-C71E-44DE-936C-27611EB40A02} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
+		{21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05} = {7260DED9-22A9-4E9D-92F4-5E8A4404DEAF}
+		{D141CFEE-D10A-406B-8963-F86FA13732E3} = {21BB9C13-20C1-4F2B-80E4-D7C64AA3BD05}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {CC3C47E1-AD1A-4619-9CD3-E08A0148E5CE}

+ 1 - 0
src/Components/ComponentsNoDeps.slnf

@@ -17,6 +17,7 @@
       "Blazor\\Templates\\src\\Microsoft.AspNetCore.Blazor.Templates.csproj",
       "Blazor\\Validation\\src\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.csproj",
       "Blazor\\Validation\\test\\Microsoft.AspNetCore.Blazor.DataAnnotations.Validation.Tests.csproj",
+      "Blazor\\Mono.WebAssembly.Interop\\src\\Mono.WebAssembly.Interop.csproj",
       "Blazor\\testassets\\HostedInAspNet.Client\\HostedInAspNet.Client.csproj",
       "Blazor\\testassets\\HostedInAspNet.Server\\HostedInAspNet.Server.csproj",
       "Blazor\\testassets\\Microsoft.AspNetCore.Blazor.E2EPerformance\\Microsoft.AspNetCore.Blazor.E2EPerformance.csproj",