-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Conversation
- This still needs to have the code implement nullable
…http-interop # Conflicts: # src/libraries/System.Net.Http/src/System.Net.Http.csproj
Tagging subscribers to this area: @dotnet/ncl |
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.JavaScript.Array.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this 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!
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.JavaScript.Array.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.HttpHandlerService.cs
Outdated
Show resolved
Hide resolved
src/libraries/Common/src/Interop/Browser/Interop.JavaScript.HostObject.cs
Outdated
Show resolved
Hide resolved
...ibraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpMessageHandler.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/SocketsHttpHandler.cs
Outdated
Show resolved
Hide resolved
- Throws `PlatformNotSupportedException` for properties and methods of the HttpMessageHandler abstract implementation.
- Addresses commit comments.
There was a problem hiding this 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.
I'll take another pass through it today. |
…used to obtain the socket field
@@ -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); |
There was a problem hiding this comment.
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(); | ||
} |
There was a problem hiding this comment.
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(); |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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(); | ||
} | ||
|
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
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."); |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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> |
There was a problem hiding this comment.
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 | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
/// <param name="js_handle">Js handle.</param> | ||
internal DataView(IntPtr js_handle) : base(js_handle) | ||
{ } | ||
/// <summary> |
There was a problem hiding this comment.
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) { } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
public Float64Array() { } | ||
|
||
public Float64Array(int length) : base(length) { } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
|
||
public Int8Array(int length) : base(length) | ||
{ } | ||
|
There was a problem hiding this comment.
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.
public DictionaryEntry Entry => (DictionaryEntry)Current; | ||
|
||
// Return the key of the current item. | ||
public object Key { get; private set; } = new object(); |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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?
Will follow up with PR to address the other points. |
Initial file support for Interop and Http handlers.