diff options
Diffstat (limited to 'op_crates/fetch/22_body.js')
-rw-r--r-- | op_crates/fetch/22_body.js | 338 |
1 files changed, 0 insertions, 338 deletions
diff --git a/op_crates/fetch/22_body.js b/op_crates/fetch/22_body.js deleted file mode 100644 index 938e3023e..000000000 --- a/op_crates/fetch/22_body.js +++ /dev/null @@ -1,338 +0,0 @@ -// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. - -// @ts-check -/// <reference path="../webidl/internal.d.ts" /> -/// <reference path="../url/internal.d.ts" /> -/// <reference path="../url/lib.deno_url.d.ts" /> -/// <reference path="../web/internal.d.ts" /> -/// <reference path="../file/internal.d.ts" /> -/// <reference path="../file/lib.deno_file.d.ts" /> -/// <reference path="./internal.d.ts" /> -/// <reference path="./11_streams_types.d.ts" /> -/// <reference path="./lib.deno_fetch.d.ts" /> -/// <reference lib="esnext" /> -"use strict"; - -((window) => { - const core = window.Deno.core; - const webidl = globalThis.__bootstrap.webidl; - const { parseUrlEncoded } = globalThis.__bootstrap.url; - const { parseFormData, formDataFromEntries, encodeFormData } = - globalThis.__bootstrap.formData; - const mimesniff = globalThis.__bootstrap.mimesniff; - const { isReadableStreamDisturbed } = globalThis.__bootstrap.streams; - - class InnerBody { - /** @type {ReadableStream<Uint8Array> | { body: Uint8Array, consumed: boolean }} */ - streamOrStatic; - /** @type {null | Uint8Array | Blob | FormData} */ - source = null; - /** @type {null | number} */ - length = null; - - /** - * @param {ReadableStream<Uint8Array> | { body: Uint8Array, consumed: boolean }} stream - */ - constructor(stream) { - this.streamOrStatic = stream ?? - { body: new Uint8Array(), consumed: false }; - } - - get stream() { - if (!(this.streamOrStatic instanceof ReadableStream)) { - const { body, consumed } = this.streamOrStatic; - this.streamOrStatic = new ReadableStream({ - start(controller) { - controller.enqueue(body); - controller.close(); - }, - }); - if (consumed) { - this.streamOrStatic.cancel(); - } - } - return this.streamOrStatic; - } - - /** - * https://fetch.spec.whatwg.org/#body-unusable - * @returns {boolean} - */ - unusable() { - if (this.streamOrStatic instanceof ReadableStream) { - return this.streamOrStatic.locked || - isReadableStreamDisturbed(this.streamOrStatic); - } - return this.streamOrStatic.consumed; - } - - /** - * @returns {boolean} - */ - consumed() { - if (this.streamOrStatic instanceof ReadableStream) { - return isReadableStreamDisturbed(this.streamOrStatic); - } - return this.streamOrStatic.consumed; - } - - /** - * https://fetch.spec.whatwg.org/#concept-body-consume-body - * @returns {Promise<Uint8Array>} - */ - async consume() { - if (this.unusable()) throw new TypeError("Body already consumed."); - if (this.streamOrStatic instanceof ReadableStream) { - const reader = this.stream.getReader(); - /** @type {Uint8Array[]} */ - const chunks = []; - let totalLength = 0; - while (true) { - const { value: chunk, done } = await reader.read(); - if (done) break; - chunks.push(chunk); - totalLength += chunk.byteLength; - } - const finalBuffer = new Uint8Array(totalLength); - let i = 0; - for (const chunk of chunks) { - finalBuffer.set(chunk, i); - i += chunk.byteLength; - } - return finalBuffer; - } else { - this.streamOrStatic.consumed = true; - return this.streamOrStatic.body; - } - } - - /** - * @returns {InnerBody} - */ - clone() { - const [out1, out2] = this.stream.tee(); - this.streamOrStatic = out1; - const second = new InnerBody(out2); - second.source = core.deserialize(core.serialize(this.source)); - second.length = this.length; - return second; - } - } - - /** - * @param {any} prototype - * @param {symbol} bodySymbol - * @param {symbol} mimeTypeSymbol - * @returns {void} - */ - function mixinBody(prototype, bodySymbol, mimeTypeSymbol) { - function consumeBody(object) { - if (object[bodySymbol] !== null) { - return object[bodySymbol].consume(); - } - return Promise.resolve(new Uint8Array()); - } - - /** @type {PropertyDescriptorMap} */ - const mixin = { - body: { - /** - * @returns {ReadableStream<Uint8Array> | null} - */ - get() { - webidl.assertBranded(this, prototype); - if (this[bodySymbol] === null) { - return null; - } else { - return this[bodySymbol].stream; - } - }, - }, - bodyUsed: { - /** - * @returns {boolean} - */ - get() { - webidl.assertBranded(this, prototype); - if (this[bodySymbol] !== null) { - return this[bodySymbol].consumed(); - } - return false; - }, - }, - arrayBuffer: { - /** @returns {Promise<ArrayBuffer>} */ - value: async function arrayBuffer() { - webidl.assertBranded(this, prototype); - const body = await consumeBody(this); - return packageData(body, "ArrayBuffer"); - }, - }, - blob: { - /** @returns {Promise<Blob>} */ - value: async function blob() { - webidl.assertBranded(this, prototype); - const body = await consumeBody(this); - return packageData(body, "Blob", this[mimeTypeSymbol]); - }, - }, - formData: { - /** @returns {Promise<FormData>} */ - value: async function formData() { - webidl.assertBranded(this, prototype); - const body = await consumeBody(this); - return packageData(body, "FormData", this[mimeTypeSymbol]); - }, - }, - json: { - /** @returns {Promise<any>} */ - value: async function json() { - webidl.assertBranded(this, prototype); - const body = await consumeBody(this); - return packageData(body, "JSON"); - }, - }, - text: { - /** @returns {Promise<string>} */ - value: async function text() { - webidl.assertBranded(this, prototype); - const body = await consumeBody(this); - return packageData(body, "text"); - }, - }, - }; - return Object.defineProperties(prototype.prototype, mixin); - } - - const decoder = new TextDecoder(); - - /** - * https://fetch.spec.whatwg.org/#concept-body-package-data - * @param {Uint8Array} bytes - * @param {"ArrayBuffer" | "Blob" | "FormData" | "JSON" | "text"} type - * @param {MimeType | null} [mimeType] - */ - function packageData(bytes, type, mimeType) { - switch (type) { - case "ArrayBuffer": - return bytes.buffer; - case "Blob": - return new Blob([bytes], { - type: mimeType !== null ? mimesniff.serializeMimeType(mimeType) : "", - }); - case "FormData": { - if (mimeType !== null) { - if (mimeType !== null) { - const essence = mimesniff.essence(mimeType); - if (essence === "multipart/form-data") { - const boundary = mimeType.parameters.get("boundary"); - if (boundary === null) { - throw new TypeError( - "Missing boundary parameter in mime type of multipart formdata.", - ); - } - return parseFormData(bytes, boundary); - } else if (essence === "application/x-www-form-urlencoded") { - const entries = parseUrlEncoded(bytes); - return formDataFromEntries( - entries.map((x) => ({ name: x[0], value: x[1] })), - ); - } - } - throw new TypeError("Invalid form data"); - } - throw new TypeError("Missing content type"); - } - case "JSON": - return JSON.parse(decoder.decode(bytes)); - case "text": - return decoder.decode(bytes); - } - } - - const encoder = new TextEncoder(); - - /** - * @param {BodyInit} object - * @returns {{body: InnerBody, contentType: string | null}} - */ - function extractBody(object) { - /** @type {ReadableStream<Uint8Array> | { body: Uint8Array, consumed: boolean }} */ - let stream; - let source = null; - let length = null; - let contentType = null; - if (object instanceof Blob) { - stream = object.stream(); - source = object; - length = object.size; - if (object.type.length !== 0) { - contentType = object.type; - } - } else if (ArrayBuffer.isView(object) || object instanceof ArrayBuffer) { - const u8 = ArrayBuffer.isView(object) - ? new Uint8Array( - object.buffer, - object.byteOffset, - object.byteLength, - ) - : new Uint8Array(object); - const copy = u8.slice(0, u8.byteLength); - source = copy; - } else if (object instanceof FormData) { - const res = encodeFormData(object); - stream = { body: res.body, consumed: false }; - source = object; - length = res.body.byteLength; - contentType = res.contentType; - } else if (object instanceof URLSearchParams) { - source = encoder.encode(object.toString()); - contentType = "application/x-www-form-urlencoded;charset=UTF-8"; - } else if (typeof object === "string") { - source = encoder.encode(object); - contentType = "text/plain;charset=UTF-8"; - } else if (object instanceof ReadableStream) { - stream = object; - if (object.locked || isReadableStreamDisturbed(object)) { - throw new TypeError("ReadableStream is locked or disturbed"); - } - } - if (source instanceof Uint8Array) { - stream = { body: source, consumed: false }; - length = source.byteLength; - } - const body = new InnerBody(stream); - body.source = source; - body.length = length; - return { body, contentType }; - } - - webidl.converters["BodyInit"] = (V, opts) => { - // Union for (ReadableStream or Blob or ArrayBufferView or ArrayBuffer or FormData or URLSearchParams or USVString) - if (V instanceof ReadableStream) { - // TODO(lucacasonato): ReadableStream is not branded - return V; - } else if (V instanceof Blob) { - return webidl.converters["Blob"](V, opts); - } else if (V instanceof FormData) { - return webidl.converters["FormData"](V, opts); - } else if (V instanceof URLSearchParams) { - // TODO(lucacasonato): URLSearchParams is not branded - return V; - } - if (typeof V === "object") { - if (V instanceof ArrayBuffer || V instanceof SharedArrayBuffer) { - return webidl.converters["ArrayBuffer"](V, opts); - } - if (ArrayBuffer.isView(V)) { - return webidl.converters["ArrayBufferView"](V, opts); - } - } - return webidl.converters["USVString"](V, opts); - }; - webidl.converters["BodyInit?"] = webidl.createNullableConverter( - webidl.converters["BodyInit"], - ); - - window.__bootstrap.fetchBody = { mixinBody, InnerBody, extractBody }; -})(globalThis); |