Skip to content

Commit

Permalink
[wasm] Initial addition of Browser WebAssembly support (#35573)
Browse files Browse the repository at this point in the history
* Add Browser specific files to the project

* Browser specific file modification to not include Quic support

* Add Browser specific support files for Http Handler code

* Add Interop code for JavaScript support

* Remove unused reference

* Add Http handler bindings implementation

- This still needs to have the code implement nullable

* Nullable support

* Add browser files back after upstream merge conflict

* Use attribute Link syntax for Common files to bring in sync with existing format

* Address Missing license header

* Code formatting and removal of comment code.

* Address PR comments.

* Address commit comments

* Add blank line between License and first line of code.  Address comments

* Replace SocketsHttpHandler build for Browser.

- Throws `PlatformNotSupportedException` for properties and methods of the HttpMessageHandler abstract implementation.

* Cleanup SendAsync code when doing the call out to JavaScript Fetch.

- Addresses commit comments.

* Refactor BrowserHttpHandler code.

* Cleanup

* Remove null check as it should be checked in outer classes

* Cleanup var usage to use explicit type.  Address commit comments

- For all of these vars, please replace them with the actual type, except when the type is obvious from a new or explicit cast on the right-hand side.

* Move `.ConfigureAwait(true)` to `.ConfigureAwait(false)`

- Address review comments

* Change accessor of Runtime javascript interop methods.

* Change accessor of Runtime javascript interop methods.

* Address review comments for unused code

* Cleanup leftover debug WriteLines

* Remove the AllowNull attributes as per review comments.

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs

Co-Authored-By: Marek Safar <marek.safar@gmail.com>

* throw different exception type as per review comment

* use char[] array instead and return new string(array).

- Address review comments

* Initial addition of Browser Interop library

* use char[] array instead and return new string(array).

- Address review comments

* Add project references so the Interop.JavaScript project builds

* Coding Style update

* Split the runtime methods into two modules.

- .Api contains the methods that are only used internally from JavaScript bindings code.

* Move System.Runtime.Interop.JavaScript to \src\libraries

- Address review comments

* Change preprocessor to upper case TARGETS_BROWSER

- Address review comments

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.Api.cs

Co-authored-by: Marek Safar <marek.safar@gmail.com>

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.Api.cs

Co-authored-by: Marek Safar <marek.safar@gmail.com>

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.Api.cs

Co-authored-by: Marek Safar <marek.safar@gmail.com>

* Rename from .Api to .Bridge to address review comments

* Modify .csproj files to reflect .Bridge.cs change.

* Remove unnecessary constant

* Add docs

* Update Bridge link

* Collapse code as per review comment.

* Address review comments on `Task.ConfigureAwait(continueOnCapturedContext: true)`.

- Added comment in source code.

* Address review comment about using PropertyInfo reflection.

- GetMethod("get_Result") is less expensive to use.

* Coding Style - Address review comments

* Part of code style and object documentation to partially address review comments.

* Update src/libraries/Common/src/Interop/Browser/Interop.JavaScript.JSObject.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.Bridge.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Add class docs and code style updates

- Address review comments

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Fix badly formed XML

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Remove unnecessary Property implementations.

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Update code style involving the use of `var`

* Modify the underlying sockets field name.

- address review comments.

* Style and address review comments

* Remove reliance on ConnectHelper.cs code as it is not supported on Browser

- This removes the reliance on the QUIC support.

* Update src/libraries/Common/src/Interop/Browser/Interop.Runtime.Bridge.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Remove null check for httpresponse.Content as it is always assigned to.

- Address review comments

* Address review comments

* Remove methods that will not be implemented right now,

* Add properties back to fix build error

- error : MembersMustExist : Member 'public System.Boolean System.Net.Http.SocketsHttpHandler.XXXXXXXXXXXX.get()' does not exist in the implementation but it does exist in the contract.

* Remove tcs TaskCompletionSource to address review comments

* code style change

* Remove disposing of _abortCts here as it causes runtime errors as being disposed of too early

* Address review comment for GetType()

* Rename library as per discussions

* Add lock around the _boundObjects and _rawToJS access.

- Address concurrency review comments

* Address review comments for disposing of CancellationTokenSource

* Address new HttpContent overloads in .NET 5 that take CancellationToken

* Add project and test structure for JavaScript InteropServices

* Remove previous modification as it is no longer needed.

* Update src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs

Co-authored-by: Stephen Toub <stoub@microsoft.com>

* Remove custom message passed to the PNSE .ctor

* Update `mono` to dotnet or .NET

* Address review comment for internal sealed class

* Address extra message text

* Move these source modules to System.Runtime.InteropServices.JavaScript

* Add interop source modules to System.Runtime.InteropServices.JavaScript project

* Remove placeholder source

* Reference System.Runtime.InteropServices.JavaScript project

* Address review comments Unsafe.SizeOf

* Finish move of sources to InteropServices.JavaScript

* Remove ActiveIssue to address review comments

* Add core implementations

* Add core object implementation for Map

* Remove unused targetframework

* Fix PNSE in HttpClientHandler .ctor

- When creating an instance of the browser webassembly `System.Net.Http.BrowserHttpHandler` the following error is thrown.

```
System.PlatformNotSupportedException: Operation is not supported on this platform.
    at System.Net.Http.BrowserHttpHandler.get_SslOptions()
    at System.Net.Http.HttpClientHandler.ThrowForModifiedManagedSslOptionsIfStarted()
    at System.Net.Http.HttpClientHandler.set_ClientCertificateOptions(ClientCertificateOption value)
    at System.Net.Http.HttpClientHandler..ctor()
    at System.Net.Http.HttpClient..ctor()

```

* Remove extra parameters to `PlatformNotSupportedException`

* Fix tests due to underlying field name changing and reflection being used to obtain the socket field

Co-authored-by: Marek Safar <marek.safar@gmail.com>
Co-authored-by: Stephen Toub <stoub@microsoft.com>
  • Loading branch information
3 people authored Jun 1, 2020
1 parent bdf6a5a commit ca527ba
Show file tree
Hide file tree
Showing 36 changed files with 3,189 additions and 101 deletions.
113 changes: 113 additions & 0 deletions src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading.Tasks;

using JSObject = System.Runtime.InteropServices.JavaScript.JSObject;
using JSException = System.Runtime.InteropServices.JavaScript.JSException;

internal static partial class Interop
{
internal static partial class Runtime
{
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern string InvokeJS(string str, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object CompileFunction(string str, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object InvokeJSWithArgs(int jsObjHandle, string method, object?[] parms, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object GetObjectProperty(int jsObjHandle, string propertyName, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object SetObjectProperty(int jsObjHandle, string propertyName, object value, bool createIfNotExists, bool hasOwnProperty, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object GetByIndex(int jsObjHandle, int index, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object SetByIndex(int jsObjHandle, int index, object? value, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object GetGlobalObject(string? globalName, out int exceptionalResult);

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object ReleaseHandle(int jsObjHandle, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object ReleaseObject(int jsObjHandle, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object NewObjectJS(int jsObjHandle, object[] parms, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object BindCoreObject(int jsObjHandle, int gcHandle, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object BindHostObject(int jsObjHandle, int gcHandle, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object New(string className, object[] parms, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object TypedArrayToArray(int jsObjHandle, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object TypedArrayCopyTo(int jsObjHandle, int arrayPtr, int begin, int end, int bytesPerElement, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object TypedArrayFrom(int arrayPtr, int begin, int end, int bytesPerElement, int type, out int exceptionalResult);
[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern object TypedArrayCopyFrom(int jsObjHandle, int arrayPtr, int begin, int end, int bytesPerElement, out int exceptionalResult);

// / <summary>
// / Execute the provided string in the JavaScript context
// / </summary>
// / <returns>The js.</returns>
// / <param name="str">String.</param>
public static string InvokeJS(string str)
{
string res = InvokeJS(str, out int exception);
if (exception != 0)
throw new JSException(res);
return res;
}

public static System.Runtime.InteropServices.JavaScript.Function? CompileFunction(string snippet)
{
object res = CompileFunction(snippet, out int exception);
if (exception != 0)
throw new JSException((string)res);
return res as System.Runtime.InteropServices.JavaScript.Function;
}

public static int New<T>(params object[] parms)
{
object res = New(typeof(T).Name, parms, out int exception);
if (exception != 0)
throw new JSException((string)res);
return (int)res;
}

public static int New(string hostClassName, params object[] parms)
{
object res = New(hostClassName, parms, out int exception);
if (exception != 0)
throw new JSException((string)res);
return (int)res;
}

public static JSObject? NewJSObject(JSObject? jsFuncPtr = null, params object[] parms)
{
object res = NewObjectJS(jsFuncPtr?.JSHandle ?? 0, parms, out int exception);
if (exception != 0)
throw new JSException((string)res);
return res as JSObject;
}
public static object GetGlobalObject(string? str = null)
{
int exception;
object globalHandle = Runtime.GetGlobalObject(str, out exception);

if (exception != 0)
throw new JSException($"Error obtaining a handle to global {str}");

return globalHandle;
}

}
}
2 changes: 1 addition & 1 deletion src/libraries/Common/tests/System/Net/Http/TestHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public static void EnableUnencryptedHttp2IfNecessary(HttpClientHandler handler)
return;
}

FieldInfo socketsHttpHandlerField = typeof(HttpClientHandler).GetField("_socketsHttpHandler", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo socketsHttpHandlerField = typeof(HttpClientHandler).GetField("_underlyingHandler", BindingFlags.NonPublic | BindingFlags.Instance);
if (socketsHttpHandlerField == null)
{
// Not using .NET Core implementation, i.e. could be .NET Framework.
Expand Down
Loading

0 comments on commit ca527ba

Please sign in to comment.