summaryrefslogtreecommitdiff
path: root/ext/fetch/22_body.js
diff options
context:
space:
mode:
authorMarcos Casagrande <marcoscvp90@gmail.com>2022-10-04 15:48:50 +0200
committerGitHub <noreply@github.com>2022-10-04 15:48:50 +0200
commit569287b15b6482a39f2c816f103574c3b35351f8 (patch)
treeff8433fc87613e3016ff7a188ee34aa3fc7d81c4 /ext/fetch/22_body.js
parent0b4a6c4d084df54e827bc7767ce8653e06c45e93 (diff)
perf(ext/fetch): consume body using ops (#16038)
This commit adds a fast path to `Request` and `Response` that make consuming request bodies much faster when using `Body#text`, `Body#arrayBuffer`, and `Body#blob`, if the body is a FastStream. Because the response bodies for `fetch` are FastStream, this speeds up consuming `fetch` response bodies significantly.
Diffstat (limited to 'ext/fetch/22_body.js')
-rw-r--r--ext/fetch/22_body.js48
1 files changed, 5 insertions, 43 deletions
diff --git a/ext/fetch/22_body.js b/ext/fetch/22_body.js
index 6e9a57447..429b56ae1 100644
--- a/ext/fetch/22_body.js
+++ b/ext/fetch/22_body.js
@@ -30,19 +30,18 @@
errorReadableStream,
readableStreamClose,
readableStreamDisturb,
+ readableStreamCollectIntoUint8Array,
createProxy,
ReadableStreamPrototype,
} = globalThis.__bootstrap.streams;
const {
ArrayBufferPrototype,
ArrayBufferIsView,
- ArrayPrototypePush,
ArrayPrototypeMap,
JSONParse,
ObjectDefineProperties,
ObjectPrototypeIsPrototypeOf,
PromiseResolve,
- TypedArrayPrototypeSet,
TypedArrayPrototypeSlice,
TypeError,
Uint8Array,
@@ -66,12 +65,10 @@
}
class InnerBody {
- #knownExactLength = null;
-
/**
* @param {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} stream
*/
- constructor(stream, knownExactLength) {
+ constructor(stream) {
/** @type {ReadableStream<Uint8Array> | { body: Uint8Array | string, consumed: boolean }} */
this.streamOrStatic = stream ??
{ body: new Uint8Array(), consumed: false };
@@ -79,8 +76,6 @@
this.source = null;
/** @type {null | number} */
this.length = null;
-
- this.#knownExactLength = knownExactLength;
}
get stream() {
@@ -144,7 +139,7 @@
* https://fetch.spec.whatwg.org/#concept-body-consume-body
* @returns {Promise<Uint8Array>}
*/
- async consume() {
+ consume() {
if (this.unusable()) throw new TypeError("Body already consumed.");
if (
ObjectPrototypeIsPrototypeOf(
@@ -152,40 +147,7 @@
this.streamOrStatic,
)
) {
- 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;
-
- 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;
- }
-
- if (finalBuffer) {
- return finalBuffer;
- }
-
- finalBuffer = new Uint8Array(totalLength);
- let i = 0;
- for (const chunk of chunks) {
- TypedArrayPrototypeSet(finalBuffer, chunk, i);
- i += chunk.byteLength;
- }
- return finalBuffer;
+ return readableStreamCollectIntoUint8Array(this.stream);
} else {
this.streamOrStatic.consumed = true;
return this.streamOrStatic.body;
@@ -224,7 +186,7 @@
clone() {
const [out1, out2] = this.stream.tee();
this.streamOrStatic = out1;
- const second = new InnerBody(out2, this.#knownExactLength);
+ const second = new InnerBody(out2);
second.source = core.deserialize(core.serialize(this.source));
second.length = this.length;
return second;