From 325fb2489344a15c561fdbf3aa1fc4755aa77c1c Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 7 Apr 2023 14:13:53 -0700 Subject: [PATCH 1/7] `prefer-blob-reading-methods`: Add new rule --- configs/recommended.js | 1 + docs/rules/prefer-blob-reading-methods.md | 38 ++++++++++++++++++ readme.md | 1 + rules/prefer-blob-reading-methods.js | 48 +++++++++++++++++++++++ test/prefer-blob-reading-methods.mjs | 19 +++++++++ 5 files changed, 107 insertions(+) create mode 100644 docs/rules/prefer-blob-reading-methods.md create mode 100644 rules/prefer-blob-reading-methods.js create mode 100644 test/prefer-blob-reading-methods.mjs diff --git a/configs/recommended.js b/configs/recommended.js index 7196c57a90..cb8559549c 100644 --- a/configs/recommended.js +++ b/configs/recommended.js @@ -75,6 +75,7 @@ module.exports = { 'unicorn/prefer-array-some': 'error', // TODO: Enable this by default when targeting a Node.js version that supports `Array#at`. 'unicorn/prefer-at': 'off', + 'unicorn/prefer-blob-reading-methods': 'error', 'unicorn/prefer-code-point': 'error', 'unicorn/prefer-date-now': 'error', 'unicorn/prefer-default-parameters': 'error', diff --git a/docs/rules/prefer-blob-reading-methods.md b/docs/rules/prefer-blob-reading-methods.md new file mode 100644 index 0000000000..f631277fd2 --- /dev/null +++ b/docs/rules/prefer-blob-reading-methods.md @@ -0,0 +1,38 @@ +# Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)` + +💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs). + + + + +`FileReader` predates promises, and the newer [`Blob#arrayBuffer()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/arrayBuffer) and [`Blob#text()`](https://developer.mozilla.org/en-US/docs/Web/API/Blob/text) methods are much cleaner and easier to use. + +## Fail + +```js +const arrayBuffer = await new Promise((resolve, reject) => { + const fileReader = new FileReader(); + fileReader.onload = () => resolve(fileReader.result) + fileReader.onerror = () => reject(fileReader.error) + fileReader.readAsArrayBuffer(blob); +}); +``` + +```js +const text = await new Promise((resolve, reject) => { + const fileReader = new FileReader(); + fileReader.onload = () => resolve(fileReader.result) + fileReader.onerror = () => reject(fileReader.error) + fileReader.readAsText(blob); +}); +``` + +## Pass + +```js +const arrayBuffer = await blob.arrayBuffer(); +``` + +```js +const text = await blob.text(); +``` diff --git a/readme.md b/readme.md index 36984423ea..03ea75bee9 100644 --- a/readme.md +++ b/readme.md @@ -116,6 +116,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. | ✅ | 🔧 | 💡 | | [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`. | ✅ | 🔧 | 💡 | | [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 | +| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)` | ✅ | | | | [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. | ✅ | | 💡 | | [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. | ✅ | 🔧 | | | [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. | ✅ | 🔧 | 💡 | diff --git a/rules/prefer-blob-reading-methods.js b/rules/prefer-blob-reading-methods.js new file mode 100644 index 0000000000..28badee967 --- /dev/null +++ b/rules/prefer-blob-reading-methods.js @@ -0,0 +1,48 @@ +'use strict'; +const {methodCallSelector} = require('./selectors/index.js'); + +const messages = { + 'error/readAsArrayBuffer': 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)`.', + 'error/readAsText': 'Prefer `Blob#text()` over `FileReader#readAsText(blob)`.', +}; + +const cases = [ + { + selector: methodCallSelector('readAsArrayBuffer'), + }, + { + selector: methodCallSelector({ + method: 'readAsText', + argumentsLength: 1 + }), + }, +]; + +/** @param {import('eslint').Rule.RuleContext} context */ +const create = () => Object.fromEntries( + cases.map(({selector}) => [ + selector, + node => { + const method = node.callee.property; + const methodName = method.name; + + return { + node: method, + messageId: `error/${methodName}`, + }; + }, + ]), +); + +/** @type {import('eslint').Rule.RuleModule} */ +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)`.', + }, + hasSuggestions: true, + messages, + }, +}; diff --git a/test/prefer-blob-reading-methods.mjs b/test/prefer-blob-reading-methods.mjs new file mode 100644 index 0000000000..7c2891140e --- /dev/null +++ b/test/prefer-blob-reading-methods.mjs @@ -0,0 +1,19 @@ +import {getTester} from './utils/test.mjs'; + +const {test} = getTester(import.meta); + +test.snapshot({ + valid: [ + 'blob.arrayBuffer()', + 'blob.text()', + 'new Response(blob).arrayBuffer()', + 'new Response(blob).text()', + 'new FileReader().readAsDataURL(blob)', + 'new FileReader().readAsBinaryString(blob)', + 'new FileReader().readAsText(blob, "ascii")', + ], + invalid: [ + 'new FileReader().readAsArrayBuffer(blob)', + 'new FileReader().readAsText(blob)', + ], +}); From cb065eb7675a62d6cf0f23a37c21fac1f89e651f Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Fri, 7 Apr 2023 14:18:15 -0700 Subject: [PATCH 2/7] snapshots --- .../prefer-blob-reading-methods.mjs.md | 25 ++++++++++++++++++ .../prefer-blob-reading-methods.mjs.snap | Bin 0 -> 228 bytes 2 files changed, 25 insertions(+) create mode 100644 test/snapshots/prefer-blob-reading-methods.mjs.md create mode 100644 test/snapshots/prefer-blob-reading-methods.mjs.snap diff --git a/test/snapshots/prefer-blob-reading-methods.mjs.md b/test/snapshots/prefer-blob-reading-methods.mjs.md new file mode 100644 index 0000000000..2b1ea757ac --- /dev/null +++ b/test/snapshots/prefer-blob-reading-methods.mjs.md @@ -0,0 +1,25 @@ +# Snapshot report for `test/prefer-blob-reading-methods.mjs` + +The actual snapshot is saved in `prefer-blob-reading-methods.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## Invalid #1 + 1 | new FileReader().readAsArrayBuffer(blob) + +> Error 1/1 + + `␊ + > 1 | new FileReader().readAsArrayBuffer(blob)␊ + | ^^^^^^^^^^^^^^^^^ Prefer \`Blob#arrayBuffer()\` over \`FileReader#readAsArrayBuffer(blob)\`.␊ + ` + +## Invalid #2 + 1 | new FileReader().readAsText(blob) + +> Error 1/1 + + `␊ + > 1 | new FileReader().readAsText(blob)␊ + | ^^^^^^^^^^ Prefer \`Blob#text()\` over \`FileReader#readAsText(blob)\`.␊ + ` diff --git a/test/snapshots/prefer-blob-reading-methods.mjs.snap b/test/snapshots/prefer-blob-reading-methods.mjs.snap new file mode 100644 index 0000000000000000000000000000000000000000..0ecbe33f14a09081bc977f2ee3aaf8ff54237060 GIT binary patch literal 228 zcmV Date: Sun, 9 Apr 2023 14:10:03 -0700 Subject: [PATCH 3/7] Fix lint errors --- rules/prefer-blob-reading-methods.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rules/prefer-blob-reading-methods.js b/rules/prefer-blob-reading-methods.js index 28badee967..2c5b3688af 100644 --- a/rules/prefer-blob-reading-methods.js +++ b/rules/prefer-blob-reading-methods.js @@ -12,9 +12,9 @@ const cases = [ }, { selector: methodCallSelector({ - method: 'readAsText', - argumentsLength: 1 - }), + method: 'readAsText', + argumentsLength: 1, + }), }, ]; From db88c0b6f18fd6b9c621ce221ee287e5c5b768f4 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Sun, 9 Apr 2023 14:18:57 -0700 Subject: [PATCH 4/7] Fix hasSuggestions --- readme.md | 2 +- rules/prefer-blob-reading-methods.js | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 03ea75bee9..bdcd8d84c1 100644 --- a/readme.md +++ b/readme.md @@ -116,7 +116,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. | ✅ | 🔧 | 💡 | | [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`. | ✅ | 🔧 | 💡 | | [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 | -| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)` | ✅ | | | +| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)`. | ✅ | | | | [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. | ✅ | | 💡 | | [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. | ✅ | 🔧 | | | [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. | ✅ | 🔧 | 💡 | diff --git a/rules/prefer-blob-reading-methods.js b/rules/prefer-blob-reading-methods.js index 2c5b3688af..e0c0152029 100644 --- a/rules/prefer-blob-reading-methods.js +++ b/rules/prefer-blob-reading-methods.js @@ -42,7 +42,6 @@ module.exports = { docs: { description: 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)`.', }, - hasSuggestions: true, messages, }, }; From ba281c309e2776f57bfb2e02e31be1d75fbb0a59 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 10 Apr 2023 09:25:51 +0800 Subject: [PATCH 5/7] Simplify logic --- docs/rules/prefer-blob-reading-methods.md | 25 +++++++++----- readme.md | 2 +- rules/prefer-blob-reading-methods.js | 40 +++++++++-------------- test/prefer-blob-reading-methods.mjs | 10 +++--- 4 files changed, 37 insertions(+), 40 deletions(-) diff --git a/docs/rules/prefer-blob-reading-methods.md b/docs/rules/prefer-blob-reading-methods.md index f631277fd2..f2e2e57145 100644 --- a/docs/rules/prefer-blob-reading-methods.md +++ b/docs/rules/prefer-blob-reading-methods.md @@ -1,4 +1,4 @@ -# Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)` +# Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)` 💼 This rule is enabled in the ✅ `recommended` [config](https://github.com/sindresorhus/eslint-plugin-unicorn#preset-configs). @@ -12,19 +12,18 @@ ```js const arrayBuffer = await new Promise((resolve, reject) => { const fileReader = new FileReader(); - fileReader.onload = () => resolve(fileReader.result) - fileReader.onerror = () => reject(fileReader.error) + fileReader.addEventListener('load', () => { + resolve(fileReader.result); + }); + fileReader.addEventListener('error', () => { + reject(fileReader.error); + }); fileReader.readAsArrayBuffer(blob); }); ``` ```js -const text = await new Promise((resolve, reject) => { - const fileReader = new FileReader(); - fileReader.onload = () => resolve(fileReader.result) - fileReader.onerror = () => reject(fileReader.error) - fileReader.readAsText(blob); -}); +fileReader.readAsText(blob); ``` ## Pass @@ -36,3 +35,11 @@ const arrayBuffer = await blob.arrayBuffer(); ```js const text = await blob.text(); ``` + +```js +fileReader.readAsText(blob, 'ascii'); +``` + +```js +fileReader.readAsDataURL(blob); +``` diff --git a/readme.md b/readme.md index bdcd8d84c1..d2673e7700 100644 --- a/readme.md +++ b/readme.md @@ -116,7 +116,7 @@ If you don't use the preset, ensure you use the same `env` and `parserOptions` c | [prefer-array-index-of](docs/rules/prefer-array-index-of.md) | Prefer `Array#{indexOf,lastIndexOf}()` over `Array#{findIndex,findLastIndex}()` when looking for the index of an item. | ✅ | 🔧 | 💡 | | [prefer-array-some](docs/rules/prefer-array-some.md) | Prefer `.some(…)` over `.filter(…).length` check and `.{find,findLast}(…)`. | ✅ | 🔧 | 💡 | | [prefer-at](docs/rules/prefer-at.md) | Prefer `.at()` method for index access and `String#charAt()`. | | 🔧 | 💡 | -| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)`. | ✅ | | | +| [prefer-blob-reading-methods](docs/rules/prefer-blob-reading-methods.md) | Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`. | ✅ | | | | [prefer-code-point](docs/rules/prefer-code-point.md) | Prefer `String#codePointAt(…)` over `String#charCodeAt(…)` and `String.fromCodePoint(…)` over `String.fromCharCode(…)`. | ✅ | | 💡 | | [prefer-date-now](docs/rules/prefer-date-now.md) | Prefer `Date.now()` to get the number of milliseconds since the Unix Epoch. | ✅ | 🔧 | | | [prefer-default-parameters](docs/rules/prefer-default-parameters.md) | Prefer default parameters over reassignment. | ✅ | 🔧 | 💡 | diff --git a/rules/prefer-blob-reading-methods.js b/rules/prefer-blob-reading-methods.js index e0c0152029..48f3168a9c 100644 --- a/rules/prefer-blob-reading-methods.js +++ b/rules/prefer-blob-reading-methods.js @@ -6,33 +6,23 @@ const messages = { 'error/readAsText': 'Prefer `Blob#text()` over `FileReader#readAsText(blob)`.', }; -const cases = [ - { - selector: methodCallSelector('readAsArrayBuffer'), - }, - { - selector: methodCallSelector({ - method: 'readAsText', - argumentsLength: 1, - }), - }, -]; +const selector = methodCallSelector({ + methods: ['readAsText', 'readAsArrayBuffer'], + argumentsLength: 1, +}); /** @param {import('eslint').Rule.RuleContext} context */ -const create = () => Object.fromEntries( - cases.map(({selector}) => [ - selector, - node => { - const method = node.callee.property; - const methodName = method.name; +const create = () => ({ + [selector](node) { + const method = node.callee.property; + const methodName = method.name; - return { - node: method, - messageId: `error/${methodName}`, - }; - }, - ]), -); + return { + node: method, + messageId: `error/${methodName}`, + }; + } +}); /** @type {import('eslint').Rule.RuleModule} */ module.exports = { @@ -40,7 +30,7 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(blob)` and `Blob#text()` over `FileReader#readAsText(blob)`.', + description: 'Prefer `Blob#arrayBuffer()` over `FileReader#readAsArrayBuffer(…)` and `Blob#text()` over `FileReader#readAsText(…)`.', }, messages, }, diff --git a/test/prefer-blob-reading-methods.mjs b/test/prefer-blob-reading-methods.mjs index 7c2891140e..4814dde049 100644 --- a/test/prefer-blob-reading-methods.mjs +++ b/test/prefer-blob-reading-methods.mjs @@ -8,12 +8,12 @@ test.snapshot({ 'blob.text()', 'new Response(blob).arrayBuffer()', 'new Response(blob).text()', - 'new FileReader().readAsDataURL(blob)', - 'new FileReader().readAsBinaryString(blob)', - 'new FileReader().readAsText(blob, "ascii")', + 'fileReader.readAsDataURL(blob)', + 'fileReader.readAsBinaryString(blob)', + 'fileReader.readAsText(blob, "ascii")', ], invalid: [ - 'new FileReader().readAsArrayBuffer(blob)', - 'new FileReader().readAsText(blob)', + 'fileReader.readAsArrayBuffer(blob)', + 'fileReader.readAsText(blob)', ], }); From a5428b52e4e6e00ccbfa95be704b9781c8d6bbc5 Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 10 Apr 2023 09:29:02 +0800 Subject: [PATCH 6/7] Linting --- rules/prefer-blob-reading-methods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rules/prefer-blob-reading-methods.js b/rules/prefer-blob-reading-methods.js index 48f3168a9c..bded5ca547 100644 --- a/rules/prefer-blob-reading-methods.js +++ b/rules/prefer-blob-reading-methods.js @@ -21,7 +21,7 @@ const create = () => ({ node: method, messageId: `error/${methodName}`, }; - } + }, }); /** @type {import('eslint').Rule.RuleModule} */ From 70c9d0387b157413e3a6d6040c653a469680a10e Mon Sep 17 00:00:00 2001 From: fisker Date: Mon, 10 Apr 2023 09:33:17 +0800 Subject: [PATCH 7/7] Update snapshot --- .../prefer-blob-reading-methods.mjs.md | 12 ++++++------ .../prefer-blob-reading-methods.mjs.snap | Bin 228 -> 224 bytes 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/snapshots/prefer-blob-reading-methods.mjs.md b/test/snapshots/prefer-blob-reading-methods.mjs.md index 2b1ea757ac..aae208d871 100644 --- a/test/snapshots/prefer-blob-reading-methods.mjs.md +++ b/test/snapshots/prefer-blob-reading-methods.mjs.md @@ -5,21 +5,21 @@ The actual snapshot is saved in `prefer-blob-reading-methods.mjs.snap`. Generated by [AVA](https://avajs.dev). ## Invalid #1 - 1 | new FileReader().readAsArrayBuffer(blob) + 1 | fileReader.readAsArrayBuffer(blob) > Error 1/1 `␊ - > 1 | new FileReader().readAsArrayBuffer(blob)␊ - | ^^^^^^^^^^^^^^^^^ Prefer \`Blob#arrayBuffer()\` over \`FileReader#readAsArrayBuffer(blob)\`.␊ + > 1 | fileReader.readAsArrayBuffer(blob)␊ + | ^^^^^^^^^^^^^^^^^ Prefer \`Blob#arrayBuffer()\` over \`FileReader#readAsArrayBuffer(blob)\`.␊ ` ## Invalid #2 - 1 | new FileReader().readAsText(blob) + 1 | fileReader.readAsText(blob) > Error 1/1 `␊ - > 1 | new FileReader().readAsText(blob)␊ - | ^^^^^^^^^^ Prefer \`Blob#text()\` over \`FileReader#readAsText(blob)\`.␊ + > 1 | fileReader.readAsText(blob)␊ + | ^^^^^^^^^^ Prefer \`Blob#text()\` over \`FileReader#readAsText(blob)\`.␊ ` diff --git a/test/snapshots/prefer-blob-reading-methods.mjs.snap b/test/snapshots/prefer-blob-reading-methods.mjs.snap index 0ecbe33f14a09081bc977f2ee3aaf8ff54237060..9f3c910778c83eb6bdb944c97dc4fa6baeac5513 100644 GIT binary patch literal 224 zcmV<603ZKBRzVS$nqa!0RR9GQd469 literal 228 zcmV