diff options
Diffstat (limited to 'ext/fetch/22_body.js')
-rw-r--r-- | ext/fetch/22_body.js | 29 |
1 files changed, 25 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; |