diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js index 977b58fadb3af..abb6d599f8de1 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRuleExhaustiveDeps-test.js @@ -9,7 +9,8 @@ 'use strict'; -const ESLintTester = require('eslint').RuleTester; +const ESLintTesterV7 = require('eslint-v7').RuleTester; +const ESLintTesterV9 = require('eslint-v9').RuleTester; const ReactHooksESLintPlugin = require('eslint-plugin-react-hooks'); const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['exhaustive-deps']; @@ -8223,8 +8224,15 @@ if (!process.env.CI) { testsTypescript.invalid = testsTypescript.invalid.filter(predicate); } -describe('react-hooks', () => { - const languageOptions = { +describe('rules-of-hooks/exhaustive-deps', () => { + const parserOptionsV7 = { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 6, + sourceType: 'module', + }; + const languageOptionsV9 = { ecmaVersion: 6, sourceType: 'module', parserOptions: { @@ -8239,13 +8247,22 @@ describe('react-hooks', () => { invalid: [...testsFlow.invalid, ...tests.invalid], }; - new ESLintTester({ + new ESLintTesterV7({ + parser: require.resolve('babel-eslint'), + parserOptions: parserOptionsV7, + }).run( + 'eslint: v7, parser: babel-eslint', + ReactHooksESLintRule, + testsBabelEslint + ); + + new ESLintTesterV9({ languageOptions: { - ...languageOptions, + ...languageOptionsV9, parser: require('@babel/eslint-parser'), }, }).run( - 'parser: @babel/eslint-parser', + 'eslint: v9, parser: @babel/eslint-parser', ReactHooksESLintRule, testsBabelEslint ); @@ -8255,57 +8272,119 @@ describe('react-hooks', () => { invalid: [...testsTypescript.invalid, ...tests.invalid], }; - new ESLintTester({ + new ESLintTesterV7({ + parser: require.resolve('@typescript-eslint/parser-v2'), + parserOptions: parserOptionsV7, + }).run( + 'eslint: v9, parser: @typescript-eslint/parser@2.x', + ReactHooksESLintRule, + testsTypescriptEslintParser + ); + + new ESLintTesterV9({ languageOptions: { - ...languageOptions, + ...languageOptionsV9, parser: require('@typescript-eslint/parser-v2'), }, }).run( - 'parser: @typescript-eslint/parser@2.x', + 'eslint: v9, parser: @typescript-eslint/parser@2.x', ReactHooksESLintRule, testsTypescriptEslintParser ); - new ESLintTester({ + new ESLintTesterV7({ + parser: require.resolve('@typescript-eslint/parser-v3'), + parserOptions: parserOptionsV7, + }).run( + 'eslint: v7, parser: @typescript-eslint/parser@3.x', + ReactHooksESLintRule, + testsTypescriptEslintParser + ); + + new ESLintTesterV9({ languageOptions: { - ...languageOptions, + ...languageOptionsV9, parser: require('@typescript-eslint/parser-v3'), }, }).run( - 'parser: @typescript-eslint/parser@3.x', + 'eslint: v9, parser: @typescript-eslint/parser@3.x', ReactHooksESLintRule, testsTypescriptEslintParser ); - new ESLintTester({ + new ESLintTesterV7({ + parser: require.resolve('@typescript-eslint/parser-v4'), + parserOptions: parserOptionsV7, + }).run( + 'eslint: v7, parser: @typescript-eslint/parser@4.x', + ReactHooksESLintRule, + { + valid: [ + ...testsTypescriptEslintParserV4.valid, + ...testsTypescriptEslintParser.valid, + ], + invalid: [ + ...testsTypescriptEslintParserV4.invalid, + ...testsTypescriptEslintParser.invalid, + ], + } + ); + + new ESLintTesterV9({ languageOptions: { - ...languageOptions, + ...languageOptionsV9, parser: require('@typescript-eslint/parser-v4'), }, - }).run('parser: @typescript-eslint/parser@4.x', ReactHooksESLintRule, { - valid: [ - ...testsTypescriptEslintParserV4.valid, - ...testsTypescriptEslintParser.valid, - ], - invalid: [ - ...testsTypescriptEslintParserV4.invalid, - ...testsTypescriptEslintParser.invalid, - ], - }); + }).run( + 'eslint: v9, parser: @typescript-eslint/parser@4.x', + ReactHooksESLintRule, + { + valid: [ + ...testsTypescriptEslintParserV4.valid, + ...testsTypescriptEslintParser.valid, + ], + invalid: [ + ...testsTypescriptEslintParserV4.invalid, + ...testsTypescriptEslintParser.invalid, + ], + } + ); - new ESLintTester({ + new ESLintTesterV7({ + parser: require.resolve('@typescript-eslint/parser-v5'), + parserOptions: parserOptionsV7, + }).run( + 'eslint: v7, parser: @typescript-eslint/parser@^5.0.0-0', + ReactHooksESLintRule, + { + valid: [ + ...testsTypescriptEslintParserV4.valid, + ...testsTypescriptEslintParser.valid, + ], + invalid: [ + ...testsTypescriptEslintParserV4.invalid, + ...testsTypescriptEslintParser.invalid, + ], + } + ); + + new ESLintTesterV9({ languageOptions: { - ...languageOptions, + ...languageOptionsV9, parser: require('@typescript-eslint/parser-v5'), }, - }).run('parser: @typescript-eslint/parser@^5.0.0-0', ReactHooksESLintRule, { - valid: [ - ...testsTypescriptEslintParserV4.valid, - ...testsTypescriptEslintParser.valid, - ], - invalid: [ - ...testsTypescriptEslintParserV4.invalid, - ...testsTypescriptEslintParser.invalid, - ], - }); + }).run( + 'eslint: v9, parser: @typescript-eslint/parser@^5.0.0-0', + ReactHooksESLintRule, + { + valid: [ + ...testsTypescriptEslintParserV4.valid, + ...testsTypescriptEslintParser.valid, + ], + invalid: [ + ...testsTypescriptEslintParserV4.invalid, + ...testsTypescriptEslintParser.invalid, + ], + } + ); }); diff --git a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js index 9394bb8b97e5a..a98d2b76961f7 100644 --- a/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js +++ b/packages/eslint-plugin-react-hooks/__tests__/ESLintRulesOfHooks-test.js @@ -9,19 +9,12 @@ 'use strict'; -const ESLintTester = require('eslint').RuleTester; +const ESLintTesterV7 = require('eslint-v7').RuleTester; +const ESLintTesterV9 = require('eslint-v9').RuleTester; const ReactHooksESLintPlugin = require('eslint-plugin-react-hooks'); const BabelEslintParser = require('@babel/eslint-parser'); const ReactHooksESLintRule = ReactHooksESLintPlugin.rules['rules-of-hooks']; -ESLintTester.setDefaultConfig({ - languageOptions: { - parser: BabelEslintParser, - ecmaVersion: 6, - sourceType: 'module', - }, -}); - /** * A string template tag that removes padding from the left side of multi-line strings * @param {Array} strings array of code strings (only one expected) @@ -1464,5 +1457,20 @@ if (!process.env.CI) { tests.invalid = tests.invalid.filter(predicate); } -const eslintTester = new ESLintTester(); -eslintTester.run('react-hooks', ReactHooksESLintRule, tests); +describe('rules-of-hooks/rules-of-hooks', () => { + new ESLintTesterV7({ + parser: require.resolve('babel-eslint'), + parserOptions: { + ecmaVersion: 6, + sourceType: 'module', + }, + }).run('eslint: v7', ReactHooksESLintRule, tests); + + new ESLintTesterV9({ + languageOptions: { + parser: BabelEslintParser, + ecmaVersion: 6, + sourceType: 'module', + }, + }).run('eslint: v9', ReactHooksESLintRule, tests); +}); diff --git a/packages/eslint-plugin-react-hooks/package.json b/packages/eslint-plugin-react-hooks/package.json index a0f2a71853403..805231904b01e 100644 --- a/packages/eslint-plugin-react-hooks/package.json +++ b/packages/eslint-plugin-react-hooks/package.json @@ -28,7 +28,7 @@ }, "homepage": "https://react.dev/", "peerDependencies": { - "eslint": "^9.0.0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" }, "devDependencies": { "@babel/eslint-parser": "^7.11.4", @@ -36,6 +36,8 @@ "@typescript-eslint/parser-v3": "npm:@typescript-eslint/parser@^3.10.0", "@typescript-eslint/parser-v4": "npm:@typescript-eslint/parser@^4.1.0", "@typescript-eslint/parser-v5": "npm:@typescript-eslint/parser@^5.0.0-0", - "eslint": "^9.0.0" + "babel-eslint": "^10.0.3", + "eslint-v7": "npm:eslint@^7.7.0", + "eslint-v9": "npm:eslint@^9.0.0" } } diff --git a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js index 9704347433b00..ca2a42eaa0dfc 100644 --- a/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js +++ b/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js @@ -67,6 +67,27 @@ export default { context.report(problem); } + /** + * SourceCode#getText that also works down to ESLint 3.0.0 + */ + function getSource(node) { + if (typeof context.getSource === 'function') { + return context.getSource(node); + } else { + return context.sourceCode.getText(node); + } + } + /** + * SourceCode#getScope that also works down to ESLint 3.0.0 + */ + function getScope(node) { + if (typeof context.getScope === 'function') { + return context.getScope(); + } else { + return context.sourceCode.getScope(node); + } + } + const scopeManager = context.getSourceCode().scopeManager; // Should be shared between visitors. @@ -526,13 +547,11 @@ export default { node: writeExpr, message: `Assignments to the '${key}' variable from inside React Hook ` + - `${context.sourceCode.getText( - reactiveHook, - )} will be lost after each ` + + `${getSource(reactiveHook)} will be lost after each ` + `render. To preserve the value over time, store it in a useRef ` + `Hook and keep the mutable value in the '.current' property. ` + `Otherwise, you can move this variable directly inside ` + - `${context.sourceCode.getText(reactiveHook)}.`, + `${getSource(reactiveHook)}.`, }); } @@ -632,9 +651,7 @@ export default { reportProblem({ node: declaredDependenciesNode, message: - `React Hook ${context.sourceCode.getText( - reactiveHook, - )} was passed a ` + + `React Hook ${getSource(reactiveHook)} was passed a ` + 'dependency list that is not an array literal. This means we ' + "can't statically verify whether you've passed the correct " + 'dependencies.', @@ -654,9 +671,7 @@ export default { reportProblem({ node: declaredDependencyNode, message: - `React Hook ${context.sourceCode.getText( - reactiveHook, - )} has a spread ` + + `React Hook ${getSource(reactiveHook)} has a spread ` + "element in its dependency array. This means we can't " + "statically verify whether you've passed the " + 'correct dependencies.', @@ -668,12 +683,12 @@ export default { node: declaredDependencyNode, message: 'Functions returned from `useEffectEvent` must not be included in the dependency array. ' + - `Remove \`${context.sourceCode.getText( + `Remove \`${getSource( declaredDependencyNode, )}\` from the list.`, suggest: [ { - desc: `Remove the dependency \`${context.sourceCode.getText( + desc: `Remove the dependency \`${getSource( declaredDependencyNode, )}\``, fix(fixer) { @@ -714,9 +729,7 @@ export default { reportProblem({ node: declaredDependencyNode, message: - `React Hook ${context.sourceCode.getText( - reactiveHook, - )} has a ` + + `React Hook ${getSource(reactiveHook)} has a ` + `complex expression in the dependency array. ` + 'Extract it to a separate variable so it can be statically checked.', }); @@ -986,7 +999,7 @@ export default { ` However, 'props' will change when *any* prop changes, so the ` + `preferred fix is to destructure the 'props' object outside of ` + `the ${reactiveHookName} call and refer to those specific props ` + - `inside ${context.sourceCode.getText(reactiveHook)}.`; + `inside ${getSource(reactiveHook)}.`; } } @@ -1136,7 +1149,7 @@ export default { reportProblem({ node: declaredDependenciesNode, message: - `React Hook ${context.sourceCode.getText(reactiveHook)} has ` + + `React Hook ${getSource(reactiveHook)} has ` + // To avoid a long message, show the next actionable item. (getWarningMessage(missingDependencies, 'a', 'missing', 'include') || getWarningMessage( @@ -1258,9 +1271,7 @@ export default { return; // Handled } // We'll do our best effort to find it, complain otherwise. - const variable = context.sourceCode - .getScope(callback) - .set.get(callback.name); + const variable = getScope(callback).set.get(callback.name); if (variable == null || variable.defs == null) { // If it's not in scope, we don't care. return; // Handled @@ -1804,7 +1815,7 @@ function getReactiveHookCallbackIndex(calleeNode, options) { } /** - * ESLint won't assign node.parent to references from context.sourceCode.getScope() + * ESLint won't assign node.parent to references from context.getScope() * * So instead we search for the node from an ancestor assigning node.parent * as we go. This mutates the AST. diff --git a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js index 3bda5076be600..028fbab9febf1 100644 --- a/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js +++ b/packages/eslint-plugin-react-hooks/src/RulesOfHooks.js @@ -148,6 +148,27 @@ export default { } } + /** + * SourceCode#getText that also works down to ESLint 3.0.0 + */ + function getSource(node) { + if (typeof context.getSource === 'function') { + return context.getSource(node); + } else { + return context.sourceCode.getText(node); + } + } + /** + * SourceCode#getScope that also works down to ESLint 3.0.0 + */ + function getScope(node) { + if (typeof context.getScope === 'function') { + return context.getScope(); + } else { + return context.sourceCode.getScope(node); + } + } + return { // Maintain code segment path stack as we traverse. onCodePathSegmentStart: segment => codePathSegmentStack.push(segment), @@ -466,9 +487,7 @@ export default { context.report({ node: hook, message: - `React Hook "${context.sourceCode.getText( - hook, - )}" may be executed ` + + `React Hook "${getSource(hook)}" may be executed ` + 'more than once. Possibly because it is called in a loop. ' + 'React Hooks must be called in the exact same order in ' + 'every component render.', @@ -487,9 +506,8 @@ export default { context.report({ node: hook, message: - `React Hook "${context.sourceCode.getText( - hook, - )}" cannot be ` + 'called in an async function.', + `React Hook "${getSource(hook)}" cannot be ` + + 'called in an async function.', }); } @@ -503,9 +521,7 @@ export default { !isUseIdentifier(hook) // `use(...)` can be called conditionally. ) { const message = - `React Hook "${context.sourceCode.getText( - hook, - )}" is called ` + + `React Hook "${getSource(hook)}" is called ` + 'conditionally. React Hooks must be called in the exact ' + 'same order in every component render.' + (possiblyHasEarlyReturn @@ -522,21 +538,15 @@ export default { ) { // Custom message for hooks inside a class const message = - `React Hook "${context.sourceCode.getText( - hook, - )}" cannot be called ` + + `React Hook "${getSource(hook)}" cannot be called ` + 'in a class component. React Hooks must be called in a ' + 'React function component or a custom React Hook function.'; context.report({node: hook, message}); } else if (codePathFunctionName) { // Custom message if we found an invalid function name. const message = - `React Hook "${context.sourceCode.getText( - hook, - )}" is called in ` + - `function "${context.sourceCode.getText( - codePathFunctionName, - )}" ` + + `React Hook "${getSource(hook)}" is called in ` + + `function "${getSource(codePathFunctionName)}" ` + 'that is neither a React function component nor a custom ' + 'React Hook function.' + ' React component names must start with an uppercase letter.' + @@ -545,9 +555,7 @@ export default { } else if (codePathNode.type === 'Program') { // These are dangerous if you have inline requires enabled. const message = - `React Hook "${context.sourceCode.getText( - hook, - )}" cannot be called ` + + `React Hook "${getSource(hook)}" cannot be called ` + 'at the top level. React Hooks must be called in a ' + 'React function component or a custom React Hook function.'; context.report({node: hook, message}); @@ -560,9 +568,7 @@ export default { // `use(...)` can be called in callbacks. if (isSomewhereInsideComponentOrHook && !isUseIdentifier(hook)) { const message = - `React Hook "${context.sourceCode.getText( - hook, - )}" cannot be called ` + + `React Hook "${getSource(hook)}" cannot be called ` + 'inside a callback. React Hooks must be called in a ' + 'React function component or a custom React Hook function.'; context.report({node: hook, message}); @@ -615,7 +621,7 @@ export default { context.report({ node, message: - `\`${context.sourceCode.getText( + `\`${getSource( node, )}\` is a function created with React Hook "useEffectEvent", and can only be called from ` + 'the same component. They cannot be assigned to variables or passed down.', @@ -632,14 +638,14 @@ export default { FunctionDeclaration(node) { // function MyComponent() { const onClick = useEffectEvent(...) } if (isInsideComponentOrHook(node)) { - recordAllUseEffectEventFunctions(context.sourceCode.getScope(node)); + recordAllUseEffectEventFunctions(getScope(node)); } }, ArrowFunctionExpression(node) { // const MyComponent = () => { const onClick = useEffectEvent(...) } if (isInsideComponentOrHook(node)) { - recordAllUseEffectEventFunctions(context.sourceCode.getScope(node)); + recordAllUseEffectEventFunctions(getScope(node)); } }, }; diff --git a/yarn.lock b/yarn.lock index 8e6f7d919cb45..c2052e8341e79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4397,6 +4397,18 @@ babel-core@^7.0.0-bridge: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== +babel-eslint@^10.0.3: + version "10.0.3" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" + integrity sha512-z3U7eMY6r/3f3/JB9mTsLjyxrv0Yb1zb8PCWCLpguxfCzBIZUwy23R1t/XKewP+8mEN2Ck8Dtr4q20z6ce6SoA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-visitor-keys "^1.0.0" + resolve "^1.12.0" + babel-eslint@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-9.0.0.tgz#7d9445f81ed9f60aff38115f838970df9f2b6220" @@ -7151,84 +7163,7 @@ eslint-utils@^2.0.0, eslint-utils@^2.1.0: dependencies: eslint-visitor-keys "^1.1.0" -eslint-visitor-keys@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" - integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== - -eslint-visitor-keys@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" - integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== - -eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" - integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== - -eslint-visitor-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" - integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== - -eslint-visitor-keys@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186" - integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q== - -eslint-visitor-keys@^3.3.0: - version "3.4.3" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" - integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== - -eslint-visitor-keys@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" - integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== - -eslint@5.16.0: - version "5.16.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" - integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== - dependencies: - "@babel/code-frame" "^7.0.0" - ajv "^6.9.1" - chalk "^2.1.0" - cross-spawn "^6.0.5" - debug "^4.0.1" - doctrine "^3.0.0" - eslint-scope "^4.0.3" - eslint-utils "^1.3.1" - eslint-visitor-keys "^1.0.0" - espree "^5.0.1" - esquery "^1.0.1" - esutils "^2.0.2" - file-entry-cache "^5.0.1" - functional-red-black-tree "^1.0.1" - glob "^7.1.2" - globals "^11.7.0" - ignore "^4.0.6" - import-fresh "^3.0.0" - imurmurhash "^0.1.4" - inquirer "^6.2.2" - js-yaml "^3.13.0" - json-stable-stringify-without-jsonify "^1.0.1" - levn "^0.3.0" - lodash "^4.17.11" - minimatch "^3.0.4" - mkdirp "^0.5.1" - natural-compare "^1.4.0" - optionator "^0.8.2" - path-is-inside "^1.0.2" - progress "^2.0.0" - regexpp "^2.0.1" - semver "^5.5.1" - strip-ansi "^4.0.0" - strip-json-comments "^2.0.1" - table "^5.2.3" - text-table "^0.2.0" - -eslint@^7.7.0: +"eslint-v7@npm:eslint@^7.7.0", eslint@^7.7.0: version "7.32.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.32.0.tgz#c6d328a14be3fb08c8d1d21e12c02fdb7a2a812d" integrity sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA== @@ -7274,7 +7209,7 @@ eslint@^7.7.0: text-table "^0.2.0" v8-compile-cache "^2.0.3" -eslint@^9.0.0: +"eslint-v9@npm:eslint@^9.0.0": version "9.0.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.0.0.tgz#6270548758e390343f78c8afd030566d86927d40" integrity sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q== @@ -7314,6 +7249,83 @@ eslint@^9.0.0: strip-ansi "^6.0.1" text-table "^0.2.0" +eslint-visitor-keys@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz#74415ac884874495f78ec2a97349525344c981fa" + integrity sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ== + +eslint-visitor-keys@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2" + integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A== + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint-visitor-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.0.0.tgz#e32e99c6cdc2eb063f204eda5db67bfe58bb4186" + integrity sha512-mJOZa35trBTb3IyRmo8xmKBZlxf+N7OnUl4+ZhJHs/r+0770Wh/LEACE2pqMGMe27G/4y8P2bYGk4J70IC5k1Q== + +eslint-visitor-keys@^3.3.0: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + +eslint@5.16.0: + version "5.16.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" + integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== + dependencies: + "@babel/code-frame" "^7.0.0" + ajv "^6.9.1" + chalk "^2.1.0" + cross-spawn "^6.0.5" + debug "^4.0.1" + doctrine "^3.0.0" + eslint-scope "^4.0.3" + eslint-utils "^1.3.1" + eslint-visitor-keys "^1.0.0" + espree "^5.0.1" + esquery "^1.0.1" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob "^7.1.2" + globals "^11.7.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + inquirer "^6.2.2" + js-yaml "^3.13.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.3.0" + lodash "^4.17.11" + minimatch "^3.0.4" + mkdirp "^0.5.1" + natural-compare "^1.4.0" + optionator "^0.8.2" + path-is-inside "^1.0.2" + progress "^2.0.0" + regexpp "^2.0.1" + semver "^5.5.1" + strip-ansi "^4.0.0" + strip-json-comments "^2.0.1" + table "^5.2.3" + text-table "^0.2.0" + espree@6.2.1: version "6.2.1" resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a" @@ -13691,7 +13703,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.0.tgz#c1a0028c2d166ec2fbf7d0644584927e76e7400e" integrity sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg== -resolve@^1.1.6, resolve@^1.10.0, resolve@^1.3.2: +resolve@^1.1.6, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.3.2: version "1.14.2" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.14.2.tgz#dbf31d0fa98b1f29aa5169783b9c290cb865fea2" integrity sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==