From 06985507c9ce94f238599d17ae70f32fffd90e18 Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Thu, 7 Mar 2024 17:20:53 +0100 Subject: [PATCH 1/4] Remove polyfills and re-exports for built-ins on node >= 18 --- .changeset/itchy-roses-explode.md | 8 + package.json | 7 +- packages/blob/CHANGELOG.md | 54 ---- packages/blob/License.md | 18 -- packages/blob/Readme.md | 75 ------ packages/blob/package.json | 69 ------ packages/blob/rollup.config.js | 17 -- packages/blob/src/blob.js | 284 ---------------------- packages/blob/src/blob.node.js | 20 -- packages/blob/src/lib.js | 4 - packages/blob/src/lib.node.js | 14 -- packages/blob/src/package.js | 2 - packages/blob/test/all.spec.js | 9 - packages/blob/test/blob.spec.js | 227 ----------------- packages/blob/test/fetch.spec.js | 14 -- packages/blob/test/slice.spec.js | 263 -------------------- packages/blob/test/test.js | 13 - packages/blob/test/web.spec.js | 8 - packages/blob/tsconfig.json | 16 -- packages/fetch/package.json | 1 - packages/fetch/src/body.js | 2 +- packages/fetch/src/fetch.js | 4 +- packages/fetch/src/lib.js | 2 +- packages/fetch/src/lib.node.js | 2 +- packages/fetch/src/package.js | 2 +- packages/fetch/src/package.ts | 2 +- packages/fetch/test/form-data.js | 1 - packages/fetch/test/main.js | 3 - packages/fetch/test/request.js | 3 +- packages/fetch/test/response.js | 1 - packages/file/package.json | 3 - packages/file/src/file.js | 6 +- packages/file/src/lib.js | 1 - packages/file/src/lib.node.js | 3 +- packages/file/src/package.js | 1 - packages/file/test/file.spec.js | 2 - packages/file/tsconfig.json | 3 - packages/form-data/package.json | 4 - packages/form-data/test/fetch.spec.js | 1 - packages/form-data/test/form-data.spec.js | 4 +- packages/form-data/tsconfig.json | 8 +- packages/stream/test/lib.spec.cjs | 2 +- packages/stream/test/lib.spec.js | 2 +- yarn.lock | 35 +-- 44 files changed, 27 insertions(+), 1193 deletions(-) create mode 100644 .changeset/itchy-roses-explode.md delete mode 100644 packages/blob/CHANGELOG.md delete mode 100644 packages/blob/License.md delete mode 100644 packages/blob/Readme.md delete mode 100644 packages/blob/package.json delete mode 100644 packages/blob/rollup.config.js delete mode 100644 packages/blob/src/blob.js delete mode 100644 packages/blob/src/blob.node.js delete mode 100644 packages/blob/src/lib.js delete mode 100644 packages/blob/src/lib.node.js delete mode 100644 packages/blob/src/package.js delete mode 100644 packages/blob/test/all.spec.js delete mode 100644 packages/blob/test/blob.spec.js delete mode 100644 packages/blob/test/fetch.spec.js delete mode 100644 packages/blob/test/slice.spec.js delete mode 100644 packages/blob/test/test.js delete mode 100644 packages/blob/test/web.spec.js delete mode 100644 packages/blob/tsconfig.json delete mode 100644 packages/file/src/package.js diff --git a/.changeset/itchy-roses-explode.md b/.changeset/itchy-roses-explode.md new file mode 100644 index 0000000..a45bc15 --- /dev/null +++ b/.changeset/itchy-roses-explode.md @@ -0,0 +1,8 @@ +--- +"@remix-run/web-fetch": major +"@remix-run/web-file": major +"@remix-run/web-form-data": major +"@remix-run/web-stream": major +--- + +Remove polyfills / re-exports for built-ins on node >= 18. This includes but not limited to TextEncoder, TextDecoder and Blob. diff --git a/package.json b/package.json index 5c5d544..8f47c17 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,6 @@ "name": "@remix-run/web-std-io", "private": true, "workspaces": [ - "packages/blob", "packages/file", "packages/form-data", "packages/fetch", @@ -13,13 +12,11 @@ "release": "changeset publish", "version-bump": "changeset version", "postinstall": "manypkg fix", - "prepare": "yarn prepare:blob && yarn prepare:file && yarn prepare:form-data && yarn prepare:fetch", - "prepare:blob": "yarn --cwd packages/blob prepare", + "prepare": "yarn prepare:file && yarn prepare:form-data && yarn prepare:fetch", "prepare:file": "yarn --cwd packages/file prepare", "prepare:form-data": "yarn --cwd packages/form-data prepare", "prepare:fetch": "yarn --cwd packages/fetch prepare", - "test": "yarn test:stream && yarn test:blob && yarn test:file && yarn test:form-data && yarn test:fetch", - "test:blob": "yarn --cwd packages/blob test", + "test": "yarn test:stream && yarn test:file && yarn test:form-data && yarn test:fetch", "test:file": "yarn --cwd packages/file test", "test:form-data": "yarn --cwd packages/form-data test", "test:fetch": "yarn --cwd packages/fetch test", diff --git a/packages/blob/CHANGELOG.md b/packages/blob/CHANGELOG.md deleted file mode 100644 index cd901d9..0000000 --- a/packages/blob/CHANGELOG.md +++ /dev/null @@ -1,54 +0,0 @@ -# Changelog - -## 3.1.0 - -### Minor Changes - -- Export CJS version for browser ([807fc63](https://github.com/remix-run/web-std-io/commit/807fc63)) - -### Patch Changes - -- Updated dependencies - - `@remix-run/web-stream@1.1.0` - -## 3.0.5 - -### Patch Changes - -- 43c6ce2: Move types conditional export to the top of the list to align with [the node guidance](https://nodejs.org/api/packages.html#community-conditions-definitions) -- Updated dependencies [43c6ce2] - - @remix-run/web-stream@1.0.4 - -## [3.0.4](https://www.github.com/web-std/io/compare/blob-v3.0.3...blob-v3.0.4) (2022-02-24) - -### Changes - -- disable node native blob ([#49](https://www.github.com/web-std/io/issues/49)) ([18e426e](https://www.github.com/web-std/io/commit/18e426e0552eb855275faadceab35c41335582f2)) - -## [3.0.3](https://www.github.com/web-std/io/compare/blob-v3.0.2...blob-v3.0.3) (2022-01-21) - -### Changes - -- bump version ([91420e2](https://www.github.com/web-std/io/commit/91420e294b4188a6da9c961ce4ef4eeac93595a1)) - -## [3.0.2](https://www.github.com/web-std/io/compare/blob-v3.0.1...blob-v3.0.2) (2022-01-19) - -### Bug Fixes - -- ship less files to address TSC issues ([#35](https://www.github.com/web-std/io/issues/35)) ([0651e62](https://www.github.com/web-std/io/commit/0651e62ae42d17eae2db89858c9e44f3342c304c)) - -## [3.0.1](https://www.github.com/web-std/io/compare/blob-v3.0.0...blob-v3.0.1) (2021-11-08) - -### Changes - -- align package versions ([09c8676](https://www.github.com/web-std/io/commit/09c8676348619313d9df24d9597cea0eb82704d2)) - -## 3.0.0 (2021-11-05) - -### Features - -- Refactor streams into own subpackage ([#19](https://www.github.com/web-std/io/issues/19)) ([90624cf](https://www.github.com/web-std/io/commit/90624cfd2d4253c2cbc316d092f26e77b5169f47)) - -### Changes - -- bump versions ([#27](https://www.github.com/web-std/io/issues/27)) ([0fe5224](https://www.github.com/web-std/io/commit/0fe5224124e318f560dcfbd8a234d05367c9fbcb)) diff --git a/packages/blob/License.md b/packages/blob/License.md deleted file mode 100644 index 6f69fd5..0000000 --- a/packages/blob/License.md +++ /dev/null @@ -1,18 +0,0 @@ -Copyright 2019 Irakli Gozalishvili. All rights reserved. -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to -deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -sell copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -IN THE SOFTWARE. diff --git a/packages/blob/Readme.md b/packages/blob/Readme.md deleted file mode 100644 index 95252dd..0000000 --- a/packages/blob/Readme.md +++ /dev/null @@ -1,75 +0,0 @@ -# @remix-run/web-blob - -[![ci][ci.icon]][ci.url] -[![package][version.icon] ![downloads][downloads.icon]][package.url] -[![styled with prettier][prettier.icon]][prettier.url] - -Web API compatible [Blob][] for nodejs. - -## Comparison to Alternatives - -#### [fetch-blob][] - -The reason this library exists is because [fetch-blob][] chooses to compromise -Web API compatibility of [`blob.stream()`][w3c blob.stream] by using nodejs -native [Readable][] stream. We found this to be problematic when sharing code -across nodejs and browser runtimes. Instead this library stays true to the -specification by using [ReadableStream][] implementation from [@remix-run/web-stream][] -library even if that is less convenient in nodejs context. - -> Note: Both node [Readable][] streams and web [ReadableStream][] implement -> `AsyncIterable` interface and in theory either could be used with [for await][] -> loops. In practice however major browsers do not yet ship `AsyncIterable` -> support for [ReadableStream][]s which in our experience makes choice made by -> [node-fetch][] impractical. - -[fetch-blob][] is build around node [Buffer][]s. This implementation is built -around standard [Uint8Array][]s. - -[fetch-blob] chooses to use [WeakMap][]s for encapsulating private state. This -library chooses to use to use properties with names that start with `_`. While -those properties aren't truly private they do have better performance profile -and make it possible to interop with this library, which we found impossible -to do with [node-fetch][]. - -### Usage - -```js -import { Blob } from "@remix-run/web-blob" -const blob = new Blob(["hello", new TextEncoder().encode("world")]) -for await (const chunk of blob.stream()) { - console.log(chunk) -} -``` - -### Usage from Typescript - -This library makes use of [typescript using JSDOC annotations][ts-jsdoc] and -also generates type definitions along with typed definition maps. So you should -be able to get all the type inference out of the box. - -## Install - - npm install @remix-run/web-blob - -[ci.icon]: https://github.com/web-std/io/workflows/blob/badge.svg -[ci.url]: https://github.com/web-std/io/actions/workflows/blob.yml -[version.icon]: https://img.shields.io/npm/v/@remix-run/web-blob.svg -[downloads.icon]: https://img.shields.io/npm/dm/@remix-run/web-blob.svg -[package.url]: https://npmjs.org/package/@remix-run/web-blob -[downloads.image]: https://img.shields.io/npm/dm/@remix-run/web-blob.svg -[downloads.url]: https://npmjs.org/package/@remix-run/web-blob -[prettier.icon]: https://img.shields.io/badge/styled_with-prettier-ff69b4.svg -[prettier.url]: https://github.com/prettier/prettier -[blob]: https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob -[fetch-blob]: https://github.com/node-fetch/fetch-blob -[readablestream]: https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream -[readable]: https://nodejs.org/api/stream.html#stream_readable_streams -[w3c blob.stream]: https://w3c.github.io/FileAPI/#dom-blob-stream -[@remix-run/web-stream]: https://github.com/web-std/io/tree/main/stream -[for await]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of -[buffer]: https://nodejs.org/api/buffer.html -[weakmap]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap -[ts-jsdoc]: https://www.typescriptlang.org/docs/handbook/jsdoc-supported-types.html -[uint8array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array -[node-fetch]: https://github.com/node-fetch/ diff --git a/packages/blob/package.json b/packages/blob/package.json deleted file mode 100644 index 089009e..0000000 --- a/packages/blob/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "@remix-run/web-blob", - "version": "3.1.0", - "description": "Web API compatible Blob implementation", - "keywords": [ - "blob", - "typed" - ], - "files": [ - "src", - "dist/src", - "License.md", - "Readme.md" - ], - "type": "module", - "module": "./src/lib.js", - "main": "./dist/src/lib.node.cjs", - "types": "./dist/src/lib.d.ts", - "exports": { - ".": { - "types": "./dist/src/lib.d.ts", - "browser": { - "require": "./dist/src/lib.cjs", - "import": "./src/lib.js" - }, - "require": "./dist/src/lib.node.cjs", - "import": "./src/lib.node.js" - } - }, - "dependencies": { - "@remix-run/web-stream": "^1.1.0", - "web-encoding": "1.1.5" - }, - "author": "Irakli Gozalishvili (https://gozala.io)", - "repository": "https://github.com/remix-run/web-std-io", - "license": "MIT", - "devDependencies": { - "@remix-run/web-fetch": "^4.4.2-pre.0", - "@types/node": "15.0.2", - "git-validate": "2.2.4", - "husky": "^6.0.0", - "lint-staged": "^11.0.0", - "playwright-test": "^7.2.0", - "prettier": "^2.3.0", - "rimraf": "3.0.2", - "rollup": "2.47.0", - "rollup-plugin-multi-input": "1.2.0", - "typescript": "^4.4.4", - "uvu": "0.5.2" - }, - "scripts": { - "typecheck": "tsc", - "build": "npm run build:cjs && npm run build:types", - "build:cjs": "rollup --config rollup.config.js", - "build:types": "tsc --build", - "prepare": "npm run build", - "test:es": "uvu test all.spec.js", - "test:web": "playwright-test -r uvu test/web.spec.js", - "test:cjs": "rimraf dist && npm run build && node dist/test/all.spec.cjs", - "test": "npm run test:es && npm run test:web && npm run test:cjs", - "precommit": "lint-staged" - }, - "lint-staged": { - "*.js": [ - "prettier --no-semi --write", - "git add" - ] - } -} diff --git a/packages/blob/rollup.config.js b/packages/blob/rollup.config.js deleted file mode 100644 index 5c8b019..0000000 --- a/packages/blob/rollup.config.js +++ /dev/null @@ -1,17 +0,0 @@ -import multiInput from "rollup-plugin-multi-input" - -const config = [ - ["test", "dist/test"], - ["src", "dist/src"], -].map(([base, dest]) => ({ - input: [`${base}/**/*.js`], - output: { - dir: dest, - preserveModules: true, - sourcemap: true, - format: "cjs", - entryFileNames: "[name].cjs", - }, - plugins: [multiInput({ relative: base })], -})) -export default config diff --git a/packages/blob/src/blob.js b/packages/blob/src/blob.js deleted file mode 100644 index aa55ae8..0000000 --- a/packages/blob/src/blob.js +++ /dev/null @@ -1,284 +0,0 @@ -import { ReadableStream, TextEncoder, TextDecoder } from "./package.js" - -/** - * @implements {globalThis.Blob} - */ -const WebBlob = class Blob { - /** - * @param {BlobPart[]} [init] - * @param {BlobPropertyBag} [options] - */ - constructor(init = [], options = {}) { - /** @type {Uint8Array[]} */ - const parts = [] - - let size = 0 - for (const part of init) { - if (typeof part === "string") { - const bytes = new TextEncoder().encode(part) - parts.push(bytes) - size += bytes.byteLength - } else if (part instanceof WebBlob) { - size += part.size - // @ts-ignore - `_parts` is marked private so TS will complain about - // accessing it. - parts.push(...part._parts) - } else if (part instanceof ArrayBuffer) { - parts.push(new Uint8Array(part)) - size += part.byteLength - } else if (part instanceof Uint8Array) { - parts.push(part) - size += part.byteLength - } else if (ArrayBuffer.isView(part)) { - const { buffer, byteOffset, byteLength } = part - parts.push(new Uint8Array(buffer, byteOffset, byteLength)) - size += byteLength - } else { - const bytes = new TextEncoder().encode(String(part)) - parts.push(bytes) - size += bytes.byteLength - } - } - - /** @private */ - this._size = size - /** @private */ - this._type = readType(options.type) - /** @private */ - this._parts = parts - - Object.defineProperties(this, { - _size: { enumerable: false }, - _type: { enumerable: false }, - _parts: { enumerable: false }, - }) - } - - /** - * A string indicating the MIME type of the data contained in the Blob. - * If the type is unknown, this string is empty. - * @type {string} - */ - get type() { - return this._type - } - /** - * The size, in bytes, of the data contained in the Blob object. - * @type {number} - */ - get size() { - return this._size - } - - /** - * Returns a new Blob object containing the data in the specified range of - * bytes of the blob on which it's called. - * @param {number} [start=0] - An index into the Blob indicating the first - * byte to include in the new Blob. If you specify a negative value, it's - * treated as an offset from the end of the Blob toward the beginning. For - * example, `-10` would be the 10th from last byte in the Blob. The default - * value is `0`. If you specify a value for start that is larger than the - * size of the source Blob, the returned Blob has size 0 and contains no - * data. - * @param {number} [end] - An index into the `Blob` indicating the first byte - * that will *not* be included in the new `Blob` (i.e. the byte exactly at - * this index is not included). If you specify a negative value, it's treated - * as an offset from the end of the Blob toward the beginning. For example, - * `-10` would be the 10th from last byte in the `Blob`. The default value is - * size. - * @param {string} [type] - The content type to assign to the new Blob; - * this will be the value of its type property. The default value is an empty - * string. - * @returns {Blob} - */ - slice(start = 0, end = this.size, type = "") { - const { size, _parts } = this - let offset = start < 0 ? Math.max(size + start, 0) : Math.min(start, size) - - let limit = end < 0 ? Math.max(size + end, 0) : Math.min(end, size) - const span = Math.max(limit - offset, 0) - const blob = new Blob([], { type }) - - if (span === 0) { - return blob - } - - let blobSize = 0 - const blobParts = [] - for (const part of _parts) { - const { byteLength } = part - if (offset > 0 && byteLength <= offset) { - offset -= byteLength - limit -= byteLength - } else { - const chunk = part.subarray(offset, Math.min(byteLength, limit)) - blobParts.push(chunk) - blobSize += chunk.byteLength - // no longer need to take that into account - offset = 0 - - // don't add the overflow to new blobParts - if (blobSize >= span) { - break - } - } - } - - blob._parts = blobParts - blob._size = blobSize - - return blob - } - - /** - * Returns a promise that resolves with an ArrayBuffer containing the entire - * contents of the Blob as binary data. - * @returns {Promise} - */ - // eslint-disable-next-line require-await - async arrayBuffer() { - const buffer = new ArrayBuffer(this.size) - const bytes = new Uint8Array(buffer) - let offset = 0 - for (const part of this._parts) { - bytes.set(part, offset) - offset += part.byteLength - } - return buffer - } - - /** - * Returns a promise that resolves with a USVString containing the entire - * contents of the Blob interpreted as UTF-8 text. - * @returns {Promise} - */ - // eslint-disable-next-line require-await - async text() { - const decoder = new TextDecoder() - let text = "" - for (const part of this._parts) { - text += decoder.decode(part) - } - return text - } - - /** - * @returns {BlobStream} - */ - stream() { - return new BlobStream(this._parts) - } - - /** - * @returns {string} - */ - toString() { - return "[object Blob]" - } - - get [Symbol.toStringTag]() { - return "Blob" - } -} - -// Marking export as a DOM File object instead of custom class. -/** @type {typeof globalThis.Blob} */ -const Blob = WebBlob - -/** - * Blob stream is a `ReadableStream` extension optimized to have minimal - * overhead when consumed as `AsyncIterable`. - * @extends {ReadableStream} - * @implements {AsyncIterable} - */ -class BlobStream extends ReadableStream { - /** - * @param {Uint8Array[]} chunks - */ - constructor(chunks) { - // @ts-ignore - super(new BlobStreamController(chunks.values()), { type: "bytes" }) - /** @private */ - this._chunks = chunks - } - - /** - * @param {Object} [_options] - * @property {boolean} [_options.preventCancel] - * @returns {AsyncIterator} - */ - async *[Symbol.asyncIterator](_options) { - const reader = this.getReader() - yield* this._chunks - reader.releaseLock() - } -} - -class BlobStreamController { - /** - * @param {Iterator} chunks - */ - constructor(chunks) { - this.chunks = chunks - } - - /** - * @param {ReadableStreamDefaultController} controller - */ - start(controller) { - this.work(controller) - this.isWorking = false - this.isCancelled = false - } - /** - * - * @param {ReadableStreamDefaultController} controller - */ - async work(controller) { - const { chunks } = this - - this.isWorking = true - while (!this.isCancelled && (controller.desiredSize || 0) > 0) { - let next = null - try { - next = chunks.next() - } catch (error) { - controller.error(error) - break - } - - if (next) { - if (!next.done && !this.isCancelled) { - controller.enqueue(next.value) - } else { - controller.close() - } - } - } - - this.isWorking = false - } - - /** - * @param {ReadableStreamDefaultController} controller - */ - pull(controller) { - if (!this.isWorking) { - this.work(controller) - } - } - cancel() { - this.isCancelled = true - } -} - -/** - * @param {string} [input] - * @returns {string} - */ -const readType = (input = "") => { - const type = String(input).toLowerCase() - return /[^\u0020-\u007E]/.test(type) ? "" : type -} - -export { Blob, ReadableStream, TextEncoder, TextDecoder } diff --git a/packages/blob/src/blob.node.js b/packages/blob/src/blob.node.js deleted file mode 100644 index c9dd807..0000000 --- a/packages/blob/src/blob.node.js +++ /dev/null @@ -1,20 +0,0 @@ -import * as builtin from "buffer" - -/** - * @returns {typeof globalThis.Blob|null} - */ -const use = () => { - try { - // @ts-ignore - const { Blob } = builtin - const view = new Uint16Array(1) - // Checks if critical issue with node implementation of Blob is fixed - // @see https://github.com/nodejs/node/issues/40705 - const isBugFixed = new Blob([view]).size === view.byteLength - return isBugFixed ? Blob : null - } catch (error) { - return null - } -} - -export const Blob = use() diff --git a/packages/blob/src/lib.js b/packages/blob/src/lib.js deleted file mode 100644 index 355a378..0000000 --- a/packages/blob/src/lib.js +++ /dev/null @@ -1,4 +0,0 @@ -export { TextEncoder, TextDecoder, ReadableStream } from "./package.js" - -// On the web we just export native Blob implementation -export const { Blob } = globalThis diff --git a/packages/blob/src/lib.node.js b/packages/blob/src/lib.node.js deleted file mode 100644 index 0290076..0000000 --- a/packages/blob/src/lib.node.js +++ /dev/null @@ -1,14 +0,0 @@ -export { TextEncoder, TextDecoder, ReadableStream } from "./package.js" -// import { Blob as NodeBlob } from "./blob.node.js" -import { Blob as WebBlob } from "./blob.js" - -/** @type {typeof globalThis.Blob} */ -// Our first choise is to use global `Blob` because it may be available e.g. in -// electron renderrer process. If not available fall back to node native -// implementation, if also not available use our implementation. -export const Blob = - globalThis.Blob || - // Disable node native blob until impractical perf issue is fixed - // @see https://github.com/nodejs/node/issues/42108 - // NodeBlob || - WebBlob diff --git a/packages/blob/src/package.js b/packages/blob/src/package.js deleted file mode 100644 index 0211145..0000000 --- a/packages/blob/src/package.js +++ /dev/null @@ -1,2 +0,0 @@ -export { TextEncoder, TextDecoder } from "web-encoding" -export { ReadableStream } from "@remix-run/web-stream" diff --git a/packages/blob/test/all.spec.js b/packages/blob/test/all.spec.js deleted file mode 100644 index c1152b8..0000000 --- a/packages/blob/test/all.spec.js +++ /dev/null @@ -1,9 +0,0 @@ -import { test as blobTest } from "./blob.spec.js" -import { test as sliceTest } from "./slice.spec.js" -import { test as fetchTest } from "./fetch.spec.js" -import { test } from "./test.js" - -blobTest(test) -sliceTest(test) -fetchTest(test) -test.run() diff --git a/packages/blob/test/blob.spec.js b/packages/blob/test/blob.spec.js deleted file mode 100644 index 10ebc06..0000000 --- a/packages/blob/test/blob.spec.js +++ /dev/null @@ -1,227 +0,0 @@ -import { Blob, TextDecoder } from "@remix-run/web-blob" -import * as lib from "@remix-run/web-blob" -import { assert } from "./test.js" - -/** - * @param {import('./test').Test} test - */ -export const test = test => { - test("test baisc", async () => { - assert.isEqual(typeof lib.Blob, "function") - assert.isEqual(typeof lib.TextDecoder, "function") - assert.isEqual(typeof lib.TextEncoder, "function") - assert.isEqual(typeof lib.ReadableStream, "function") - }) - - if (globalThis.window === globalThis) { - test("exports built-ins", () => { - assert.equal(lib.Blob, globalThis.Blob) - assert.equal(lib.TextDecoder, globalThis.TextDecoder) - assert.equal(lib.TextEncoder, globalThis.TextEncoder) - assert.equal(lib.ReadableStream, globalThis.ReadableStream) - }) - } - - test("test jsdom", async () => { - const blob = new Blob(["TEST"]) - assert.isEqual(blob.size, 4, "Initial blob should have a size of 4") - }) - - test("should encode a blob with proper size when given two strings as arguments", async () => { - const blob = new Blob(["hi", "hello"]) - assert.isEqual(blob.size, 7) - }) - - test("should encode arraybuffers with right content", async () => { - const bytes = new Uint8Array(5) - for (let i = 0; i < 5; i++) bytes[i] = i - const blob = new Blob([bytes.buffer]) - const buffer = await blob.arrayBuffer() - const result = new Uint8Array(buffer) - for (let i = 0; i < 5; i++) { - assert.isEqual(result[i], i) - } - }) - - test("should encode typed arrays with right content", async () => { - const bytes = new Uint8Array(5) - for (let i = 0; i < 5; i++) bytes[i] = i - const blob = new Blob([bytes]) - - const buffer = await blob.arrayBuffer() - const result = new Uint8Array(buffer) - - for (let i = 0; i < 5; i++) { - assert.isEqual(result[i], i) - } - }) - - test("should encode sliced typed arrays with right content", async () => { - const bytes = new Uint8Array(5) - for (let i = 0; i < 5; i++) bytes[i] = i - const blob = new Blob([bytes.subarray(2)]) - - const buffer = await blob.arrayBuffer() - const result = new Uint8Array(buffer) - for (let i = 0; i < 3; i++) { - assert.isEqual(result[i], i + 2) - } - }) - - test("should encode with blobs", async () => { - const bytes = new Uint8Array(5) - for (let i = 0; i < 5; i++) bytes[i] = i - const blob = new Blob([new Blob([bytes.buffer])]) - const buffer = await blob.arrayBuffer() - const result = new Uint8Array(buffer) - for (let i = 0; i < 5; i++) { - assert.isEqual(result[i], i) - } - }) - - test("should enode mixed contents to right size", async () => { - const bytes = new Uint8Array(5) - for (let i = 0; i < 5; i++) { - bytes[i] = i - } - const blob = new Blob([bytes.buffer, "hello"]) - assert.isEqual(blob.size, 10) - }) - - test("should accept mime type", async () => { - const blob = new Blob(["hi", "hello"], { type: "text/html" }) - assert.isEqual(blob.type, "text/html") - }) - - test("should be an instance of constructor", async () => { - const blob = new Blob(["hi"]) - assert.equal(blob instanceof Blob, true) - }) - - test("from text", async () => { - const blob = new Blob(["hello"]) - assert.isEqual(blob.size, 5, "is right size") - assert.isEqual(blob.type, "", "type is empty") - assert.isEqual(await blob.text(), "hello", "reads as text") - assert.isEquivalent( - new Uint8Array(await blob.arrayBuffer()), - new Uint8Array("hello".split("").map(char => char.charCodeAt(0))) - ) - }) - - test("from text with type", async () => { - const blob = new Blob(["hello"], { type: "text/markdown" }) - assert.isEqual(blob.size, 5, "is right size") - assert.isEqual(blob.type, "text/markdown", "type is set") - assert.isEqual(await blob.text(), "hello", "reads as text") - - assert.isEquivalent( - new Uint8Array(await blob.arrayBuffer()), - new Uint8Array("hello".split("").map(char => char.charCodeAt(0))) - ) - }) - - test("empty blob", async () => { - const blob = new Blob([]) - assert.isEqual(blob.size, 0, "size is 0") - assert.isEqual(blob.type, "", "type is empty") - assert.isEqual(await blob.text(), "", "reads as text") - assert.isEquivalent( - await blob.arrayBuffer(), - new ArrayBuffer(0), - "returns empty buffer" - ) - }) - - test("no args", async () => { - const blob = new Blob() - assert.isEqual(blob.size, 0, "size is 0") - assert.isEqual(blob.type, "", "type is empty") - assert.isEqual(await blob.text(), "", "reads as text") - assert.isEquivalent( - await blob.arrayBuffer(), - new ArrayBuffer(0), - "returns empty buffer" - ) - }) - - test("all emtpy args", async () => { - const blob = new Blob([ - "", - new Blob(), - "", - new Uint8Array(0), - new ArrayBuffer(0), - ]) - assert.isEqual(blob.size, 0, "size is 0") - assert.isEqual(blob.type, "", "type is empty") - assert.isEqual(await blob.text(), "", "reads as text") - assert.isEquivalent( - await blob.arrayBuffer(), - new ArrayBuffer(0), - "returns empty buffer" - ) - }) - - test("combined blob", async () => { - const uint8 = new Uint8Array([1, 2, 3]) - const uint16 = new Uint16Array([8, 190]) - const float32 = new Float32Array([5.4, 9, 1.5]) - const string = "hello world" - const blob = new Blob([uint8, uint16, float32, string]) - - const b8 = blob.slice(0, uint8.byteLength) - const r8 = new Uint8Array(await b8.arrayBuffer()) - assert.isEquivalent(uint8, r8) - - const b16 = blob.slice( - uint8.byteLength, - uint8.byteLength + uint16.byteLength - ) - const r16 = new Uint16Array(await b16.arrayBuffer()) - assert.isEquivalent(uint16, r16) - - const b32 = blob.slice( - uint8.byteLength + uint16.byteLength, - uint8.byteLength + uint16.byteLength + float32.byteLength - ) - const r32 = new Float32Array(await b32.arrayBuffer()) - assert.isEquivalent(float32, r32) - - const bs = blob.slice( - uint8.byteLength + uint16.byteLength + float32.byteLength - ) - assert.isEqual(string, await bs.text()) - - assert.isEqual("wo", await bs.slice(6, 8).text()) - assert.isEqual("world", await bs.slice(6).text()) - assert.isEqual("world", await blob.slice(-5).text()) - }) - - test("emoji", async () => { - const emojis = `👍🤷🎉😤` - const blob = new Blob([emojis]) - const nestle = new Blob([new Blob([blob, blob])]) - assert.isEqual(emojis + emojis, await nestle.text()) - }) - - test("streams", async () => { - const blob = new Blob(["hello", " ", "world"], { type: "text/plain" }) - const stream = blob.stream() - - const reader = stream.getReader() - const chunks = [] - while (true) { - const { done, value } = await reader.read() - if (done) { - break - } - - if (value != null) { - chunks.push(new TextDecoder().decode(value)) - } - } - - assert.deepEqual("hello world", chunks.join("")) - }) -} diff --git a/packages/blob/test/fetch.spec.js b/packages/blob/test/fetch.spec.js deleted file mode 100644 index 08a0e48..0000000 --- a/packages/blob/test/fetch.spec.js +++ /dev/null @@ -1,14 +0,0 @@ -import { Response } from "@remix-run/web-fetch" -import { Blob } from "@remix-run/web-blob" -import { assert } from "./test.js" - -/** - * @param {import('./test').Test} test - */ -export const test = test => { - test("nodefetch recognizes blobs", async () => { - const response = new Response(new Blob(["hello"])) - - assert.equal(await response.text(), "hello") - }) -} diff --git a/packages/blob/test/slice.spec.js b/packages/blob/test/slice.spec.js deleted file mode 100644 index ae086e7..0000000 --- a/packages/blob/test/slice.spec.js +++ /dev/null @@ -1,263 +0,0 @@ -import { Blob, TextEncoder } from "@remix-run/web-blob" -import { assert } from "./test.js" - -/** - * - * @param {Blob} blob - * @param {Object} expected - * @param {number} expected.size - * @param {string} [expected.type] - * @param {Uint8Array[]} expected.content - */ -const assertBlob = async (blob, expected) => { - assert.equal(blob instanceof Blob, true, "blob is instanceof Blob") - assert.equal(String(blob), "[object Blob]", "String(blob) -> [object Blob]") - assert.equal( - blob.toString(), - "[object Blob]", - "blob.toString() -> [object Blob]" - ) - assert.equal(blob.size, expected.size, `blob.size == ${expected.size}`) - assert.equal(blob.type, expected.type || "", "blob.type") - - const chunks = [] - // @ts-ignore - https://github.com/microsoft/TypeScript/issues/29867 - const stream = blob.stream() - const reader = stream.getReader() - while (true) { - const chunk = await reader.read() - if (chunk.done) { - reader.releaseLock() - break - } else { - chunks.push(chunk.value) - } - } - - assert.deepEqual( - concatUint8Array(chunks), - concatUint8Array(expected.content), - "blob.stream() matches expectation" - ) - - let text = "" - const encoder = new TextDecoder() - for (const chunk of expected.content) { - text += encoder.decode(chunk) - } - - assert.deepEqual( - await blob.text(), - text, - "blob.text() produces expected text" - ) - - // Not all browsers implement this - const bytes = concatUint8Array(expected.content) - const buffer = await blob.arrayBuffer() - assert.equal(buffer instanceof ArrayBuffer, true) - assert.deepEqual(buffer, bytes.buffer) - assert.deepEqual( - new Uint8Array(buffer), - bytes, - "blob.arrayBuffer() produces expected buffer" - ) -} - -/** - * @param {Uint8Array[]} chunks - */ -const concatUint8Array = chunks => { - const bytes = [] - for (const chunk of chunks) { - bytes.push(...chunk) - } - return new Uint8Array(bytes) -} - -/** - * @param {*} input - * @returns {Uint8Array} - */ -const toUint8Array = input => { - if (typeof input === "string") { - return new TextEncoder().encode(input) - } else if (input instanceof ArrayBuffer) { - return new Uint8Array(input) - } else if (input instanceof Uint8Array) { - return input - } else if (ArrayBuffer.isView(input)) { - return new Uint8Array(input.buffer, input.byteOffset, input.byteLength) - } else { - throw new TypeError(`Invalid input ${input}`) - } -} - -/** - * @param {import('./test').Test} test - */ -export const test = test => { - test("new Blob()", async () => { - const blob = new Blob() - - await assertBlob(blob, { - type: "", - size: 0, - content: [], - }) - }) - - test('new Blob("a=1")', async () => { - const data = "a=1" - const blob = new Blob([data]) - - await assertBlob(blob, { - size: 3, - type: "", - content: [toUint8Array(data)], - }) - }) - - test("Blob with mixed parts", async () => { - const parts = [ - "a", - new Uint8Array([98]), - new Uint16Array([25699]), - new Uint8Array([101]).buffer, - new TextEncoder().encode("f"), - new Blob(["g"]), - ] - - await assertBlob(new Blob(parts), { - size: 7, - content: [...parts.slice(0, -1).map(toUint8Array), toUint8Array("g")], - }) - }) - - test("Blob slice", async () => { - const parts = ["hello ", "world"] - const blob = new Blob(parts) - - await assertBlob(blob, { - size: 11, - content: parts.map(toUint8Array), - }) - - assertBlob(blob.slice(), { - size: 11, - content: parts.map(toUint8Array), - }) - - assertBlob(blob.slice(2), { - size: 9, - content: [toUint8Array("llo "), toUint8Array("world")], - }) - - assertBlob(blob.slice(5), { - size: 6, - content: [toUint8Array(" "), toUint8Array("world")], - }) - - assertBlob(blob.slice(6), { - size: 5, - content: [toUint8Array("world")], - }) - - assertBlob(blob.slice(5, 100), { - size: 6, - content: [toUint8Array(" "), toUint8Array("world")], - }) - - assertBlob(blob.slice(-5), { - size: 5, - content: [toUint8Array("world")], - }) - - assertBlob(blob.slice(-5, -10), { - size: 0, - content: [], - }) - - assertBlob(blob.slice(-5, -2), { - size: 3, - content: [toUint8Array("wor")], - }) - - assertBlob(blob.slice(-5, 11), { - size: 5, - content: [toUint8Array("world")], - }) - - assertBlob(blob.slice(-5, 12), { - size: 5, - content: [toUint8Array("world")], - }) - - assertBlob(blob.slice(-5, 10), { - size: 4, - content: [toUint8Array("worl")], - }) - }) - - test("Blob type", async () => { - const type = "text/plain" - const blob = new Blob([], { type }) - await assertBlob(blob, { size: 0, type, content: [] }) - }) - - test("Blob slice type", async () => { - const type = "text/plain" - const blob = new Blob().slice(0, 0, type) - await assertBlob(blob, { size: 0, type, content: [] }) - }) - - test("invalid Blob type", async () => { - const blob = new Blob([], { type: "\u001Ftext/plain" }) - await assertBlob(blob, { size: 0, type: "", content: [] }) - }) - - test("invalid Blob slice type", async () => { - const blob = new Blob().slice(0, 0, "\u001Ftext/plain") - await assertBlob(blob, { size: 0, type: "", content: [] }) - }) - - test("normalized Blob type", async () => { - const blob = new Blob().slice(0, 0, "text/Plain") - await assertBlob(blob, { size: 0, type: "text/plain", content: [] }) - }) - - test("Blob slice(0, 1)", async () => { - const data = "abcdefgh" - const blob = new Blob([data]).slice(0, 1) - await assertBlob(blob, { - size: 1, - content: [toUint8Array("a")], - }) - }) - - test("Blob slice(-1)", async () => { - const data = "abcdefgh" - const blob = new Blob([data]).slice(-1) - await assertBlob(blob, { - size: 1, - content: [toUint8Array("h")], - }) - }) - - test("Blob slice(0, -1)", async () => { - const data = "abcdefgh" - const blob = new Blob([data]).slice(0, -1) - await assertBlob(blob, { - size: 7, - content: [toUint8Array("abcdefg")], - }) - }) - - test("blob.slice(1, 2)", async () => { - const blob = new Blob(["a", "b", "c"]).slice(1, 2) - await assertBlob(blob, { - size: 1, - content: [toUint8Array("b")], - }) - }) -} diff --git a/packages/blob/test/test.js b/packages/blob/test/test.js deleted file mode 100644 index 69eb734..0000000 --- a/packages/blob/test/test.js +++ /dev/null @@ -1,13 +0,0 @@ -import * as uvu from "uvu" -import * as uvuassert from "uvu/assert" - -const deepEqual = uvuassert.equal -const isEqual = uvuassert.equal -const isEquivalent = uvuassert.equal -export const assert = { ...uvuassert, deepEqual, isEqual, isEquivalent } -export const test = uvu.test - - -/** - * @typedef {uvu.Test} Test - */ diff --git a/packages/blob/test/web.spec.js b/packages/blob/test/web.spec.js deleted file mode 100644 index 97d871e..0000000 --- a/packages/blob/test/web.spec.js +++ /dev/null @@ -1,8 +0,0 @@ -import { test as blobTest } from "./blob.spec.js" -import { test as sliceTest } from "./slice.spec.js" -import { test } from "./test.js" - -blobTest(test) -sliceTest(test) - -test.run() diff --git a/packages/blob/tsconfig.json b/packages/blob/tsconfig.json deleted file mode 100644 index 5695f02..0000000 --- a/packages/blob/tsconfig.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "outDir": "dist", - "paths": { - "@remix-run/web-blob": ["packages/blob/src/lib.js"] - } - }, - "include": [ - "src", - "test" - ], - "references": [ - { "path": "../fetch"} - ] -} diff --git a/packages/fetch/package.json b/packages/fetch/package.json index 1b6a3bb..b938a63 100644 --- a/packages/fetch/package.json +++ b/packages/fetch/package.json @@ -100,7 +100,6 @@ "xo": "^0.33.1" }, "dependencies": { - "@remix-run/web-blob": "^3.1.0", "@remix-run/web-file": "^3.1.0", "@remix-run/web-form-data": "^3.1.0", "@remix-run/web-stream": "^1.1.0", diff --git a/packages/fetch/src/body.js b/packages/fetch/src/body.js index 2b7a373..dc7c400 100644 --- a/packages/fetch/src/body.js +++ b/packages/fetch/src/body.js @@ -8,7 +8,7 @@ import Stream from 'stream'; import {types} from 'util'; -import {Blob, ReadableStream} from './package.js'; +import {ReadableStream} from './package.js'; import {FetchError} from './errors/fetch-error.js'; import {FetchBaseError} from './errors/base.js'; diff --git a/packages/fetch/src/fetch.js b/packages/fetch/src/fetch.js index 8ced217..69b20b3 100644 --- a/packages/fetch/src/fetch.js +++ b/packages/fetch/src/fetch.js @@ -23,10 +23,10 @@ import {AbortError} from './errors/abort-error.js'; import {isRedirect} from './utils/is-redirect.js'; import {pipeline as pump, PassThrough} from 'stream'; import * as Stream from 'stream'; -import { ReadableStream, Blob, FormData } from './package.js'; +import { ReadableStream, FormData } from './package.js'; -export {Headers, Request, Response, ReadableStream, Blob, FormData}; +export {Headers, Request, Response, ReadableStream, FormData}; const supportedSchemas = new Set(['data:', 'http:', 'https:', 'file:']); diff --git a/packages/fetch/src/lib.js b/packages/fetch/src/lib.js index a5aa83e..17f0996 100644 --- a/packages/fetch/src/lib.js +++ b/packages/fetch/src/lib.js @@ -1,4 +1,4 @@ // On the web we just export native fetch implementation -export { ReadableStream, Blob, FormData, File } from './package.js'; +export { ReadableStream, FormData, File } from './package.js'; export const { Headers, Request, Response } = globalThis; export default globalThis.fetch.bind(globalThis) diff --git a/packages/fetch/src/lib.node.js b/packages/fetch/src/lib.node.js index 062b92e..4f67877 100644 --- a/packages/fetch/src/lib.node.js +++ b/packages/fetch/src/lib.node.js @@ -1,5 +1,5 @@ export { default, fetch, Headers, Request, Response } from "./fetch.js"; -export { ReadableStream, Blob, FormData, File } from './package.js'; +export { ReadableStream, FormData, File } from './package.js'; // Node 18+ introduces fetch API globally and it doesn't support our use-cases yet. // For now we always use the polyfill. diff --git a/packages/fetch/src/package.js b/packages/fetch/src/package.js index 60d7378..8fa4730 100644 --- a/packages/fetch/src/package.js +++ b/packages/fetch/src/package.js @@ -1,5 +1,5 @@ -export { Blob, ReadableStream } from '@remix-run/web-blob' +export { ReadableStream } from '@remix-run/web-stream' export { File } from '@remix-run/web-file' export { FormData } from '@remix-run/web-form-data' diff --git a/packages/fetch/src/package.ts b/packages/fetch/src/package.ts index ee39622..8a63295 100644 --- a/packages/fetch/src/package.ts +++ b/packages/fetch/src/package.ts @@ -1,4 +1,4 @@ -export const { FormData, Blob, File } = globalThis +export const { FormData, File } = globalThis export { ReadableStream } from "@remix-run/web-stream" diff --git a/packages/fetch/test/form-data.js b/packages/fetch/test/form-data.js index 199444b..d79b920 100644 --- a/packages/fetch/test/form-data.js +++ b/packages/fetch/test/form-data.js @@ -1,5 +1,4 @@ import FormData from 'formdata-node'; -import {Blob} from '@remix-run/web-blob'; import chai from 'chai'; diff --git a/packages/fetch/test/main.js b/packages/fetch/test/main.js index 610faff..4f61f35 100644 --- a/packages/fetch/test/main.js +++ b/packages/fetch/test/main.js @@ -20,9 +20,6 @@ import abortControllerPolyfill from "abortcontroller-polyfill/dist/abortcontroll import { ReadableStream } from "../src/package.js"; const AbortControllerPolyfill = abortControllerPolyfill.AbortController; -// Test subjects -import { Blob } from "@remix-run/web-file"; - import fetch, { Headers, Request, Response } from "@remix-run/web-fetch"; import { FetchError } from "../src/errors/fetch-error.js"; import HeadersOrig, { fromRawHeaders } from "../src/headers.js"; diff --git a/packages/fetch/test/request.js b/packages/fetch/test/request.js index bf85b76..7ed6685 100644 --- a/packages/fetch/test/request.js +++ b/packages/fetch/test/request.js @@ -4,7 +4,6 @@ import {TextEncoder} from 'util'; import AbortController from 'abort-controller'; import chai from 'chai'; import FormData from 'form-data'; -import {Blob} from '@remix-run/web-fetch'; import { ReadableStream } from '@remix-run/web-fetch'; import TestServer from './utils/server.js'; @@ -481,7 +480,7 @@ describe('Request', () => { return clonedRequest.formData().then(async clonedFormData => { expect(clonedFormData.get('a')).to.equal("1"); const file = clonedFormData.get('file'); - expect(file.name).to.equal(""); + expect(file.name).to. equal(""); expect(file.type).to.equal("application/octet-stream"); expect(file.size).to.equal(0); }); diff --git a/packages/fetch/test/response.js b/packages/fetch/test/response.js index b4c2957..100d5e1 100644 --- a/packages/fetch/test/response.js +++ b/packages/fetch/test/response.js @@ -1,7 +1,6 @@ import {TextEncoder} from 'util'; import chai from 'chai'; -import {Blob} from '@remix-run/web-blob'; import {Response} from '@remix-run/web-fetch'; import TestServer from './utils/server.js'; import { ReadableStream } from '../src/package.js'; diff --git a/packages/file/package.json b/packages/file/package.json index 74fa2fc..b92dd10 100644 --- a/packages/file/package.json +++ b/packages/file/package.json @@ -32,9 +32,6 @@ "node": "./src/lib.node.js" } }, - "dependencies": { - "@remix-run/web-blob": "^3.1.0" - }, "author": "Irakli Gozalishvili (https://gozala.io)", "repository": "https://github.com/remix-run/web-std-io", "license": "MIT", diff --git a/packages/file/src/file.js b/packages/file/src/file.js index b5ee1e3..65d1bd9 100644 --- a/packages/file/src/file.js +++ b/packages/file/src/file.js @@ -1,5 +1,3 @@ -import { Blob } from "./package.js" - /** * @implements {globalThis.File} */ @@ -14,7 +12,7 @@ export class File extends Blob { constructor( init, name = panic(new TypeError("File constructor requires name argument")), - options = {} + options = {}, ) { super(init, options) // Per File API spec https://w3c.github.io/FileAPI/#file-constructor @@ -61,6 +59,6 @@ export class File extends Blob { * @param {*} error * @returns {never} */ -const panic = error => { +const panic = (error) => { throw error } diff --git a/packages/file/src/lib.js b/packages/file/src/lib.js index fdb251f..a37644c 100644 --- a/packages/file/src/lib.js +++ b/packages/file/src/lib.js @@ -1,2 +1 @@ export const File = globalThis.File -export const Blob = globalThis.Blob diff --git a/packages/file/src/lib.node.js b/packages/file/src/lib.node.js index 143bcbb..034b486 100644 --- a/packages/file/src/lib.node.js +++ b/packages/file/src/lib.node.js @@ -1,6 +1,5 @@ "use strict" -import { Blob } from "./package.js" import { File as WebFile } from "./file.js" // Electron-renderer should get the browser implementation instead of node @@ -10,4 +9,4 @@ import { File as WebFile } from "./file.js" /** @type {typeof globalThis.File} */ const File = WebFile -export { File, Blob } +export { File } diff --git a/packages/file/src/package.js b/packages/file/src/package.js deleted file mode 100644 index 56b17ed..0000000 --- a/packages/file/src/package.js +++ /dev/null @@ -1 +0,0 @@ -export { Blob } from "@remix-run/web-blob"; diff --git a/packages/file/test/file.spec.js b/packages/file/test/file.spec.js index 3247e46..dc8d885 100644 --- a/packages/file/test/file.spec.js +++ b/packages/file/test/file.spec.js @@ -7,14 +7,12 @@ import { assert } from "./test.js"; */ export const test = test => { test("test baisc", async () => { - assert.isEqual(typeof lib.Blob, "function"); assert.isEqual(typeof lib.File, "function"); }); if (globalThis.window === globalThis) { test("uses built-ins", async () => { assert.isEqual(lib.File, globalThis.File); - assert.isEqual(lib.Blob, globalThis.Blob); }); } diff --git a/packages/file/tsconfig.json b/packages/file/tsconfig.json index 5deead4..d7be6c3 100644 --- a/packages/file/tsconfig.json +++ b/packages/file/tsconfig.json @@ -7,9 +7,6 @@ } }, "references": [ - { - "path": "../blob" - }, { "path": "../fetch" } diff --git a/packages/form-data/package.json b/packages/form-data/package.json index 2211564..c93c94c 100644 --- a/packages/form-data/package.json +++ b/packages/form-data/package.json @@ -30,14 +30,10 @@ "import": "./src/lib.node.js" } }, - "dependencies": { - "web-encoding": "1.1.5" - }, "author": "Irakli Gozalishvili (https://gozala.io)", "repository": "https://github.com/remix-run/web-std-io", "license": "MIT", "devDependencies": { - "@remix-run/web-blob": "^3.1.0", "@remix-run/web-fetch": "^4.4.2-pre.0", "@remix-run/web-file": "^3.1.0", "@types/node": "15.0.2", diff --git a/packages/form-data/test/fetch.spec.js b/packages/form-data/test/fetch.spec.js index 938777a..adf3993 100644 --- a/packages/form-data/test/fetch.spec.js +++ b/packages/form-data/test/fetch.spec.js @@ -1,5 +1,4 @@ import { FormData } from "@remix-run/web-form-data"; -import { Blob } from "@remix-run/web-file"; import { Response } from "@remix-run/web-fetch"; import { assert } from "./test.js"; diff --git a/packages/form-data/test/form-data.spec.js b/packages/form-data/test/form-data.spec.js index 3539ab3..1efb661 100644 --- a/packages/form-data/test/form-data.spec.js +++ b/packages/form-data/test/form-data.spec.js @@ -1,6 +1,6 @@ -import { FormData } from "@remix-run/web-form-data"; +import { File } from "@remix-run/web-file"; import * as lib from "@remix-run/web-form-data"; -import { File, Blob } from "@remix-run/web-file"; +import { FormData } from "@remix-run/web-form-data"; import { assert } from "./test.js"; /** diff --git a/packages/form-data/tsconfig.json b/packages/form-data/tsconfig.json index b076f88..d4d7afc 100644 --- a/packages/form-data/tsconfig.json +++ b/packages/form-data/tsconfig.json @@ -9,13 +9,7 @@ "references": [ { "path": "../file" - }, - { - "path": "../blob" } ], - "include": [ - "src", - "test" - ] + "include": ["src", "test"] } diff --git a/packages/stream/test/lib.spec.cjs b/packages/stream/test/lib.spec.cjs index a1dde55..89f6136 100644 --- a/packages/stream/test/lib.spec.cjs +++ b/packages/stream/test/lib.spec.cjs @@ -5,7 +5,7 @@ const lib = require("@remix-run/web-stream"); */ exports.test = async ({ test, assert }) => { console.log("define tests"); - test("test baisc", async () => { + test("test basic", async () => { console.log("test basic"); assert.isEqual(typeof lib.ReadableStream, "function"); diff --git a/packages/stream/test/lib.spec.js b/packages/stream/test/lib.spec.js index 6411205..80b701f 100644 --- a/packages/stream/test/lib.spec.js +++ b/packages/stream/test/lib.spec.js @@ -5,7 +5,7 @@ import { assert } from "./test.js"; * @param {import('./test').Test} test */ export const test = test => { - test("test baisc", async () => { + test("test basic", async () => { assert.isEqual(typeof lib.ReadableStream, "function"); }); diff --git a/yarn.lock b/yarn.lock index 2421e7c..7e3aaa1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -783,11 +783,6 @@ resolved "https://registry.yarnpkg.com/@web3-storage/multipart-parser/-/multipart-parser-1.0.0.tgz#6b69dc2a32a5b207ba43e556c25cc136a56659c4" integrity sha512-BEO6al7BYqcnfX15W2cnGR+Q566ACXAT9UQykORCWW80lmkpWsnEob6zJS1ZVBKsSJC8+7vJkHwlp+lXG1UCdw== -"@zxing/text-encoding@0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" - integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== - abort-controller@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" @@ -3806,13 +3801,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-generator-function@^1.0.7: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== - dependencies: - has-tostringtag "^1.0.0" - is-get-set-prop@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-get-set-prop/-/is-get-set-prop-1.0.0.tgz#2731877e4d78a6a69edcce6bb9d68b0779e76312" @@ -4008,7 +3996,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.3, is-typed-array@^1.1.7: +is-typed-array@^1.1.7: version "1.1.8" resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.8.tgz#cbaa6585dc7db43318bc5b89523ea384a6f65e79" integrity sha512-HqH41TNZq2fgtGT8WHVFVJhBVGuY3AnP3Q36K8JKXUxSxRgk/d+7NjmwG2vo2mYmXK8UYZKu0qH8bVP5gEisjA== @@ -6854,18 +6842,6 @@ util@^0.11.0: dependencies: inherits "2.0.3" -util@^0.12.3: - version "0.12.4" - resolved "https://registry.yarnpkg.com/util/-/util-0.12.4.tgz#66121a31420df8f01ca0c464be15dfa1d1850253" - integrity sha512-bxZ9qtSlGUWSOy9Qa9Xgk11kSslpuZwaxCg4sNIDj6FLucDab2JxnHwyNTCpHMtK1MjoQiWQ6DiUMZYbSrO+Sw== - dependencies: - inherits "^2.0.3" - is-arguments "^1.0.4" - is-generator-function "^1.0.7" - is-typed-array "^1.1.3" - safe-buffer "^5.1.2" - which-typed-array "^1.1.2" - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -6932,15 +6908,6 @@ wcwidth@^1.0.1: dependencies: defaults "^1.0.3" -web-encoding@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864" - integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA== - dependencies: - util "^0.12.3" - optionalDependencies: - "@zxing/text-encoding" "0.9.0" - web-streams-polyfill@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.1.1.tgz#1516f2d4ea8f1bdbfed15eb65cb2df87098c8364" From 55510dedd7727aff8e59a46fc6cda7a66498971b Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Thu, 7 Mar 2024 17:25:06 +0100 Subject: [PATCH 2/4] Update Node.js version in workflows --- .github/workflows/release.yml | 2 +- .github/workflows/validate.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 108cbe9..9c750e5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: uses: actions/setup-node@v3 with: cache: yarn - node-version: 16 + node-version: 18 - name: 📥 Install deps run: yarn --frozen-lockfile diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index 669ad6b..fe6b042 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-node@v3 with: cache: yarn - node-version: 16 + node-version: 18 - name: 📥 Install deps run: yarn --frozen-lockfile @@ -42,7 +42,7 @@ jobs: fail-fast: false matrix: - node: [14, 16, 18, 20] + node: [18, 20] os: [ubuntu-latest, windows-latest, macos-latest] project: [blob, fetch, file, form-data, stream] From b7ec98c900fb6592921b0497b9708c22e581b67f Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Thu, 7 Mar 2024 17:27:43 +0100 Subject: [PATCH 3/4] Fix file name comparison in formData test --- packages/fetch/test/request.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/fetch/test/request.js b/packages/fetch/test/request.js index 7ed6685..648c97c 100644 --- a/packages/fetch/test/request.js +++ b/packages/fetch/test/request.js @@ -480,7 +480,7 @@ describe('Request', () => { return clonedRequest.formData().then(async clonedFormData => { expect(clonedFormData.get('a')).to.equal("1"); const file = clonedFormData.get('file'); - expect(file.name).to. equal(""); + expect(file.name).to.equal(""); expect(file.type).to.equal("application/octet-stream"); expect(file.size).to.equal(0); }); From a7710bd8f25bd75aaba85814990147fef8d01f14 Mon Sep 17 00:00:00 2001 From: Lee Freeman Date: Thu, 7 Mar 2024 17:30:08 +0100 Subject: [PATCH 4/4] Revert formatting change --- packages/file/src/file.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/file/src/file.js b/packages/file/src/file.js index 65d1bd9..ed6bdd9 100644 --- a/packages/file/src/file.js +++ b/packages/file/src/file.js @@ -12,7 +12,7 @@ export class File extends Blob { constructor( init, name = panic(new TypeError("File constructor requires name argument")), - options = {}, + options = {} ) { super(init, options) // Per File API spec https://w3c.github.io/FileAPI/#file-constructor @@ -59,6 +59,6 @@ export class File extends Blob { * @param {*} error * @returns {never} */ -const panic = (error) => { +const panic = error => { throw error }