summaryrefslogtreecommitdiff
path: root/ext/fetch
diff options
context:
space:
mode:
Diffstat (limited to 'ext/fetch')
-rw-r--r--ext/fetch/22_body.js29
-rw-r--r--ext/fetch/26_fetch.js1
-rw-r--r--ext/fetch/lib.rs4
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,
})
}