diff --git a/eng/ProjectReferences.props b/eng/ProjectReferences.props
index 3ac3e8dbf6..d170c5aa24 100644
--- a/eng/ProjectReferences.props
+++ b/eng/ProjectReferences.props
@@ -15,6 +15,7 @@
+
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index e5f59d2cb6..92ed43ccfb 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -289,10 +289,6 @@
https://github.com/aspnet/Extensions4ebd75b961136c7ca331866eed3403becda75681
-
- https://github.com/aspnet/Extensions
- 4ebd75b961136c7ca331866eed3403becda75681
- https://github.com/dotnet/corefx0f7f38c4fd323b26da10cce95f857f77f0f09b48
diff --git a/eng/Versions.props b/eng/Versions.props
index 4c61494afa..e2dd6a11fe 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -158,7 +158,6 @@
3.1.03.1.0-rtm.19568.33.1.0
- 3.1.0-preview4.19568.33.1.03.1.0
diff --git a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj
index be140d936e..18bdc5e1fe 100644
--- a/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj
+++ b/src/Components/Blazor/Http/src/Microsoft.AspNetCore.Blazor.HttpClient.csproj
@@ -1,7 +1,7 @@
- netstandard2.1
+ netstandard2.0Provides experimental support for using System.Text.Json with HttpClient. Intended for use with Blazor running under WebAssembly.true
diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs b/src/Components/Blazor/Mono.WebAssembly.Interop/src/InternalCalls.cs
new file mode 100644
index 0000000000..60c0cdc429
--- /dev/null
+++ b/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
+{
+ ///
+ /// Methods that map to the functions compiled into the Mono WebAssembly runtime,
+ /// as defined by 'mono_add_internal_call' calls in driver.c
+ ///
+ 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(out string exception, string functionIdentifier, T0 arg0, T1 arg1, T2 arg2);
+ }
+}
diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj b/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj
new file mode 100644
index 0000000000..ea714b2d92
--- /dev/null
+++ b/src/Components/Blazor/Mono.WebAssembly.Interop/src/Mono.WebAssembly.Interop.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.1
+ Abstractions and features for interop between Mono WebAssembly and JavaScript code.
+ wasm;javascript;interop
+ true
+ true
+ true
+ false
+
+
+
+
+
+
+
diff --git a/src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs b/src/Components/Blazor/Mono.WebAssembly.Interop/src/MonoWebAssemblyJSRuntime.cs
new file mode 100644
index 0000000000..654263a123
--- /dev/null
+++ b/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
+{
+ ///
+ /// Provides methods for invoking JavaScript functions for applications running
+ /// on the Mono WebAssembly runtime.
+ ///
+ public class MonoWebAssemblyJSRuntime : JSInProcessRuntime
+ {
+ ///
+ /// Gets the used to perform operations using .
+ ///
+ private static MonoWebAssemblyJSRuntime Instance { get; set; }
+
+ ///
+ /// Initializes the to be used to perform operations using .
+ ///
+ /// The instance.
+ protected static void Initialize(MonoWebAssemblyJSRuntime jsRuntime)
+ {
+ if (Instance != null)
+ {
+ throw new InvalidOperationException("MonoWebAssemblyJSRuntime has already been initialized.");
+ }
+
+ Instance = jsRuntime ?? throw new ArgumentNullException(nameof(jsRuntime));
+ }
+
+ ///
+ 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;
+ }
+
+ ///
+ 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
+
+ ///
+ /// Invokes the JavaScript function registered with the specified identifier.
+ ///
+ /// The .NET type corresponding to the function's return value type.
+ /// The identifier used when registering the target function.
+ /// The result of the function invocation.
+ public TRes InvokeUnmarshalled(string identifier)
+ => InvokeUnmarshalled