UNPKG

@web-std/blob

Version:

Web API compatible Blob implementation

1 lines 14 kB
{"version":3,"file":"blob.cjs","sources":["../../src/blob.js"],"sourcesContent":["import { ReadableStream, TextEncoder, TextDecoder } from \"./package.js\"\n\n/**\n * @implements {globalThis.Blob}\n */\nconst WebBlob = class Blob {\n /**\n * @param {BlobPart[]} [init]\n * @param {BlobPropertyBag} [options]\n */\n constructor(init = [], options = {}) {\n /** @type {Uint8Array[]} */\n const parts = []\n\n let size = 0\n for (const part of init) {\n if (typeof part === \"string\") {\n const bytes = new TextEncoder().encode(part)\n parts.push(bytes)\n size += bytes.byteLength\n } else if (part instanceof WebBlob) {\n size += part.size\n // @ts-ignore - `_parts` is marked private so TS will complain about\n // accessing it.\n parts.push(...part._parts)\n } else if (part instanceof ArrayBuffer) {\n parts.push(new Uint8Array(part))\n size += part.byteLength\n } else if (part instanceof Uint8Array) {\n parts.push(part)\n size += part.byteLength\n } else if (ArrayBuffer.isView(part)) {\n const { buffer, byteOffset, byteLength } = part\n parts.push(new Uint8Array(buffer, byteOffset, byteLength))\n size += byteLength\n } else {\n const bytes = new TextEncoder().encode(String(part))\n parts.push(bytes)\n size += bytes.byteLength\n }\n }\n\n /** @private */\n this._size = size\n /** @private */\n this._type = readType(options.type)\n /** @private */\n this._parts = parts\n\n Object.defineProperties(this, {\n _size: { enumerable: false },\n _type: { enumerable: false },\n _parts: { enumerable: false },\n })\n }\n\n /**\n * A string indicating the MIME type of the data contained in the Blob.\n * If the type is unknown, this string is empty.\n * @type {string}\n */\n get type() {\n return this._type\n }\n /**\n * The size, in bytes, of the data contained in the Blob object.\n * @type {number}\n */\n get size() {\n return this._size\n }\n\n /**\n * Returns a new Blob object containing the data in the specified range of\n * bytes of the blob on which it's called.\n * @param {number} [start=0] - An index into the Blob indicating the first\n * byte to include in the new Blob. If you specify a negative value, it's\n * treated as an offset from the end of the Blob toward the beginning. For\n * example, `-10` would be the 10th from last byte in the Blob. The default\n * value is `0`. If you specify a value for start that is larger than the\n * size of the source Blob, the returned Blob has size 0 and contains no\n * data.\n * @param {number} [end] - An index into the `Blob` indicating the first byte\n * that will *not* be included in the new `Blob` (i.e. the byte exactly at\n * this index is not included). If you specify a negative value, it's treated\n * as an offset from the end of the Blob toward the beginning. For example,\n * `-10` would be the 10th from last byte in the `Blob`. The default value is\n * size.\n * @param {string} [type] - The content type to assign to the new Blob;\n * this will be the value of its type property. The default value is an empty\n * string.\n * @returns {Blob}\n */\n slice(start = 0, end = this.size, type = \"\") {\n const { size, _parts } = this\n let offset = start < 0 ? Math.max(size + start, 0) : Math.min(start, size)\n\n let limit = end < 0 ? Math.max(size + end, 0) : Math.min(end, size)\n const span = Math.max(limit - offset, 0)\n const blob = new Blob([], { type })\n\n if (span === 0) {\n return blob\n }\n\n let blobSize = 0\n const blobParts = []\n for (const part of _parts) {\n const { byteLength } = part\n if (offset > 0 && byteLength <= offset) {\n offset -= byteLength\n limit -= byteLength\n } else {\n const chunk = part.subarray(offset, Math.min(byteLength, limit))\n blobParts.push(chunk)\n blobSize += chunk.byteLength\n // no longer need to take that into account\n offset = 0\n\n // don't add the overflow to new blobParts\n if (blobSize >= span) {\n break\n }\n }\n }\n\n blob._parts = blobParts\n blob._size = blobSize\n\n return blob\n }\n\n /**\n * Returns a promise that resolves with an ArrayBuffer containing the entire\n * contents of the Blob as binary data.\n * @returns {Promise<ArrayBuffer>}\n */\n // eslint-disable-next-line require-await\n async arrayBuffer() {\n const buffer = new ArrayBuffer(this.size)\n const bytes = new Uint8Array(buffer)\n let offset = 0\n for (const part of this._parts) {\n bytes.set(part, offset)\n offset += part.byteLength\n }\n return buffer\n }\n\n /**\n * Returns a promise that resolves with a USVString containing the entire\n * contents of the Blob interpreted as UTF-8 text.\n * @returns {Promise<string>}\n */\n // eslint-disable-next-line require-await\n async text() {\n const decoder = new TextDecoder()\n let text = \"\"\n for (const part of this._parts) {\n text += decoder.decode(part)\n }\n return text\n }\n\n /**\n * @returns {BlobStream}\n */\n stream() {\n return new BlobStream(this._parts)\n }\n\n /**\n * @returns {string}\n */\n toString() {\n return \"[object Blob]\"\n }\n\n get [Symbol.toStringTag]() {\n return \"Blob\"\n }\n}\n\n// Marking export as a DOM File object instead of custom class.\n/** @type {typeof globalThis.Blob} */\nconst Blob = WebBlob\n\n/**\n * Blob stream is a `ReadableStream` extension optimized to have minimal\n * overhead when consumed as `AsyncIterable<Uint8Array>`.\n * @extends {ReadableStream<Uint8Array>}\n * @implements {AsyncIterable<Uint8Array>}\n */\nclass BlobStream extends ReadableStream {\n /**\n * @param {Uint8Array[]} chunks\n */\n constructor(chunks) {\n // @ts-ignore\n super(new BlobStreamController(chunks.values()), { type: \"bytes\" })\n /** @private */\n this._chunks = chunks\n }\n\n /**\n * @param {Object} [_options]\n * @property {boolean} [_options.preventCancel]\n * @returns {AsyncIterator<Uint8Array>}\n */\n async *[Symbol.asyncIterator](_options) {\n const reader = this.getReader()\n yield* this._chunks\n reader.releaseLock()\n }\n}\n\nclass BlobStreamController {\n /**\n * @param {Iterator<Uint8Array>} chunks\n */\n constructor(chunks) {\n this.chunks = chunks\n }\n\n /**\n * @param {ReadableStreamDefaultController} controller\n */\n start(controller) {\n this.work(controller)\n this.isWorking = false\n this.isCancelled = false\n }\n /**\n *\n * @param {ReadableStreamDefaultController} controller\n */\n async work(controller) {\n const { chunks } = this\n\n this.isWorking = true\n while (!this.isCancelled && (controller.desiredSize || 0) > 0) {\n let next = null\n try {\n next = chunks.next()\n } catch (error) {\n controller.error(error)\n break\n }\n\n if (next) {\n if (!next.done && !this.isCancelled) {\n controller.enqueue(next.value)\n } else {\n controller.close()\n }\n }\n }\n\n this.isWorking = false\n }\n\n /**\n * @param {ReadableStreamDefaultController} controller\n */\n pull(controller) {\n if (!this.isWorking) {\n this.work(controller)\n }\n }\n cancel() {\n this.isCancelled = true\n }\n}\n\n/**\n * @param {string} [input]\n * @returns {string}\n */\nconst readType = (input = \"\") => {\n const type = String(input).toLowerCase()\n return /[^\\u0020-\\u007E]/.test(type) ? \"\" : type\n}\n\nexport { Blob, ReadableStream, TextEncoder, TextDecoder }\n"],"names":["TextEncoder","TextDecoder","ReadableStream"],"mappings":"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"}