summaryrefslogtreecommitdiff
path: root/cli/js/web/body.ts
diff options
context:
space:
mode:
Diffstat (limited to 'cli/js/web/body.ts')
-rw-r--r--cli/js/web/body.ts34
1 files changed, 22 insertions, 12 deletions
diff --git a/cli/js/web/body.ts b/cli/js/web/body.ts
index 80c4b646a..3bcda0634 100644
--- a/cli/js/web/body.ts
+++ b/cli/js/web/body.ts
@@ -18,6 +18,11 @@ import { MultipartParser } from "./fetch/multipart.ts";
const { TextEncoder, TextDecoder } = encoding;
const DenoBlob = blob.DenoBlob;
+interface BodyMeta {
+ contentType: string;
+ size?: number;
+}
+
function validateBodyType(owner: Body, bodySource: BodyInit | null): boolean {
if (isTypedArray(bodySource)) {
return true;
@@ -40,11 +45,17 @@ function validateBodyType(owner: Body, bodySource: BodyInit | null): boolean {
}
async function bufferFromStream(
- stream: ReadableStreamReader
+ stream: ReadableStreamReader,
+ size?: number
): Promise<ArrayBuffer> {
const encoder = new TextEncoder();
const buffer = new Buffer();
+ if (size) {
+ // grow to avoid unnecessary allocations & copies
+ buffer.grow(size);
+ }
+
while (true) {
const { done, value } = await stream.read();
@@ -71,14 +82,13 @@ export const BodyUsedError =
export class Body implements domTypes.Body {
protected _stream: ReadableStreamImpl<string | ArrayBuffer> | null;
-
- constructor(
- protected _bodySource: BodyInit | null,
- readonly contentType: string
- ) {
+ #contentType: string;
+ #size: number | undefined;
+ constructor(protected _bodySource: BodyInit | null, meta: BodyMeta) {
validateBodyType(this, _bodySource);
this._bodySource = _bodySource;
- this.contentType = contentType;
+ this.#contentType = meta.contentType;
+ this.#size = meta.size;
this._stream = null;
}
@@ -111,15 +121,15 @@ export class Body implements domTypes.Body {
public async blob(): Promise<Blob> {
return new DenoBlob([await this.arrayBuffer()], {
- type: this.contentType,
+ type: this.#contentType,
});
}
// ref: https://fetch.spec.whatwg.org/#body-mixin
public async formData(): Promise<FormData> {
const formData = new FormData();
- if (hasHeaderValueOf(this.contentType, "multipart/form-data")) {
- const params = getHeaderValueParams(this.contentType);
+ if (hasHeaderValueOf(this.#contentType, "multipart/form-data")) {
+ const params = getHeaderValueParams(this.#contentType);
// ref: https://tools.ietf.org/html/rfc2046#section-5.1
const boundary = params.get("boundary")!;
@@ -128,7 +138,7 @@ export class Body implements domTypes.Body {
return multipartParser.parse();
} else if (
- hasHeaderValueOf(this.contentType, "application/x-www-form-urlencoded")
+ hasHeaderValueOf(this.#contentType, "application/x-www-form-urlencoded")
) {
// From https://github.com/github/fetch/blob/master/fetch.js
// Copyright (c) 2014-2016 GitHub, Inc. MIT License
@@ -184,7 +194,7 @@ export class Body implements domTypes.Body {
enc.encode(this._bodySource).buffer as ArrayBuffer
);
} else if (this._bodySource instanceof ReadableStreamImpl) {
- return bufferFromStream(this._bodySource.getReader());
+ return bufferFromStream(this._bodySource.getReader(), this.#size);
} else if (
this._bodySource instanceof FormData ||
this._bodySource instanceof URLSearchParams