diff options
Diffstat (limited to 'ext/fetch')
-rw-r--r-- | ext/fetch/22_body.js | 29 | ||||
-rw-r--r-- | ext/fetch/26_fetch.js | 1 | ||||
-rw-r--r-- | ext/fetch/lib.rs | 4 |
3 files changed, 30 insertions, 4 deletions
diff --git a/ext/fetch/22_body.js b/ext/fetch/22_body.js index a51cdc184..97a8a8db1 100644 --- a/ext/fetch/22_body.js +++ b/ext/fetch/22_body.js @@ -64,10 +64,12 @@ } class InnerBody { + #knownExactLength = null; + /** * @param {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} stream */ - constructor(stream) { + constructor(stream, knownExactLength) { /** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */ this.streamOrStatic = stream ?? { body: new Uint8Array(), consumed: false }; @@ -75,6 +77,8 @@ this.source = null; /** @type {null | number} */ this.length = null; + + this.#knownExactLength = knownExactLength; } get stream() { @@ -147,14 +151,31 @@ const reader = this.stream.getReader(); /** @type {Uint8Array[]} */ const chunks = []; + + let finalBuffer = this.#knownExactLength + ? new Uint8Array(this.#knownExactLength) + : null; + let totalLength = 0; while (true) { const { value: chunk, done } = await reader.read(); if (done) break; - ArrayPrototypePush(chunks, chunk); + + if (finalBuffer) { + // fast path, content-length is present + TypedArrayPrototypeSet(finalBuffer, chunk, totalLength); + } else { + // slow path, content-length is not present + ArrayPrototypePush(chunks, chunk); + } totalLength += chunk.byteLength; } - const finalBuffer = new Uint8Array(totalLength); + + if (finalBuffer) { + return finalBuffer; + } + + finalBuffer = new Uint8Array(totalLength); let i = 0; for (const chunk of chunks) { TypedArrayPrototypeSet(finalBuffer, chunk, i); @@ -199,7 +220,7 @@ clone() { const [out1, out2] = this.stream.tee(); this.streamOrStatic = out1; - const second = new InnerBody(out2); + const second = new InnerBody(out2, this.#knownExactLength); second.source = core.deserialize(core.serialize(this.source)); second.length = this.length; return second; diff --git a/ext/fetch/26_fetch.js b/ext/fetch/26_fetch.js index c980bc9b8..13c34f534 100644 --- a/ext/fetch/26_fetch.js +++ b/ext/fetch/26_fetch.js @@ -335,6 +335,7 @@ } else { response.body = new InnerBody( createResponseBodyStream(resp.responseRid, terminator), + resp.contentLength, ); } } diff --git a/ext/fetch/lib.rs b/ext/fetch/lib.rs index 20db7abbc..3988acf9e 100644 --- a/ext/fetch/lib.rs +++ b/ext/fetch/lib.rs @@ -361,6 +361,7 @@ pub struct FetchResponse { headers: Vec<(ByteString, ByteString)>, url: String, response_rid: ResourceId, + content_length: Option<u64>, } #[op] @@ -391,6 +392,8 @@ pub async fn op_fetch_send( res_headers.push((key.as_str().into(), val.as_bytes().into())); } + let content_length = res.content_length(); + let stream: BytesStream = Box::pin(res.bytes_stream().map(|r| { r.map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err)) })); @@ -409,6 +412,7 @@ pub async fn op_fetch_send( headers: res_headers, url, response_rid: rid, + content_length, }) } |