Skip to content

Commit 92ae132

Browse files
committed
swap delegate allocation with state allocation
1 parent e2193e6 commit 92ae132

File tree

3 files changed

+65
-45
lines changed

3 files changed

+65
-45
lines changed

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

Lines changed: 61 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -232,48 +232,9 @@ private static async Task<WasmFetchResponse> CallFetch(HttpRequestMessage reques
232232
Stream stream = await request.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(true);
233233
cancellationToken.ThrowIfCancellationRequested();
234234

235-
byte[]? buffer = null;
236-
237-
var pull = async void (JSObject controller, int desiredSize) =>
238-
{
239-
Memory<byte> view;
240-
if (desiredSize > 0)
241-
{
242-
if (buffer is null || buffer.Length < desiredSize)
243-
{
244-
view = buffer = new byte[desiredSize];
245-
}
246-
else
247-
{
248-
view = buffer.AsMemory(0, desiredSize);
249-
}
250-
}
251-
else
252-
{
253-
view = buffer ??= new byte[65536];
254-
}
255-
256-
using (controller)
257-
{
258-
try
259-
{
260-
int length = await stream.ReadAsync(view, cancellationToken).ConfigureAwait(true);
261-
using (Buffers.MemoryHandle handle = view.Pin())
262-
{
263-
ReadableStreamControllerEnqueueUnsafe(controller, handle, length);
264-
}
265-
}
266-
catch (Exception ex)
267-
{
268-
BrowserHttpInterop.ReadableStreamControllerError(controller, ex);
269-
}
270-
}
271-
};
272-
273-
unsafe static void ReadableStreamControllerEnqueueUnsafe(JSObject controller, Buffers.MemoryHandle handle, int length) =>
274-
BrowserHttpInterop.ReadableStreamControllerEnqueue(controller, (IntPtr)handle.Pointer, length);
275-
276-
promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, pull);
235+
ReadableStreamPullState pullState = new ReadableStreamPullState(stream, cancellationToken);
236+
237+
promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, ReadableStreamPull, pullState);
277238
}
278239
else
279240
{
@@ -306,6 +267,49 @@ unsafe static void ReadableStreamControllerEnqueueUnsafe(JSObject controller, Bu
306267
}
307268
}
308269

270+
private static async void ReadableStreamPull(JSObject controller, int desiredSize, object state)
271+
{
272+
using (controller)
273+
{
274+
try
275+
{
276+
ReadableStreamPullState pullState = (ReadableStreamPullState)state;
277+
278+
byte[]? buffer = pullState.Buffer;
279+
Memory<byte> view;
280+
if (desiredSize > 0)
281+
{
282+
if (buffer is null || buffer.Length < desiredSize)
283+
{
284+
view = buffer = new byte[desiredSize];
285+
}
286+
else
287+
{
288+
view = buffer.AsMemory(0, desiredSize);
289+
}
290+
}
291+
else
292+
{
293+
view = buffer ??= new byte[65536];
294+
}
295+
pullState.Buffer = buffer;
296+
297+
int length = await pullState.Stream.ReadAsync(view, pullState.CancellationToken).ConfigureAwait(true);
298+
using (Buffers.MemoryHandle handle = view.Pin())
299+
{
300+
ReadableStreamControllerEnqueueUnsafe(controller, handle, length);
301+
}
302+
}
303+
catch (Exception ex)
304+
{
305+
BrowserHttpInterop.ReadableStreamControllerError(controller, ex);
306+
}
307+
}
308+
309+
unsafe static void ReadableStreamControllerEnqueueUnsafe(JSObject controller, Buffers.MemoryHandle handle, int length) =>
310+
BrowserHttpInterop.ReadableStreamControllerEnqueue(controller, (IntPtr)handle.Pointer, length);
311+
}
312+
309313
private static HttpResponseMessage ConvertResponse(HttpRequestMessage request, WasmFetchResponse fetchResponse)
310314
{
311315
#if FEATURE_WASM_THREADS
@@ -370,6 +374,21 @@ static async Task<HttpResponseMessage> Impl(HttpRequestMessage request, Cancella
370374
}
371375
}
372376

377+
internal sealed class ReadableStreamPullState
378+
{
379+
public ReadableStreamPullState(Stream stream, CancellationToken cancellationToken)
380+
{
381+
ArgumentNullException.ThrowIfNull(stream);
382+
383+
Stream = stream;
384+
CancellationToken = cancellationToken;
385+
}
386+
387+
public Stream Stream { get; }
388+
public CancellationToken CancellationToken { get; }
389+
public byte[]? Buffer { get; set; }
390+
}
391+
373392
internal sealed class WasmFetchResponse : IDisposable
374393
{
375394
#if FEATURE_WASM_THREADS

src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpInterop.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,8 @@ public static partial Task<JSObject> Fetch(
8080
string[] optionNames,
8181
[JSMarshalAs<JSType.Array<JSType.Any>>] object?[] optionValues,
8282
JSObject abortControler,
83-
[JSMarshalAs<JSType.Function<JSType.Object, JSType.Number>>] Action<JSObject, int> pull);
83+
[JSMarshalAs<JSType.Function<JSType.Object, JSType.Number, JSType.Any>>] Action<JSObject, int, object> pull,
84+
[JSMarshalAs<JSType.Any>] object pullState);
8485

8586
[JSImport("INTERNAL.http_wasm_fetch_bytes")]
8687
private static partial Task<JSObject> FetchBytes(

src/mono/wasm/runtime/http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export function http_wasm_readable_stream_controller_error(controller: ReadableB
8181
controller.__resolve_pull();
8282
}
8383

84-
export function http_wasm_fetch_stream(url: string, header_names: string[], header_values: string[], option_names: string[], option_values: any[], abort_controller: AbortController, pull: (controller: ReadableByteStreamControllerExtension, desired_size: number) => void): Promise<ResponseExtension> {
84+
export function http_wasm_fetch_stream(url: string, header_names: string[], header_values: string[], option_names: string[], option_values: any[], abort_controller: AbortController, pull: (controller: ReadableByteStreamControllerExtension, desired_size: number, pull_state: any) => void, pull_state: any): Promise<ResponseExtension> {
8585
return new Promise((resolve_fetch, reject_fetch) => {
8686
const body = new ReadableStream({
8787
type: "bytes",
@@ -95,7 +95,7 @@ export function http_wasm_fetch_stream(url: string, header_names: string[], head
9595
}
9696
c.__resolve_pull = pull_promise_control.resolve;
9797
c.__reject_fetch = reject_fetch;
98-
pull(c, desired_size || 0);
98+
pull(c, desired_size || 0, pull_state);
9999
return pull_promise;
100100
},
101101
cancel(reason) {

0 commit comments

Comments
 (0)