From b48f178c2513667fc34f5a2a3c89e739d503ba2a Mon Sep 17 00:00:00 2001 From: fisker Date: Thu, 28 Jan 2021 15:24:02 +0800 Subject: [PATCH 1/7] Add `prefer-module` rule --- docs/rules/prefer-module.md | 91 ++ index.js | 1 + readme.md | 2 + rules/prefer-module.js | 331 +++++++ rules/prevent-abbreviations.js | 11 +- rules/utils/is-static-require.js | 15 + test/prefer-module.mjs | 251 +++++ test/snapshots/prefer-module.mjs.md | 1254 +++++++++++++++++++++++++ test/snapshots/prefer-module.mjs.snap | Bin 0 -> 3953 bytes 9 files changed, 1946 insertions(+), 10 deletions(-) create mode 100644 docs/rules/prefer-module.md create mode 100644 rules/prefer-module.js create mode 100644 rules/utils/is-static-require.js create mode 100644 test/prefer-module.mjs create mode 100644 test/snapshots/prefer-module.mjs.md create mode 100644 test/snapshots/prefer-module.mjs.snap diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md new file mode 100644 index 0000000000..d7f024ff9d --- /dev/null +++ b/docs/rules/prefer-module.md @@ -0,0 +1,91 @@ +# Prefer ES modules over CommonJS + +Prefer use ESM over legacy CommonJS module. + +1. Forbid `use strict` directive. + + ESM scripts use Strict Mode by default. + +1. Forbid `Global Return` + + This is a CommonJS-only feature. + +1. Forbid global variables `__dirname` and `__filename`. + + It's not available in ESM. + +1. Forbid `require(…)` + + `import …` is preferred in ESM. + +1. Forbid `exports` and `module.exports` + + `export …` is preferred in ESM. + + +## Fail + +```js +'use strict'; + +// … +``` + +```js +if (foo) { + return; +} + +// … +``` + +```js +const file = path.join(__dirname, 'foo.js'); +``` + +```js +const {fromPairs} = require('lodash'); +``` + +```js +module.exports = foo; +``` + +```js +exports.foo = foo; +``` + +## Pass + + +```js +function run() { + if (foo) { + return; + } + + // … +} + +run(); +``` + +```js +const file = fileURLToPath(new URL('foo.js', import.meta.url)); +``` + +```js +import {fromPairs} from 'lodash-es'; +``` + +```js +export default foo; +``` + +```js +export {foo}; +``` + +## Resources + +- [Get Ready For ESM](https://blog.sindresorhus.com/get-ready-for-esm-aa53530b3f77) by @sindresorhus diff --git a/index.js b/index.js index c873a76bd5..04db914cf7 100644 --- a/index.js +++ b/index.js @@ -99,6 +99,7 @@ module.exports = { 'unicorn/prefer-keyboard-event-key': 'error', 'unicorn/prefer-math-trunc': 'error', 'unicorn/prefer-modern-dom-apis': 'error', + 'unicorn/prefer-module': 'error', 'unicorn/prefer-negative-index': 'error', 'unicorn/prefer-number-properties': 'error', 'unicorn/prefer-optional-catch-binding': 'error', diff --git a/readme.md b/readme.md index c569eca7c1..2cf396fdbc 100644 --- a/readme.md +++ b/readme.md @@ -90,6 +90,7 @@ Configure it in `package.json`. "unicorn/prefer-keyboard-event-key": "error", "unicorn/prefer-math-trunc": "error", "unicorn/prefer-modern-dom-apis": "error", + "unicorn/prefer-module": "error", "unicorn/prefer-negative-index": "error", "unicorn/prefer-number-properties": "error", "unicorn/prefer-optional-catch-binding": "error", @@ -180,6 +181,7 @@ Each rule has emojis denoting: | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | ✅ | 🔧 | | [prefer-modern-dom-apis](docs/rules/prefer-modern-dom-apis.md) | Prefer `.before()` over `.insertBefore()`, `.replaceWith()` over `.replaceChild()`, prefer one of `.before()`, `.after()`, `.append()` or `.prepend()` over `insertAdjacentText()` and `insertAdjacentElement()`. | ✅ | 🔧 | +| [prefer-module](docs/rules/prefer-module.md) | Prefer ES modules over CommonJS. | ✅ | 🔧 | | [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#slice()` and `Array#splice()`. | ✅ | 🔧 | | [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. | ✅ | 🔧 | | [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) | Prefer omitting the `catch` binding parameter. | ✅ | 🔧 | diff --git a/rules/prefer-module.js b/rules/prefer-module.js new file mode 100644 index 0000000000..c3db4341c2 --- /dev/null +++ b/rules/prefer-module.js @@ -0,0 +1,331 @@ +'use strict'; +const {isOpeningParenToken} = require('eslint-utils'); +const getDocumentationUrl = require('./utils/get-documentation-url'); +const isShadowed = require('./utils/is-shadowed'); +const removeSpacesAfter = require('./utils/remove-spaces-after'); +const isStaticRequire = require('./utils/is-static-require'); +const renameIdentifier = require('./utils/rename-identifier'); +const {getParentheses} = require('./utils/parentheses'); +const assertToken = require('./utils/assert-token'); +const referenceIdentifierSelector = require('./utils/reference-identifier-selector'); + +const ERROR_USE_STRICT_DIRECTIVE = 'error/use-strict-directive'; +const ERROR_GLOBAL_RETURN = 'error/global-return'; +const ERROR_IDENTIFIER = 'error/identifier'; +const SUGGESTION_DIRNAME = 'suggestion/dirname'; +const SUGGESTION_FILENAME = 'suggestion/filename'; +const SUGGESTION_IMPORT = 'suggestion/import'; +const SUGGESTION_EXPORT = 'suggestion/export'; +const messages = { + [ERROR_USE_STRICT_DIRECTIVE]: 'Do not use "use strict" directive.', + [ERROR_GLOBAL_RETURN]: '"return" should be used inside a function.', + [ERROR_IDENTIFIER]: 'Do not use "{{name}}".', + [SUGGESTION_DIRNAME]: 'Replace "__dirname" with `"…(import.meta.url)"`.', + [SUGGESTION_FILENAME]: 'Replace "__filename" with `"…(import.meta.url)"`.', + [SUGGESTION_IMPORT]: 'Switch to `import`.', + [SUGGESTION_EXPORT]: 'Switch to `export`.' +}; + +const identifierSelector = referenceIdentifierSelector([ + 'exports', + 'require', + 'module', + '__filename', + '__dirname' +]); + +function fixRequireCall(node, sourceCode) { + if (!isStaticRequire(node.parent) || node.parent.callee !== node) { + return; + } + + const requireCall = node.parent; + const { + parent, + callee, + arguments: [source] + } = requireCall; + + // `require("foo")` + if (parent.type === 'ExpressionStatement' && parent.parent.type === 'Program') { + return function * (fixer) { + yield fixer.replaceText(callee, 'import'); + const openingParenthesisToken = sourceCode.getTokenAfter( + callee, + isOpeningParenToken + ); + yield fixer.replaceText(openingParenthesisToken, ' '); + const closingParenthesisToken = sourceCode.getLastToken(requireCall); + yield fixer.remove(closingParenthesisToken); + + // Remove parentheses + for (const node of [callee, requireCall, source]) { + const parentheses = getParentheses(node, sourceCode); + for (const token of parentheses) { + yield fixer.remove(token); + } + } + }; + } + + // `const foo = require("foo")` + // `const {foo} = require("foo")` + if ( + parent.type === 'VariableDeclarator' && + parent.init === requireCall && + ( + parent.id.type === 'Identifier' || + ( + parent.id.type === 'ObjectPattern' && + parent.id.properties.every( + ({type, key, value, computed}) => + type === 'Property' && + !computed && + value.type === 'Identifier' && + key.type === 'Identifier' + ) + ) + ) && + parent.parent.type === 'VariableDeclaration' && + parent.parent.kind === 'const' && + parent.parent.declarations.length === 1 && + parent.parent.declarations[0] === parent && + parent.parent.parent.type === 'Program' + ) { + const declarator = parent; + const declaration = declarator.parent; + const {id} = declarator; + + return function * (fixer) { + const constToken = sourceCode.getFirstToken(declaration); + assertToken(constToken, { + expected: {type: 'Keyword', value: 'const'}, + ruleId: 'prefer-module' + }); + yield fixer.replaceText(constToken, 'import'); + + const equalToken = sourceCode.getTokenAfter(id); + assertToken(equalToken, { + expected: {type: 'Punctuator', value: '='}, + ruleId: 'prefer-module' + }); + yield removeSpacesAfter(id, sourceCode, fixer); + yield removeSpacesAfter(equalToken, sourceCode, fixer); + yield fixer.replaceText(equalToken, ' from '); + + yield fixer.remove(callee); + const openingParenthesisToken = sourceCode.getTokenAfter( + callee, + isOpeningParenToken + ); + yield fixer.remove(openingParenthesisToken); + const closingParenthesisToken = sourceCode.getLastToken(requireCall); + yield fixer.remove(closingParenthesisToken); + + for (const node of [callee, requireCall, source]) { + const parentheses = getParentheses(node, sourceCode); + for (const token of parentheses) { + yield fixer.remove(token); + } + } + + if (id.type === 'Identifier') { + return; + } + + const {properties} = id; + + for (const property of properties) { + const {key, shorthand} = property; + if (!shorthand) { + const commaToken = sourceCode.getTokenAfter(key); + assertToken(commaToken, { + expected: {type: 'Punctuator', value: ':'}, + ruleId: 'prefer-module' + }); + yield removeSpacesAfter(key, sourceCode, fixer); + yield removeSpacesAfter(commaToken, sourceCode, fixer); + yield fixer.replaceText(commaToken, ' as '); + } + } + }; + } +} + +const isTopLevelAssignment = node => + node.parent.type === 'AssignmentExpression' && + node.parent.operator === '=' && + node.parent.left === node && + node.parent.parent.type === 'ExpressionStatement' && + node.parent.parent.parent.type === 'Program'; +const isNamedExport = node => + node.parent.type === 'MemberExpression' && + !node.parent.optional && + !node.parent.computed && + node.parent.object === node && + node.parent.property.type === 'Identifier' && + isTopLevelAssignment(node.parent) && + node.parent.parent.right.type === 'Identifier'; +const isModuleExports = node => + node.parent.type === 'MemberExpression' && + !node.parent.optional && + !node.parent.computed && + node.parent.object === node && + node.parent.property.type === 'Identifier' && + node.parent.property.name === 'exports'; + +function fixDefaultExport(node, sourceCode) { + return function * (fixer) { + yield fixer.replaceText(node, 'export default '); + yield removeSpacesAfter(node, sourceCode, fixer); + + const equalToken = sourceCode.getTokenAfter(node, token => token.type === 'Punctuator' && token.value === '='); + yield fixer.remove(equalToken); + yield removeSpacesAfter(equalToken, sourceCode, fixer); + + for (const nodeToRemove of [node.parent, node]) { + const parentheses = getParentheses(nodeToRemove, sourceCode); + for (const token of parentheses) { + yield fixer.remove(token); + } + } + }; +} + +function fixNamedExport(node, sourceCode) { + return function * (fixer) { + const assignmentExpression = node.parent.parent; + const exported = node.parent.property.name; + const local = assignmentExpression.right.name; + yield fixer.replaceText(assignmentExpression, `export {${local} as ${exported}}`); + + for (const node of [assignmentExpression]) { + const parentheses = getParentheses(node, sourceCode); + for (const token of parentheses) { + yield fixer.remove(token); + } + } + }; +} + +function fixExports(node, sourceCode) { + // `exports = bar` + if (isTopLevelAssignment(node)) { + return fixDefaultExport(node, sourceCode); + } + + // `exports.foo = bar` + if (isNamedExport(node)) { + return fixNamedExport(node, sourceCode); + } +} + +function fixModuleExports(node, sourceCode) { + if (isModuleExports(node)) { + return fixExports(node.parent, sourceCode); + } +} + +function create(context) { + const sourceCode = context.getSourceCode(); + + return { + 'ExpressionStatement[directive="use strict"]'(node) { + context.report({ + node, + messageId: ERROR_USE_STRICT_DIRECTIVE, + * fix(fixer) { + yield fixer.remove(node); + yield removeSpacesAfter(node, sourceCode, fixer); + } + }); + }, + 'ReturnStatement:not(:function ReturnStatement)'(node) { + context.report({ + node: sourceCode.getFirstToken(node), + messageId: ERROR_GLOBAL_RETURN + }); + }, + [identifierSelector](node) { + if (isShadowed(context.getScope(), node)) { + return; + } + + const {name} = node; + + const problem = { + node, + messageId: ERROR_IDENTIFIER, + data: {name} + }; + + switch (name) { + case '__filename': + case '__dirname': { + const messageId = node.name === '__dirname' ? SUGGESTION_DIRNAME : SUGGESTION_FILENAME; + const replacement = node.name === '__dirname' ? + 'path.dirname(url.fileURLToPath(import.meta.url))' : + 'url.fileURLToPath(import.meta.url)'; + problem.suggest = [{ + messageId, + fix: fixer => renameIdentifier(node, replacement, fixer, sourceCode) + }]; + break; + } + + case 'require': { + const fix = fixRequireCall(node, sourceCode); + if (fix) { + problem.suggest = [{ + messageId: SUGGESTION_IMPORT, + fix + }]; + } + + break; + } + + case 'exports': { + const fix = fixExports(node, sourceCode); + if (fix) { + problem.suggest = [{ + messageId: SUGGESTION_EXPORT, + fix + }]; + } + + break; + } + + case 'module': { + const fix = fixModuleExports(node, sourceCode); + if (fix) { + problem.suggest = [{ + messageId: SUGGESTION_EXPORT, + fix + }]; + } + + break; + } + + default: + } + + context.report(problem); + } + }; +} + +module.exports = { + create, + meta: { + type: 'suggestion', + docs: { + description: 'Prefer ES modules over CommonJS.', + url: getDocumentationUrl(__filename) + }, + fixable: 'code', + messages + } +}; diff --git a/rules/prevent-abbreviations.js b/rules/prevent-abbreviations.js index 9632562b46..4b9dfac1ca 100644 --- a/rules/prevent-abbreviations.js +++ b/rules/prevent-abbreviations.js @@ -9,6 +9,7 @@ const isShorthandPropertyIdentifier = require('./utils/is-shorthand-property-ide const isShorthandImportIdentifier = require('./utils/is-shorthand-import-identifier'); const getVariableIdentifiers = require('./utils/get-variable-identifiers'); const renameIdentifier = require('./utils/rename-identifier'); +const isStaticRequire = require('./utils/is-static-require'); const isUpperCase = string => string === string.toUpperCase(); const isUpperFirst = string => isUpperCase(string[0]); @@ -445,16 +446,6 @@ const shouldFix = variable => { return !getVariableIdentifiers(variable).some(identifier => isExportedIdentifier(identifier)); }; -const isStaticRequire = node => Boolean( - node && - node.callee && - node.callee.type === 'Identifier' && - node.callee.name === 'require' && - node.arguments.length === 1 && - node.arguments[0].type === 'Literal' && - typeof node.arguments[0].value === 'string' -); - const isDefaultOrNamespaceImportName = identifier => { if ( identifier.parent.type === 'ImportDefaultSpecifier' && diff --git a/rules/utils/is-static-require.js b/rules/utils/is-static-require.js new file mode 100644 index 0000000000..b46b0aa2f9 --- /dev/null +++ b/rules/utils/is-static-require.js @@ -0,0 +1,15 @@ +'use strict'; + +const isStaticRequire = node => Boolean( + node && + node.type === 'CallExpression' && + node.callee && + node.callee.type === 'Identifier' && + node.callee.name === 'require' && + !node.optional && + node.arguments.length === 1 && + node.arguments[0].type === 'Literal' && + typeof node.arguments[0].value === 'string' +); + +module.exports = isStaticRequire; diff --git a/test/prefer-module.mjs b/test/prefer-module.mjs new file mode 100644 index 0000000000..85c7108264 --- /dev/null +++ b/test/prefer-module.mjs @@ -0,0 +1,251 @@ +import outdent from 'outdent'; +import {getTester} from './utils/test.mjs'; + +const {test} = getTester(import.meta); + +// Strict mode +test.snapshot({ + valid: [ + 'const foo = "use strict";', + '("use strict")', + '"use strong";', + 'eval("\'use strict\'; var x = 42; x;");', + 'new Function("\'use strict\'; var x = 42; return x;");' + ], + invalid: [ + outdent` + 'use strict'; + + console.log(1); + `, + outdent` + "use strict"; + + console.log(1); + `, + outdent` + function foo () { + "use strict"; + console.log(1); + } + ` + ] +}); + +// Global return +test({ + valid: [ + outdent` + function a() { + return; + } + ` + ], + invalid: [ + { + code: outdent` + if (foo) { + return; + } + `, + output: outdent` + if (foo) { + return; + } + `, + errors: 1, + parserOptions: { + sourceType: 'script', + ecmaFeatures: { + globalReturn: true + } + } + } + ] +}); + +// `__dirname` and `__filename` +test.snapshot({ + testerOptions: { + globals: { + __dirname: true, + __filename: true + } + }, + valid: [ + outdent` + const __filename = 1; + const foo = __filename; + `, + outdent` + const __dirname = 1; + const foo = __dirname; + `, + 'import {__filename as filename} from "foo.mjs"', + 'const foo = 1;export {foo as __dirname}' + ], + invalid: [ + 'const dirname = __dirname;', + 'const dirname = __filename;', + 'const foo = { __dirname};', + 'const foo = {__filename, };', + 'if (__dirname.startsWith("/project/src/")) {}', + 'if (__filename.endsWith(".js")) {}' + ] +}); + +// `require(…)` +test.snapshot({ + valid: [ + outdent` + import {createRequire} from 'module'; + const require = createRequire(import.meta.url); + const foo = require("foo"); + `, + outdent` + const require = function require(require, id) { + return require(id); + } + `, + outdent` + const require = class A { + require(require) { + return require(id); + } + } + ` + ], + invalid: [ + 'require("foo");', + 'require(\'foo\');', + 'require( (("foo")) );', + '((require))("foo");', + '(( require("foo") ));', + 'const foo=require("foo");', + 'const foo = require.resolve("foo");', + outdent` + const foo + = + require("foo"); + `, + 'const foo = require("foo");', + 'const foo = require( (("foo")) );', + 'const foo = ((require))("foo");', + 'const foo = (( require("foo") ));', + 'const {foo}=require("foo");', + outdent` + const {foo} + = + require("foo"); + `, + 'const {foo} = require("foo");', + 'const {foo} = require( (("foo")) );', + 'const {foo} = ((require))("foo");', + 'const {foo} = (( require("foo") ));', + 'const {foo} = (( require("foo") ));', + 'const {foo: foo}=require("foo");', + outdent` + const {foo: foo} + = + require("foo"); + `, + 'const {foo: foo} = require("foo");', + 'const {foo: foo} = require( (("foo")) );', + 'const {foo: foo} = ((require))("foo");', + 'const {foo: foo} = (( require("foo") ));', + 'const {foo: foo} = (( require("foo") ));', + 'const {foo:bar}=require("foo");', + outdent` + const {foo:bar} + = + require("foo"); + `, + 'const {foo:bar} = require("foo");', + 'const {foo:bar} = require( (("foo")) );', + 'const {foo:bar} = ((require))("foo");', + 'const {foo:bar} = (( require("foo") ));', + 'const {foo:bar} = (( require("foo") ));', + 'const {a :foo, b: bar, default : baz}=require("foo");', + outdent` + const { + a :foo, + b: bar, + default : baz, + } + = + require("foo"); + `, + 'const {a :foo, b: bar, default : baz} = require("foo");', + 'const {a :foo, b: bar, default : baz} = require( (("foo")) );', + 'const {a :foo, b: bar, default : baz} = ((require))("foo");', + 'const {a :foo, b: bar, default : baz} = (( require("foo") ));', + 'const {a :foo, b: bar, default : baz} = (( require("foo") ));', + 'const {} = require("foo");', + 'const{ }=require("foo");', + // Not fixable + outdent` + const r = require; + const foo = r("foo"); + `, + 'new require("foo")', + 'require("foo", extraArgument)', + 'const a = require()', + 'require(..."foo")', + 'require("../" + "file.js")', + 'require(file)', + 'a = require("foo")', + 'function a(a = require("foo")) {}', + 'let foo = require("foo");', + 'const foo = require("foo"), bar = require("bar");', + 'const {[foo]: foo} = require("foo");', + 'const {["foo"]: foo} = require("foo");', + 'if (foo) require("foo");', + 'const foo = require("foo"), bar = 1;', + 'const foo = require("foo"), bar = require("bar");' + ] +}); + +// `exports` and `module` +test.snapshot({ + valid: [ + 'function exports(exports) {}', + 'function module(module) {}', + outdent` + const exports = foo; + exports.bar = bar; + `, + 'const exports = 1;', + outdent` + const module = foo; + module.exports = bar; + module.exports.bar = bar; + `, + 'const module = 1;' + ], + invalid: [ + 'exports = foo;', + 'module.exports = foo;', + '(( ((exports)) = ((foo)) ));', + '(( ((module.exports)) = ((foo)) ));', + 'exports.foo = foo;', + 'module.exports.foo = foo;', + 'exports["foo"] = foo;', + 'module.exports["foo"] = foo;', + 'const foo = exports;', + 'const foo = exports.foo;', + 'const foo = module.exports;', + 'const foo = module.exports.foo;', + 'module["exports"] = foo;', + 'module[exports] = foo;', + 'module.exports.foo.bar = foo;', + 'exports.default = foo;', + 'module.exports.default = foo;', + 'exports.foo.bar = foo;', + 'exports = 1;', + 'exports.foo = [];', + 'module.exports = function() {};', + 'module.exports.foo = foo || bar;', + 'exports += foo;', + 'module.exports &= foo;' + ] +}); diff --git a/test/snapshots/prefer-module.mjs.md b/test/snapshots/prefer-module.mjs.md new file mode 100644 index 0000000000..c250d9d567 --- /dev/null +++ b/test/snapshots/prefer-module.mjs.md @@ -0,0 +1,1254 @@ +# Snapshot report for `test/prefer-module.mjs` + +The actual snapshot is saved in `prefer-module.mjs.snap`. + +Generated by [AVA](https://avajs.dev). + +## Invalid #1 + 1 | 'use strict'; + 2 | + 3 | console.log(1); + +> Output + + `␊ + 1 | console.log(1);␊ + ` + +> Error 1/1 + + `␊ + > 1 | 'use strict';␊ + | ^^^^^^^^^^^^^ Do not use "use strict" directive.␊ + 2 |␊ + 3 | console.log(1);␊ + ` + +## Invalid #2 + 1 | "use strict"; + 2 | + 3 | console.log(1); + +> Output + + `␊ + 1 | console.log(1);␊ + ` + +> Error 1/1 + + `␊ + > 1 | "use strict";␊ + | ^^^^^^^^^^^^^ Do not use "use strict" directive.␊ + 2 |␊ + 3 | console.log(1);␊ + ` + +## Invalid #3 + 1 | function foo () { + 2 | "use strict"; + 3 | console.log(1); + 4 | } + +> Output + + `␊ + 1 | function foo () {␊ + 2 | console.log(1);␊ + 3 | }␊ + ` + +> Error 1/1 + + `␊ + 1 | function foo () {␊ + > 2 | "use strict";␊ + | ^^^^^^^^^^^^^ Do not use "use strict" directive.␊ + 3 | console.log(1);␊ + 4 | }␊ + ` + +## Invalid #1 + 1 | const dirname = __dirname; + +> Error 1/1 + + `␊ + > 1 | const dirname = __dirname;␊ + | ^^^^^^^^^ Do not use "__dirname".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__dirname" with \`"…(import.meta.url)"\`.␊ + 1 | const dirname = path.dirname(url.fileURLToPath(import.meta.url));␊ + ` + +## Invalid #2 + 1 | const dirname = __filename; + +> Error 1/1 + + `␊ + > 1 | const dirname = __filename;␊ + | ^^^^^^^^^^ Do not use "__filename".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__filename" with \`"…(import.meta.url)"\`.␊ + 1 | const dirname = url.fileURLToPath(import.meta.url);␊ + ` + +## Invalid #3 + 1 | const foo = { __dirname}; + +> Error 1/2 + + `␊ + > 1 | const foo = { __dirname};␊ + | ^^^^^^^^^ Do not use "__dirname".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__dirname" with \`"…(import.meta.url)"\`.␊ + 1 | const foo = { __dirname: path.dirname(url.fileURLToPath(import.meta.url))};␊ + ` + +> Error 2/2 + + `␊ + > 1 | const foo = { __dirname};␊ + | ^^^^^^^^^ Do not use "__dirname".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__dirname" with \`"…(import.meta.url)"\`.␊ + 1 | const foo = { __dirname: path.dirname(url.fileURLToPath(import.meta.url))};␊ + ` + +## Invalid #4 + 1 | const foo = {__filename, }; + +> Error 1/2 + + `␊ + > 1 | const foo = {__filename, };␊ + | ^^^^^^^^^^ Do not use "__filename".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__filename" with \`"…(import.meta.url)"\`.␊ + 1 | const foo = {__filename: url.fileURLToPath(import.meta.url), };␊ + ` + +> Error 2/2 + + `␊ + > 1 | const foo = {__filename, };␊ + | ^^^^^^^^^^ Do not use "__filename".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__filename" with \`"…(import.meta.url)"\`.␊ + 1 | const foo = {__filename: url.fileURLToPath(import.meta.url), };␊ + ` + +## Invalid #5 + 1 | if (__dirname.startsWith("/project/src/")) {} + +> Error 1/1 + + `␊ + > 1 | if (__dirname.startsWith("/project/src/")) {}␊ + | ^^^^^^^^^ Do not use "__dirname".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__dirname" with \`"…(import.meta.url)"\`.␊ + 1 | if (path.dirname(url.fileURLToPath(import.meta.url)).startsWith("/project/src/")) {}␊ + ` + +## Invalid #6 + 1 | if (__filename.endsWith(".js")) {} + +> Error 1/1 + + `␊ + > 1 | if (__filename.endsWith(".js")) {}␊ + | ^^^^^^^^^^ Do not use "__filename".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Replace "__filename" with \`"…(import.meta.url)"\`.␊ + 1 | if (url.fileURLToPath(import.meta.url).endsWith(".js")) {}␊ + ` + +## Invalid #1 + 1 | require("foo"); + +> Error 1/1 + + `␊ + > 1 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import "foo";␊ + ` + +## Invalid #2 + 1 | require('foo'); + +> Error 1/1 + + `␊ + > 1 | require('foo');␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import 'foo';␊ + ` + +## Invalid #3 + 1 | require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import "foo" ;␊ + ` + +## Invalid #4 + 1 | ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import "foo";␊ + ` + +## Invalid #5 + 1 | (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import "foo" ;␊ + ` + +## Invalid #6 + 1 | const foo=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const foo=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo";␊ + ` + +## Invalid #7 + 1 | const foo = require.resolve("foo"); + +> Error 1/1 + + `␊ + > 1 | const foo = require.resolve("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #8 + 1 | const foo + 2 | = + 3 | require("foo"); + +> Error 1/1 + + `␊ + 1 | const foo␊ + 2 | =␊ + > 3 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo";␊ + ` + +## Invalid #9 + 1 | const foo = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const foo = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo";␊ + ` + +## Invalid #10 + 1 | const foo = require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | const foo = require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo" ;␊ + ` + +## Invalid #11 + 1 | const foo = ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | const foo = ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo";␊ + ` + +## Invalid #12 + 1 | const foo = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const foo = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import foo from "foo" ;␊ + ` + +## Invalid #13 + 1 | const {foo}=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo}=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo";␊ + ` + +## Invalid #14 + 1 | const {foo} + 2 | = + 3 | require("foo"); + +> Error 1/1 + + `␊ + 1 | const {foo}␊ + 2 | =␊ + > 3 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo";␊ + ` + +## Invalid #15 + 1 | const {foo} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo";␊ + ` + +## Invalid #16 + 1 | const {foo} = require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | const {foo} = require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo" ;␊ + ` + +## Invalid #17 + 1 | const {foo} = ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo} = ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo";␊ + ` + +## Invalid #18 + 1 | const {foo} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo" ;␊ + ` + +## Invalid #19 + 1 | const {foo} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo} from "foo" ;␊ + ` + +## Invalid #20 + 1 | const {foo: foo}=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo}=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo";␊ + ` + +## Invalid #21 + 1 | const {foo: foo} + 2 | = + 3 | require("foo"); + +> Error 1/1 + + `␊ + 1 | const {foo: foo}␊ + 2 | =␊ + > 3 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo";␊ + ` + +## Invalid #22 + 1 | const {foo: foo} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo";␊ + ` + +## Invalid #23 + 1 | const {foo: foo} = require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo} = require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo" ;␊ + ` + +## Invalid #24 + 1 | const {foo: foo} = ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo} = ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo";␊ + ` + +## Invalid #25 + 1 | const {foo: foo} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo" ;␊ + ` + +## Invalid #26 + 1 | const {foo: foo} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo: foo} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as foo} from "foo" ;␊ + ` + +## Invalid #27 + 1 | const {foo:bar}=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar}=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo";␊ + ` + +## Invalid #28 + 1 | const {foo:bar} + 2 | = + 3 | require("foo"); + +> Error 1/1 + + `␊ + 1 | const {foo:bar}␊ + 2 | =␊ + > 3 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo";␊ + ` + +## Invalid #29 + 1 | const {foo:bar} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo";␊ + ` + +## Invalid #30 + 1 | const {foo:bar} = require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar} = require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo" ;␊ + ` + +## Invalid #31 + 1 | const {foo:bar} = ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar} = ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo";␊ + ` + +## Invalid #32 + 1 | const {foo:bar} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo" ;␊ + ` + +## Invalid #33 + 1 | const {foo:bar} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {foo:bar} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {foo as bar} from "foo" ;␊ + ` + +## Invalid #34 + 1 | const {a :foo, b: bar, default : baz}=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz}=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo";␊ + ` + +## Invalid #35 + 1 | const { + 2 | a :foo, + 3 | b: bar, + 4 | default : baz, + 5 | } + 6 | = + 7 | require("foo"); + +> Error 1/1 + + `␊ + 1 | const {␊ + 2 | a :foo,␊ + 3 | b: bar,␊ + 4 | default : baz,␊ + 5 | }␊ + 6 | =␊ + > 7 | require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {␊ + 2 | a as foo,␊ + 3 | b as bar,␊ + 4 | default as baz,␊ + 5 | } from "foo";␊ + ` + +## Invalid #36 + 1 | const {a :foo, b: bar, default : baz} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo";␊ + ` + +## Invalid #37 + 1 | const {a :foo, b: bar, default : baz} = require( (("foo")) ); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz} = require( (("foo")) );␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo" ;␊ + ` + +## Invalid #38 + 1 | const {a :foo, b: bar, default : baz} = ((require))("foo"); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz} = ((require))("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo";␊ + ` + +## Invalid #39 + 1 | const {a :foo, b: bar, default : baz} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo" ;␊ + ` + +## Invalid #40 + 1 | const {a :foo, b: bar, default : baz} = (( require("foo") )); + +> Error 1/1 + + `␊ + > 1 | const {a :foo, b: bar, default : baz} = (( require("foo") ));␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {a as foo, b as bar, default as baz} from "foo" ;␊ + ` + +## Invalid #41 + 1 | const {} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import {} from "foo";␊ + ` + +## Invalid #42 + 1 | const{ }=require("foo"); + +> Error 1/1 + + `␊ + > 1 | const{ }=require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`import\`.␊ + 1 | import{ } from "foo";␊ + ` + +## Invalid #43 + 1 | const r = require; + 2 | const foo = r("foo"); + +> Error 1/1 + + `␊ + > 1 | const r = require;␊ + | ^^^^^^^ Do not use "require".␊ + 2 | const foo = r("foo");␊ + ` + +## Invalid #44 + 1 | new require("foo") + +> Error 1/1 + + `␊ + > 1 | new require("foo")␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #45 + 1 | require("foo", extraArgument) + +> Error 1/1 + + `␊ + > 1 | require("foo", extraArgument)␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #46 + 1 | const a = require() + +> Error 1/1 + + `␊ + > 1 | const a = require()␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #47 + 1 | require(..."foo") + +> Error 1/1 + + `␊ + > 1 | require(..."foo")␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #48 + 1 | require("../" + "file.js") + +> Error 1/1 + + `␊ + > 1 | require("../" + "file.js")␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #49 + 1 | require(file) + +> Error 1/1 + + `␊ + > 1 | require(file)␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #50 + 1 | a = require("foo") + +> Error 1/1 + + `␊ + > 1 | a = require("foo")␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #51 + 1 | function a(a = require("foo")) {} + +> Error 1/1 + + `␊ + > 1 | function a(a = require("foo")) {}␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #52 + 1 | let foo = require("foo"); + +> Error 1/1 + + `␊ + > 1 | let foo = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #53 + 1 | const foo = require("foo"), bar = require("bar"); + +> Error 1/2 + + `␊ + > 1 | const foo = require("foo"), bar = require("bar");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +> Error 2/2 + + `␊ + > 1 | const foo = require("foo"), bar = require("bar");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #54 + 1 | const {[foo]: foo} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {[foo]: foo} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #55 + 1 | const {["foo"]: foo} = require("foo"); + +> Error 1/1 + + `␊ + > 1 | const {["foo"]: foo} = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #56 + 1 | if (foo) require("foo"); + +> Error 1/1 + + `␊ + > 1 | if (foo) require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #57 + 1 | const foo = require("foo"), bar = 1; + +> Error 1/1 + + `␊ + > 1 | const foo = require("foo"), bar = 1;␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #58 + 1 | const foo = require("foo"), bar = require("bar"); + +> Error 1/2 + + `␊ + > 1 | const foo = require("foo"), bar = require("bar");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +> Error 2/2 + + `␊ + > 1 | const foo = require("foo"), bar = require("bar");␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #1 + 1 | exports = foo; + +> Error 1/1 + + `␊ + > 1 | exports = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default foo;␊ + ` + +## Invalid #2 + 1 | module.exports = foo; + +> Error 1/1 + + `␊ + > 1 | module.exports = foo;␊ + | ^^^^^^ Do not use "module".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default foo;␊ + ` + +## Invalid #3 + 1 | (( ((exports)) = ((foo)) )); + +> Error 1/1 + + `␊ + > 1 | (( ((exports)) = ((foo)) ));␊ + | ^^^^^^^ Do not use "exports".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default ((foo)) ;␊ + ` + +## Invalid #4 + 1 | (( ((module.exports)) = ((foo)) )); + +> Error 1/1 + + `␊ + > 1 | (( ((module.exports)) = ((foo)) ));␊ + | ^^^^^^ Do not use "module".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default ((foo)) ;␊ + ` + +## Invalid #5 + 1 | exports.foo = foo; + +> Error 1/1 + + `␊ + > 1 | exports.foo = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export {foo as foo};␊ + ` + +## Invalid #6 + 1 | module.exports.foo = foo; + +> Error 1/1 + + `␊ + > 1 | module.exports.foo = foo;␊ + | ^^^^^^ Do not use "module".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export {foo as foo};␊ + ` + +## Invalid #7 + 1 | exports["foo"] = foo; + +> Error 1/1 + + `␊ + > 1 | exports["foo"] = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #8 + 1 | module.exports["foo"] = foo; + +> Error 1/1 + + `␊ + > 1 | module.exports["foo"] = foo;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #9 + 1 | const foo = exports; + +> Error 1/1 + + `␊ + > 1 | const foo = exports;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #10 + 1 | const foo = exports.foo; + +> Error 1/1 + + `␊ + > 1 | const foo = exports.foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #11 + 1 | const foo = module.exports; + +> Error 1/1 + + `␊ + > 1 | const foo = module.exports;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #12 + 1 | const foo = module.exports.foo; + +> Error 1/1 + + `␊ + > 1 | const foo = module.exports.foo;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #13 + 1 | module["exports"] = foo; + +> Error 1/1 + + `␊ + > 1 | module["exports"] = foo;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #14 + 1 | module[exports] = foo; + +> Error 1/2 + + `␊ + > 1 | module[exports] = foo;␊ + | ^^^^^^ Do not use "module".␊ + ` + +> Error 2/2 + + `␊ + > 1 | module[exports] = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #15 + 1 | module.exports.foo.bar = foo; + +> Error 1/1 + + `␊ + > 1 | module.exports.foo.bar = foo;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #16 + 1 | exports.default = foo; + +> Error 1/1 + + `␊ + > 1 | exports.default = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export {foo as default};␊ + ` + +## Invalid #17 + 1 | module.exports.default = foo; + +> Error 1/1 + + `␊ + > 1 | module.exports.default = foo;␊ + | ^^^^^^ Do not use "module".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export {foo as default};␊ + ` + +## Invalid #18 + 1 | exports.foo.bar = foo; + +> Error 1/1 + + `␊ + > 1 | exports.foo.bar = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #19 + 1 | exports = 1; + +> Error 1/1 + + `␊ + > 1 | exports = 1;␊ + | ^^^^^^^ Do not use "exports".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default 1;␊ + ` + +## Invalid #20 + 1 | exports.foo = []; + +> Error 1/1 + + `␊ + > 1 | exports.foo = [];␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #21 + 1 | module.exports = function() {}; + +> Error 1/1 + + `␊ + > 1 | module.exports = function() {};␊ + | ^^^^^^ Do not use "module".␊ + ␊ + --------------------------------------------------------------------------------␊ + Suggestion 1/1: Switch to \`export\`.␊ + 1 | export default function() {};␊ + ` + +## Invalid #22 + 1 | module.exports.foo = foo || bar; + +> Error 1/1 + + `␊ + > 1 | module.exports.foo = foo || bar;␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #23 + 1 | exports += foo; + +> Error 1/1 + + `␊ + > 1 | exports += foo;␊ + | ^^^^^^^ Do not use "exports".␊ + ` + +## Invalid #24 + 1 | module.exports &= foo; + +> Error 1/1 + + `␊ + > 1 | module.exports &= foo;␊ + | ^^^^^^ Do not use "module".␊ + ` diff --git a/test/snapshots/prefer-module.mjs.snap b/test/snapshots/prefer-module.mjs.snap new file mode 100644 index 0000000000000000000000000000000000000000..1caffe352281252ab5490f2af2d783d492e4b421 GIT binary patch literal 3953 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 Date: Tue, 13 Apr 2021 17:41:42 +0800 Subject: [PATCH 2/7] More tests --- docs/rules/prefer-module.md | 18 +++++- rules/prefer-module.js | 39 ++++-------- test/prefer-module.mjs | 21 ++++++- test/snapshots/prefer-module.mjs.md | 84 ++++++++++++++++++++++++-- test/snapshots/prefer-module.mjs.snap | Bin 3953 -> 4201 bytes 5 files changed, 128 insertions(+), 34 deletions(-) diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md index d7f024ff9d..145d83fb3f 100644 --- a/docs/rules/prefer-module.md +++ b/docs/rules/prefer-module.md @@ -14,15 +14,24 @@ Prefer use ESM over legacy CommonJS module. It's not available in ESM. + Replacements: + + ```js + import {fileURLToPath} from 'url'; + import path from 'path'; + + const __filename = fileURLToPath(import.meta.url); + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + ``` + 1. Forbid `require(…)` - `import …` is preferred in ESM. + `require(…)` can be replaced by `import …` or `import(…)`. 1. Forbid `exports` and `module.exports` `export …` is preferred in ESM. - ## Fail ```js @@ -43,6 +52,10 @@ if (foo) { const file = path.join(__dirname, 'foo.js'); ``` +```js +const content = fs.readFileSync(__filename, 'utf8'); +``` + ```js const {fromPairs} = require('lodash'); ``` @@ -57,7 +70,6 @@ exports.foo = foo; ## Pass - ```js function run() { if (foo) { diff --git a/rules/prefer-module.js b/rules/prefer-module.js index c3db4341c2..9a9bded308 100644 --- a/rules/prefer-module.js +++ b/rules/prefer-module.js @@ -34,6 +34,15 @@ const identifierSelector = referenceIdentifierSelector([ '__dirname' ]); +function * removeParentheses(nodeOrNodes, fixer, sourceCode) { + for (const node of Array.isArray(nodeOrNodes) ? nodeOrNodes : [nodeOrNodes]) { + const parentheses = getParentheses(node, sourceCode); + for (const token of parentheses) { + yield fixer.remove(token); + } + } +} + function fixRequireCall(node, sourceCode) { if (!isStaticRequire(node.parent) || node.parent.callee !== node) { return; @@ -57,14 +66,7 @@ function fixRequireCall(node, sourceCode) { yield fixer.replaceText(openingParenthesisToken, ' '); const closingParenthesisToken = sourceCode.getLastToken(requireCall); yield fixer.remove(closingParenthesisToken); - - // Remove parentheses - for (const node of [callee, requireCall, source]) { - const parentheses = getParentheses(node, sourceCode); - for (const token of parentheses) { - yield fixer.remove(token); - } - } + yield* removeParentheses([callee, requireCall, source], fixer, sourceCode); }; } @@ -122,12 +124,7 @@ function fixRequireCall(node, sourceCode) { const closingParenthesisToken = sourceCode.getLastToken(requireCall); yield fixer.remove(closingParenthesisToken); - for (const node of [callee, requireCall, source]) { - const parentheses = getParentheses(node, sourceCode); - for (const token of parentheses) { - yield fixer.remove(token); - } - } + yield* removeParentheses([callee, requireCall, source], fixer, sourceCode); if (id.type === 'Identifier') { return; @@ -183,12 +180,7 @@ function fixDefaultExport(node, sourceCode) { yield fixer.remove(equalToken); yield removeSpacesAfter(equalToken, sourceCode, fixer); - for (const nodeToRemove of [node.parent, node]) { - const parentheses = getParentheses(nodeToRemove, sourceCode); - for (const token of parentheses) { - yield fixer.remove(token); - } - } + yield* removeParentheses([node.parent, node], fixer, sourceCode); }; } @@ -199,12 +191,7 @@ function fixNamedExport(node, sourceCode) { const local = assignmentExpression.right.name; yield fixer.replaceText(assignmentExpression, `export {${local} as ${exported}}`); - for (const node of [assignmentExpression]) { - const parentheses = getParentheses(node, sourceCode); - for (const token of parentheses) { - yield fixer.remove(token); - } - } + yield* removeParentheses(assignmentExpression, fixer, sourceCode); }; } diff --git a/test/prefer-module.mjs b/test/prefer-module.mjs index 85c7108264..bc7e01df75 100644 --- a/test/prefer-module.mjs +++ b/test/prefer-module.mjs @@ -200,6 +200,18 @@ test.snapshot({ 'const {[foo]: foo} = require("foo");', 'const {["foo"]: foo} = require("foo");', 'if (foo) require("foo");', + 'const foo = require`foo`;', + outdent` + function loadModule() { + return require("foo"); + } + `, + outdent` + function loadModule() { + const foo = require("foo"); + return foo; + } + `, 'const foo = require("foo"), bar = 1;', 'const foo = require("foo"), bar = require("bar");' ] @@ -246,6 +258,13 @@ test.snapshot({ 'module.exports = function() {};', 'module.exports.foo = foo || bar;', 'exports += foo;', - 'module.exports &= foo;' + 'const foo = module.children', + 'const parentModule = module.parent', + outdent` + function foo() { + exports.foo = foo; + module.exports.foo = foo; + } + ` ] }); diff --git a/test/snapshots/prefer-module.mjs.md b/test/snapshots/prefer-module.mjs.md index c250d9d567..1179914ea9 100644 --- a/test/snapshots/prefer-module.mjs.md +++ b/test/snapshots/prefer-module.mjs.md @@ -940,6 +940,46 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #57 + 1 | const foo = require`foo`; + +> Error 1/1 + + `␊ + > 1 | const foo = require\`foo\`;␊ + | ^^^^^^^ Do not use "require".␊ + ` + +## Invalid #58 + 1 | function loadModule() { + 2 | return require("foo"); + 3 | } + +> Error 1/1 + + `␊ + 1 | function loadModule() {␊ + > 2 | return require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + 3 | }␊ + ` + +## Invalid #59 + 1 | function loadModule() { + 2 | const foo = require("foo"); + 3 | return foo; + 4 | } + +> Error 1/1 + + `␊ + 1 | function loadModule() {␊ + > 2 | const foo = require("foo");␊ + | ^^^^^^^ Do not use "require".␊ + 3 | return foo;␊ + 4 | }␊ + ` + +## Invalid #60 1 | const foo = require("foo"), bar = 1; > Error 1/1 @@ -949,7 +989,7 @@ Generated by [AVA](https://avajs.dev). | ^^^^^^^ Do not use "require".␊ ` -## Invalid #58 +## Invalid #61 1 | const foo = require("foo"), bar = require("bar"); > Error 1/2 @@ -1244,11 +1284,47 @@ Generated by [AVA](https://avajs.dev). ` ## Invalid #24 - 1 | module.exports &= foo; + 1 | const foo = module.children > Error 1/1 `␊ - > 1 | module.exports &= foo;␊ - | ^^^^^^ Do not use "module".␊ + > 1 | const foo = module.children␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #25 + 1 | const parentModule = module.parent + +> Error 1/1 + + `␊ + > 1 | const parentModule = module.parent␊ + | ^^^^^^ Do not use "module".␊ + ` + +## Invalid #26 + 1 | function foo() { + 2 | exports.foo = foo; + 3 | module.exports.foo = foo; + 4 | } + +> Error 1/2 + + `␊ + 1 | function foo() {␊ + > 2 | exports.foo = foo;␊ + | ^^^^^^^ Do not use "exports".␊ + 3 | module.exports.foo = foo;␊ + 4 | }␊ + ` + +> Error 2/2 + + `␊ + 1 | function foo() {␊ + 2 | exports.foo = foo;␊ + > 3 | module.exports.foo = foo;␊ + | ^^^^^^ Do not use "module".␊ + 4 | }␊ ` diff --git a/test/snapshots/prefer-module.mjs.snap b/test/snapshots/prefer-module.mjs.snap index 1caffe352281252ab5490f2af2d783d492e4b421..e4d83f5a96323d757de46c54e90d073d970e4c99 100644 GIT binary patch literal 4201 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 literal 3953 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 Date: Tue, 13 Apr 2021 17:51:42 +0800 Subject: [PATCH 3/7] Lint --- rules/prefer-module.js | 8 ++++---- test/run-rules-on-codebase/lint.mjs | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/rules/prefer-module.js b/rules/prefer-module.js index 9a9bded308..fec9666572 100644 --- a/rules/prefer-module.js +++ b/rules/prefer-module.js @@ -66,7 +66,7 @@ function fixRequireCall(node, sourceCode) { yield fixer.replaceText(openingParenthesisToken, ' '); const closingParenthesisToken = sourceCode.getLastToken(requireCall); yield fixer.remove(closingParenthesisToken); - yield* removeParentheses([callee, requireCall, source], fixer, sourceCode); + yield * removeParentheses([callee, requireCall, source], fixer, sourceCode); }; } @@ -124,7 +124,7 @@ function fixRequireCall(node, sourceCode) { const closingParenthesisToken = sourceCode.getLastToken(requireCall); yield fixer.remove(closingParenthesisToken); - yield* removeParentheses([callee, requireCall, source], fixer, sourceCode); + yield * removeParentheses([callee, requireCall, source], fixer, sourceCode); if (id.type === 'Identifier') { return; @@ -180,7 +180,7 @@ function fixDefaultExport(node, sourceCode) { yield fixer.remove(equalToken); yield removeSpacesAfter(equalToken, sourceCode, fixer); - yield* removeParentheses([node.parent, node], fixer, sourceCode); + yield * removeParentheses([node.parent, node], fixer, sourceCode); }; } @@ -191,7 +191,7 @@ function fixNamedExport(node, sourceCode) { const local = assignmentExpression.right.name; yield fixer.replaceText(assignmentExpression, `export {${local} as ${exported}}`); - yield* removeParentheses(assignmentExpression, fixer, sourceCode); + yield * removeParentheses(assignmentExpression, fixer, sourceCode); }; } diff --git a/test/run-rules-on-codebase/lint.mjs b/test/run-rules-on-codebase/lint.mjs index f9615644a2..90ffaa2df6 100644 --- a/test/run-rules-on-codebase/lint.mjs +++ b/test/run-rules-on-codebase/lint.mjs @@ -31,7 +31,24 @@ const eslint = new ESLint({ ], // https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1109#issuecomment-782689255 'unicorn/consistent-destructuring': 'off' - } + }, + overrides: [ + { + files: [ + // ESLint don't support module + 'rules/**/*.js', + 'index.js', + // `eslint-remote-tester` only support cjs config + 'test/smoke/eslint-remote-tester.config.js', + // TODO: Switch to module + 'scripts/create-rule.js', + 'test/integration/**/*' + ], + rules: { + 'unicorn/prefer-module': 'off' + } + } + ] } }); From 4fbd31a8dab81683408f81cba8ad0afd518408d5 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Tue, 20 Apr 2021 18:30:53 +0700 Subject: [PATCH 4/7] Update prefer-module.md --- docs/rules/prefer-module.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md index 145d83fb3f..d6ea1d09bc 100644 --- a/docs/rules/prefer-module.md +++ b/docs/rules/prefer-module.md @@ -1,18 +1,18 @@ # Prefer ES modules over CommonJS -Prefer use ESM over legacy CommonJS module. +Prefer use [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) over legacy CommonJS module. -1. Forbid `use strict` directive. +1. Forbids `'use strict'` directive. - ESM scripts use Strict Mode by default. + ESM scripts use “Strict Mode” by default. -1. Forbid `Global Return` +1. Forbids “Global Return” This is a CommonJS-only feature. -1. Forbid global variables `__dirname` and `__filename`. +1. Forbids the global variables `__dirname` and `__filename`. - It's not available in ESM. + They are not available in ESM. Replacements: @@ -24,13 +24,13 @@ Prefer use ESM over legacy CommonJS module. const __dirname = path.dirname(fileURLToPath(import.meta.url)); ``` -1. Forbid `require(…)` +1. Forbids `require(…)` `require(…)` can be replaced by `import …` or `import(…)`. -1. Forbid `exports` and `module.exports` +1. Forbids `exports` and `module.exports` - `export …` is preferred in ESM. + `export …` should be used in ESM. ## Fail From ec312944b00fb252d005ca47d512638218c743b7 Mon Sep 17 00:00:00 2001 From: fisker Cheung Date: Wed, 21 Apr 2021 09:52:06 +0800 Subject: [PATCH 5/7] Address review --- docs/rules/prefer-module.md | 2 +- readme.md | 2 +- rules/prefer-module.js | 5 +++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md index d6ea1d09bc..625d272bef 100644 --- a/docs/rules/prefer-module.md +++ b/docs/rules/prefer-module.md @@ -1,4 +1,4 @@ -# Prefer ES modules over CommonJS +# Prefer JavaScript modules (ESM) over CommonJS Prefer use [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) over legacy CommonJS module. diff --git a/readme.md b/readme.md index ed6db55fc7..3e99439072 100644 --- a/readme.md +++ b/readme.md @@ -182,7 +182,7 @@ Each rule has emojis denoting: | [prefer-keyboard-event-key](docs/rules/prefer-keyboard-event-key.md) | Prefer `KeyboardEvent#key` over `KeyboardEvent#keyCode`. | ✅ | 🔧 | | [prefer-math-trunc](docs/rules/prefer-math-trunc.md) | Enforce the use of `Math.trunc` instead of bitwise operators. | ✅ | 🔧 | | [prefer-modern-dom-apis](docs/rules/prefer-modern-dom-apis.md) | Prefer `.before()` over `.insertBefore()`, `.replaceWith()` over `.replaceChild()`, prefer one of `.before()`, `.after()`, `.append()` or `.prepend()` over `insertAdjacentText()` and `insertAdjacentElement()`. | ✅ | 🔧 | -| [prefer-module](docs/rules/prefer-module.md) | Prefer ES modules over CommonJS. | ✅ | 🔧 | +| [prefer-module](docs/rules/prefer-module.md) | Prefer JavaScript modules (ESM) over CommonJS. | ✅ | 🔧 | | [prefer-negative-index](docs/rules/prefer-negative-index.md) | Prefer negative index over `.length - index` for `{String,Array,TypedArray}#slice()` and `Array#splice()`. | ✅ | 🔧 | | [prefer-number-properties](docs/rules/prefer-number-properties.md) | Prefer `Number` static properties over global ones. | ✅ | 🔧 | | [prefer-optional-catch-binding](docs/rules/prefer-optional-catch-binding.md) | Prefer omitting the `catch` binding parameter. | ✅ | 🔧 | diff --git a/rules/prefer-module.js b/rules/prefer-module.js index fec9666572..1694f6cfa0 100644 --- a/rules/prefer-module.js +++ b/rules/prefer-module.js @@ -309,10 +309,11 @@ module.exports = { meta: { type: 'suggestion', docs: { - description: 'Prefer ES modules over CommonJS.', + description: 'Prefer JavaScript modules (ESM) over CommonJS.', url: getDocumentationUrl(__filename) }, fixable: 'code', - messages + messages, + schema: [] } }; From 23ad79dc7da435251cedd5d1718c84777a42149a Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 21 Apr 2021 19:18:41 +0700 Subject: [PATCH 6/7] Update prefer-module.md --- docs/rules/prefer-module.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md index 625d272bef..da0d062b90 100644 --- a/docs/rules/prefer-module.md +++ b/docs/rules/prefer-module.md @@ -1,18 +1,18 @@ # Prefer JavaScript modules (ESM) over CommonJS -Prefer use [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) over legacy CommonJS module. +Prefer using the [JavaScript module](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) format over the legacy CommonJS module format. 1. Forbids `'use strict'` directive. - ESM scripts use “Strict Mode” by default. + JavaScript modules use “Strict Mode” by default. -1. Forbids “Global Return” +1. Forbids “Global Return”. This is a CommonJS-only feature. 1. Forbids the global variables `__dirname` and `__filename`. - They are not available in ESM. + They are [not available in JavaScript modules](https://nodejs.org/api/esm.html#esm_no_filename_or_dirname). Replacements: @@ -24,13 +24,13 @@ Prefer use [ESM](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/M const __dirname = path.dirname(fileURLToPath(import.meta.url)); ``` -1. Forbids `require(…)` +1. Forbids `require(…)`. `require(…)` can be replaced by `import …` or `import(…)`. -1. Forbids `exports` and `module.exports` +1. Forbids `exports` and `module.exports`. - `export …` should be used in ESM. + `export …` should be used in JavaScript modules. ## Fail From dec3cad77d54993fb17c300ad5b947354d158c45 Mon Sep 17 00:00:00 2001 From: Sindre Sorhus Date: Wed, 21 Apr 2021 19:22:17 +0700 Subject: [PATCH 7/7] Update prefer-module.md --- docs/rules/prefer-module.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/rules/prefer-module.md b/docs/rules/prefer-module.md index da0d062b90..d1205baa32 100644 --- a/docs/rules/prefer-module.md +++ b/docs/rules/prefer-module.md @@ -23,6 +23,20 @@ Prefer using the [JavaScript module](https://developer.mozilla.org/en-US/docs/We const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(fileURLToPath(import.meta.url)); ``` + + However, in most cases, this is better: + + ```js + import {fileURLToPath} from 'url'; + + const foo = fileURLToPath(new URL('foo.js', import.meta.url)); + ``` + + And many Node.js APIs accept `URL` directly, so you can just do this: + + ```js + const foo = new URL('foo.js', import.meta.url); + ``` 1. Forbids `require(…)`.