Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Initial addition of Browser WebAssembly support #35573

Merged
merged 114 commits into from
Jun 1, 2020
Merged

[wasm] Initial addition of Browser WebAssembly support #35573

merged 114 commits into from
Jun 1, 2020

Conversation

kjpou1
Copy link
Contributor

@kjpou1 kjpou1 commented Apr 28, 2020

Initial file support for Interop and Http handlers.

@ghost
Copy link

ghost commented Apr 28, 2020

Tagging subscribers to this area: @dotnet/ncl
Notify danmosemsft if you want to be subscribed.

Copy link
Member

@stephentoub stephentoub left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for starting to work on this. I skimmed it and left a few comments. I'll comment in more depth when it's further along and the initial round of feedback has been addressed. Thanks!

@kjpou1 kjpou1 changed the title Initial addition of Browser WebAssembly support [wasm] Initial addition of Browser WebAssembly support Apr 29, 2020
@kjpou1 kjpou1 requested a review from jkotas May 27, 2020 08:38
Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CI failures seem to be related to the change. The CI needs to be green before this is merged.

All my concerns are addressed.

I would like to see somebody from the networking team to sign-off on this as well.

@jkotas jkotas requested a review from a team May 27, 2020 15:27
@stephentoub
Copy link
Member

I'll take another pass through it today.

@@ -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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that _underlyingHandler could be something other than a SocketsHttpHandler, this set of checks will probably need to be updated to validate that the instance retrieved from the field actually is a SocketsHttpHandler and bailing if it's not. That could be left for later, but if we start running the System.Net.Http tests against the webassembly implementation, this will likely cause problems (then again, I expect a ton of tests wouldn't pass, anyway).

{
using (var streamingSupported = new Function("return typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream === 'function'"))
StreamingSupported = (bool)streamingSupported.Call();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't need to be in this PR, but it might be worth refactoring this subsequently to avoid the explicit static cctor, e.g.

private static bool StreamingSupported { get; } = GetIsStreamingSupported();

private static bool GetIsStreamingSupported()
{
    using (var streamingSupported = new Function("return typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream === 'function'"))
        return (bool)streamingSupported.Call();
}

set => throw new PlatformNotSupportedException();
}

public IDictionary<string, object?> Properties => throw new PlatformNotSupportedException();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May not matter, but this can be made to work, e.g.

private Dictionary<string, object?>? _properties;
public IDictionary<string, object?> Properties => _properties ??= new Dictionary<string, object?>();

It's fine if you want to punt on that for now, given that most everything else throws PNSE and there's little reason right now for someone to be storing data into properties.


protected override Task SerializeToStreamAsync(Stream stream, TransportContext? context) =>
SerializeToStreamAsync(stream, context, CancellationToken.None);
protected sealed override async Task SerializeToStreamAsync(Stream stream, TransportContext? context, CancellationToken cancellationToken)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: the sealed here isn't necessary, as the whole class is sealed

get => throw new NotSupportedException();
set => throw new NotSupportedException();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: you might want to override BeginRead/EndRead as well; if you don't and someone uses them, they'll end up getting an exception about synchronous reads not being supported, as by default the base implementations just queue a work item that wraps the sync method. You can implement these pretty easily with an internal helper that should already be available in this library, e.g. something like:

public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsynCallback? callback, object? state) =>
    TaskToApm.Begin(ReadAsync(buffer, offset, count), callback, state);

public override int EndRead(IAsyncResult asyncResult) => TaskToApm.End<int>(asyncResult);

Search for BeginRead/EndRead and you should find other examples in this project.

}
}

if (_bufferedBytes != null && _position < _bufferedBytes.Length)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I reading this correctly that if someone reads to the end but then calls read again (such that _position >= _bufferedBytes.Length), they'll end up starting to read again at the beginning because they'll fail this if check and proceed to the below try? If so, that seems wrong.

public bool UseCookies
{
get => throw new PlatformNotSupportedException("Property UseCookies is not supported.");
set => throw new PlatformNotSupportedException("Property UseCookies is not supported.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still see all of these custom messages being passed to PNSE.

ThrowForModifiedManagedSslOptionsIfStarted();
_clientCertificateOptions = value;
_socketsHttpHandler.SslOptions.LocalCertificateSelectionCallback = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => CertificateHelper.GetEligibleClientCertificate()!;
_underlyingHandler.SslOptions.LocalCertificateSelectionCallback = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => CertificateHelper.GetEligibleClientCertificate()!;
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These ifdefs are ok for now. It'd be good to see if we can find a cleaner solution subsequently.

<StrongNameKeyId>Microsoft</StrongNameKeyId>
<IsNETCoreApp>true</IsNETCoreApp>
</PropertyGroup>
</Project>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing a newline at the end of the file


namespace System.Runtime.InteropServices.JavaScript
{

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change

/// <param name="js_handle">Js handle.</param>
internal DataView(IntPtr js_handle) : base(js_handle)
{ }
/// <summary>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: some of these members have blank lines between them, some don't

public Float32Array() { }

public Float32Array(int length) : base(length) { }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change

public Float64Array() { }

public Float64Array(int length) : base(length) { }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change


public Int8Array(int length) : base(length)
{ }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:
Another extra blank line. I'll stop commenting on these, but there look to be a few more.

Suggested change

public DictionaryEntry Entry => (DictionaryEntry)Current;

// Return the key of the current item.
public object Key { get; private set; } = new object();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems a little strange to be assigning a new object to Key here. Is that intentional?

}

// TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
// TODO: set large fields to null.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the plan for all these TODOs? Is there an issue tracking whatever needs to be done here?

@kjpou1 kjpou1 merged commit ca527ba into dotnet:master Jun 1, 2020
@kjpou1
Copy link
Contributor Author

kjpou1 commented Jun 1, 2020

Will follow up with PR to address the other points.

@kjpou1 kjpou1 deleted the wasm-http-interop branch June 1, 2020 07:07
@karelz karelz added this to the 5.0.0 milestone Aug 18, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 9, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Net.Http
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants