diff --git a/.eslintrc b/.eslintrc index 894df7caa9..5864cfdbc3 100644 --- a/.eslintrc +++ b/.eslintrc @@ -7,7 +7,7 @@ "node": true }, "parserOptions": { - "ecmaVersion": 6, + "ecmaVersion": 2022, "ecmaFeatures": { "jsx": true }, @@ -34,17 +34,10 @@ "consistent-return": 0, "prefer-destructuring": [2, { "array": false, "object": false }, { "enforceForRenamedProperties": false }], - "prefer-object-spread": 0, // until node 8 is required - "prefer-rest-params": 0, // until node 6 is required - "prefer-spread": 0, // until node 6 is required - "function-call-argument-newline": 1, // TODO: enable + "function-call-argument-newline": 1, "function-paren-newline": 0, "no-plusplus": [2, {"allowForLoopAfterthoughts": true}], "no-param-reassign": 1, - "no-restricted-syntax": [2, { - "selector": "ObjectPattern", - "message": "Object destructuring is not compatible with Node v4" - }], "strict": [2, "safe"], "valid-jsdoc": [2, { "requireReturn": false, @@ -73,12 +66,11 @@ { "files": ".github/workflows/*.js", "parserOptions": { - "ecmaVersion": 2019, + "ecmaVersion": 2022, }, "rules": { "camelcase": 0, "no-console": 0, - "no-restricted-syntax": 0, }, }, ], diff --git a/.github/workflows/node-minors.yml b/.github/workflows/node-minors.yml deleted file mode 100644 index 69f92684ea..0000000000 --- a/.github/workflows/node-minors.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: 'Tests: node.js (4 - 18)' - -on: [pull_request, push] - -jobs: - matrix: - runs-on: ubuntu-latest - outputs: - latest: ${{ steps.set-matrix.outputs.requireds }} - minors: ${{ steps.set-matrix.outputs.optionals }} - steps: - - uses: ljharb/actions/node/matrix@main - id: set-matrix - with: - versionsAsRoot: true - type: majors - preset: '>=4 < 18' - - latest: - needs: [matrix] - name: 'latest majors' - runs-on: ubuntu-latest - - strategy: - fail-fast: false - matrix: - node-version: ${{ fromJson(needs.matrix.outputs.latest) }} - eslint: - - 8 - - 7 - - 6 - - 5 - - 4 - - 4.14 # last version without messageId - - 3 - babel-eslint: - - 10 - - 9 - - 8 - exclude: - - node-version: 5 - babel-eslint: 10 - - node-version: 5 - babel-eslint: 9 - - node-version: 4 - babel-eslint: 10 - - node-version: 4 - babel-eslint: 9 - - node-version: 15 - eslint: 8 - - node-version: 13 - eslint: 8 - - node-version: 11 - eslint: 8 - - node-version: 11 - eslint: 7 - - node-version: 10 - eslint: 8 - - node-version: 9 - eslint: 8 - - node-version: 9 - eslint: 7 - - node-version: 8 - eslint: 8 - - node-version: 8 - eslint: 7 - - node-version: 7 - eslint: 8 - - node-version: 7 - eslint: 7 - - node-version: 7 - eslint: 6 - - node-version: 6 - eslint: 8 - - node-version: 6 - eslint: 7 - - node-version: 6 - eslint: 6 - - node-version: 5 - eslint: 8 - - node-version: 5 - eslint: 7 - - node-version: 5 - eslint: 6 - - node-version: 5 - eslint: 5 - - node-version: 4 - eslint: 8 - - node-version: 4 - eslint: 7 - - node-version: 4 - eslint: 6 - - node-version: 4 - eslint: 5 - - steps: - - uses: actions/checkout@v4 - - uses: ljharb/actions/node/install@main - name: 'nvm install ${{ matrix.node-version }} && npm install' - with: - node-version: ${{ matrix.node-version }} - after_install: | - npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.node-version >= 18 && matrix.eslint >= 8 && '8' || (matrix.node-version >= 16 && matrix.eslint >= 7 && '6' || (matrix.node-version >= 14 && '5' || (matrix.node-version >= 12 && '4' || (matrix.node-version >= 10 && '4.0' || (matrix.node-version >= 8 && '3' || '2'))))) }}" "babel-eslint@${{ matrix.babel-eslint }}" - skip-ls-check: ${{ matrix.node-version < 10 && true || false }} - env: - NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.node-version >= 16 && matrix.eslint >= 7 && 'false' || 'true' }}" - - run: npx ls-engines - if: ${{ matrix.node-version >= 12 }} - - run: npm run unit-test - - uses: codecov/codecov-action@v3.1.5 - - node: - name: 'node 4 - 17' - needs: [latest] - runs-on: ubuntu-latest - steps: - - run: 'echo tests completed' diff --git a/.github/workflows/node-18+.yml b/.github/workflows/node.yml similarity index 97% rename from .github/workflows/node-18+.yml rename to .github/workflows/node.yml index ee7d126939..56d96887a0 100644 --- a/.github/workflows/node-18+.yml +++ b/.github/workflows/node.yml @@ -1,4 +1,4 @@ -name: 'Tests: node.js (18+)' +name: 'Tests: node.js' on: [pull_request, push] @@ -14,7 +14,7 @@ jobs: with: versionsAsRoot: true type: majors - preset: '>=18' + preset: '^18.18.0 || ^20.9.0 || >=21.1.0' latest: needs: [matrix] diff --git a/index.js b/index.js index 8426993e5b..32a883f424 100644 --- a/index.js +++ b/index.js @@ -1,12 +1,9 @@ 'use strict'; -const fromEntries = require('object.fromentries'); -const entries = require('object.entries'); - const allRules = require('./lib/rules'); function filterRules(rules, predicate) { - return fromEntries(entries(rules).filter((entry) => predicate(entry[1]))); + return Object.fromEntries(Object.entries(rules).filter((entry) => predicate(entry[1]))); } /** @@ -14,7 +11,7 @@ function filterRules(rules, predicate) { * @returns {Record} */ function configureAsError(rules) { - return fromEntries(Object.keys(rules).map((key) => [`react/${key}`, 2])); + return Object.fromEntries(Object.keys(rules).map((key) => [`react/${key}`, 2])); } /** @type {Partial} */ diff --git a/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js index afa844a903..42274462a8 100644 --- a/lib/rules/boolean-prop-naming.js +++ b/lib/rules/boolean-prop-naming.js @@ -5,19 +5,13 @@ 'use strict'; -const flatMap = require('array.prototype.flatmap'); -const values = require('object.values'); - const Components = require('../util/Components'); const propsUtil = require('../util/props'); const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); const propWrapperUtil = require('../util/propWrapper'); const report = require('../util/report'); -const eslintUtil = require('../util/eslint'); - -const getSourceCode = eslintUtil.getSourceCode; -const getText = eslintUtil.getText; +const { getSourceCode, getText } = require('../util/eslint'); /** * Checks if prop is nested @@ -260,7 +254,7 @@ module.exports = { } const annotationTypeArguments = propsUtil.getTypeArguments( - component.node.parent.id.typeAnnotation.typeAnnotation + component.node.parent.id.typeAnnotation.typeAnnotation, ); if ( annotationTypeArguments && ( @@ -269,7 +263,7 @@ module.exports = { ) ) { return annotationTypeArguments.params.find( - (param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation' + (param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation', ); } } @@ -278,7 +272,7 @@ module.exports = { if (node.type === 'TSTypeLiteral' || node.type === 'ObjectTypeAnnotation' || node.type === 'TSInterfaceBody') { const currentNode = [].concat( objectTypeAnnotations.get(identifier.name) || [], - node + node, ); objectTypeAnnotations.set(identifier.name, currentNode); } else if ( @@ -317,7 +311,7 @@ module.exports = { && astUtil.isCallExpression(node.value) && propWrapperUtil.isPropWrapperFunction( context, - getText(context, node.value.callee) + getText(context, node.value.callee), ) ) { checkPropWrapperArguments(node, node.value.arguments); @@ -343,7 +337,7 @@ module.exports = { astUtil.isCallExpression(right) && propWrapperUtil.isPropWrapperFunction( context, - getText(context, right.callee) + getText(context, right.callee), ) ) { checkPropWrapperArguments(component.node, right.arguments); @@ -384,7 +378,7 @@ module.exports = { return; } - values(components.list()).forEach((component) => { + Object.values(components.list()).forEach((component) => { const annotation = getComponentTypeAnnotation(component); if (annotation) { @@ -396,7 +390,7 @@ module.exports = { } else if (annotation.type === 'TSTypeReference') { propType = objectTypeAnnotations.get(annotation.typeName.name); } else if (annotation.type === 'TSIntersectionType') { - propType = flatMap(annotation.types, (type) => ( + propType = annotation.types.flatMap((type) => ( type.type === 'TSTypeReference' ? objectTypeAnnotations.get(type.typeName.name) : type @@ -407,7 +401,7 @@ module.exports = { [].concat(propType).filter(Boolean).forEach((prop) => { validatePropNaming( component.node, - prop.properties || prop.members || prop.body + prop.properties || prop.members || prop.body, ); }); } diff --git a/lib/rules/button-has-type.js b/lib/rules/button-has-type.js index a6fd41cbfe..dd3c183c9a 100644 --- a/lib/rules/button-has-type.js +++ b/lib/rules/button-has-type.js @@ -61,7 +61,7 @@ module.exports = { }, create(context) { - const configuration = Object.assign({}, optionDefaults, context.options[0]); + const configuration = { ...optionDefaults, ...context.options[0] }; function reportMissing(node) { report(context, messages.missingType, 'missingType', { diff --git a/lib/rules/checked-requires-onchange-or-readonly.js b/lib/rules/checked-requires-onchange-or-readonly.js index d67449ea51..c7a9ba757d 100644 --- a/lib/rules/checked-requires-onchange-or-readonly.js +++ b/lib/rules/checked-requires-onchange-or-readonly.js @@ -6,7 +6,6 @@ 'use strict'; const ASTUtils = require('jsx-ast-utils'); -const flatMap = require('array.prototype.flatmap'); const isCreateElement = require('../util/isCreateElement'); const report = require('../util/report'); const docsUrl = require('../util/docsUrl'); @@ -30,14 +29,13 @@ const defaultOptions = { */ function extractTargetProps(properties, keyName) { return new Set( - flatMap( - properties, + properties.flatMap( (prop) => ( prop[keyName] && targetPropSet.has(prop[keyName].name) ? [prop[keyName].name] : [] - ) - ) + ), + ), ); } @@ -64,14 +62,14 @@ module.exports = { }], }, create(context) { - const options = Object.assign({}, defaultOptions, context.options[0]); + const options = { ...defaultOptions, ...context.options[0] }; function reportMissingProperty(node) { report( context, messages.missingProperty, 'missingProperty', - { node } + { node }, ); } @@ -80,7 +78,7 @@ module.exports = { context, messages.exclusiveCheckedAttribute, 'exclusiveCheckedAttribute', - { node } + { node }, ); } diff --git a/lib/rules/default-props-match-prop-types.js b/lib/rules/default-props-match-prop-types.js index 95b341650a..d93b247c36 100644 --- a/lib/rules/default-props-match-prop-types.js +++ b/lib/rules/default-props-match-prop-types.js @@ -6,8 +6,6 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); @@ -95,12 +93,12 @@ module.exports = { return { 'Program:exit'() { // If no defaultProps could be found, we don't report anything. - values(components.list()) + Object.values(components.list()) .filter((component) => component.defaultProps) .forEach((component) => { reportInvalidDefaultProps( component.declaredPropTypes, - component.defaultProps || {} + component.defaultProps || {}, ); }); }, diff --git a/lib/rules/display-name.js b/lib/rules/display-name.js index b85ec34f1c..aab2cdb02b 100644 --- a/lib/rules/display-name.js +++ b/lib/rules/display-name.js @@ -5,7 +5,6 @@ 'use strict'; -const values = require('object.values'); const filter = require('es-iterator-helpers/Iterator.prototype.filter'); const forEach = require('es-iterator-helpers/Iterator.prototype.forEach'); @@ -269,14 +268,14 @@ module.exports = { 'Program:exit'() { const list = components.list(); // Report missing display name for all components - values(list).filter((component) => !component.hasDisplayName).forEach((component) => { + Object.values(list).filter((component) => !component.hasDisplayName).forEach((component) => { reportMissingDisplayName(component); }); if (checkContextObjects) { // Report missing display name for all context objects forEach( filter(contextObjects.values(), (v) => !v.hasDisplayName), - (contextObj) => reportMissingContextDisplayName(contextObj) + (contextObj) => reportMissingContextDisplayName(contextObj), ); } }, diff --git a/lib/rules/forbid-component-props.js b/lib/rules/forbid-component-props.js index 2dd4412b87..f4c5e16c88 100644 --- a/lib/rules/forbid-component-props.js +++ b/lib/rules/forbid-component-props.js @@ -179,7 +179,7 @@ module.exports = { } return options.allowPatternList.every( - (pattern) => !minimatch(tagName, pattern) + (pattern) => !minimatch(tagName, pattern), ); } @@ -193,7 +193,7 @@ module.exports = { } return options.disallowPatternList.some( - (pattern) => minimatch(tagName, pattern) + (pattern) => minimatch(tagName, pattern), ); } diff --git a/lib/rules/forbid-elements.js b/lib/rules/forbid-elements.js index f08ef1d1e7..e819c65c29 100644 --- a/lib/rules/forbid-elements.js +++ b/lib/rules/forbid-elements.js @@ -5,9 +5,8 @@ 'use strict'; -const has = require('hasown'); const docsUrl = require('../util/docsUrl'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); const isCreateElement = require('../util/isCreateElement'); const report = require('../util/report'); @@ -73,7 +72,7 @@ module.exports = { }); function reportIfForbidden(element, node) { - if (has(indexedForbidConfigs, element)) { + if (Object.hasOwn(indexedForbidConfigs, element)) { const message = indexedForbidConfigs[element].message; report( @@ -86,7 +85,7 @@ module.exports = { element, message, }, - } + }, ); } } diff --git a/lib/rules/forward-ref-uses-ref.js b/lib/rules/forward-ref-uses-ref.js index aeedeb82df..38b8b0f36b 100644 --- a/lib/rules/forward-ref-uses-ref.js +++ b/lib/rules/forward-ref-uses-ref.js @@ -77,10 +77,10 @@ module.exports = { const shouldAddParentheses = node.type === 'ArrowFunctionExpression' && !isParenthesized(context, param); return [].concat( shouldAddParentheses ? fixer.insertTextBefore(param, '(') : [], - fixer.insertTextAfter(param, `, ref${shouldAddParentheses ? ')' : ''}`) + fixer.insertTextAfter(param, `, ref${shouldAddParentheses ? ')' : ''}`), ); }, - } + }, ), Object.assign( getMessageData('removeForwardRef', messages.removeForwardRef), @@ -88,7 +88,7 @@ module.exports = { fix(fixer) { return fixer.replaceText(node.parent, sourceCode.getText(node)); }, - } + }, ), ], }); diff --git a/lib/rules/function-component-definition.js b/lib/rules/function-component-definition.js index cca665abe2..33ee573ff8 100644 --- a/lib/rules/function-component-definition.js +++ b/lib/rules/function-component-definition.js @@ -5,11 +5,10 @@ 'use strict'; -const arrayIncludes = require('array-includes'); const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); const reportC = require('../util/report'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); const propsUtil = require('../util/props'); // ------------------------------------------------------------------------------ @@ -19,7 +18,7 @@ const propsUtil = require('../util/props'); function buildFunction(template, parts) { return Object.keys(parts).reduce( (acc, key) => acc.replace(`{${key}}`, () => parts[key] || ''), - template + template, ); } @@ -72,7 +71,7 @@ function getParams(node, source) { if (node.params.length === 0) return null; return source.slice( node.params[0].range[0], - node.params[node.params.length - 1].range[1] + node.params[node.params.length - 1].range[1], ); } @@ -176,10 +175,10 @@ module.exports = { let fileVarType = 'var'; const namedConfig = [].concat( - configuration.namedComponents || 'function-declaration' + configuration.namedComponents || 'function-declaration', ); const unnamedConfig = [].concat( - configuration.unnamedComponents || 'function-expression' + configuration.unnamedComponents || 'function-expression', ); function getFixer(node, options) { @@ -214,7 +213,7 @@ module.exports = { body: getBody(node, source), name: getName(node), varType, - }) + }), ); } @@ -230,7 +229,7 @@ module.exports = { if (node.parent && node.parent.type === 'Property') return; - if (hasName(node) && !arrayIncludes(namedConfig, functionType)) { + if (hasName(node) && !namedConfig.includes(functionType)) { report(node, { messageId: namedConfig[0], fixerOptions: { @@ -243,7 +242,7 @@ module.exports = { }, }); } - if (!hasName(node) && !arrayIncludes(unnamedConfig, functionType)) { + if (!hasName(node) && !unnamedConfig.includes(functionType)) { report(node, { messageId: unnamedConfig[0], fixerOptions: { diff --git a/lib/rules/hook-use-state.js b/lib/rules/hook-use-state.js index 2d1cf681cd..065c66dd54 100644 --- a/lib/rules/hook-use-state.js +++ b/lib/rules/hook-use-state.js @@ -75,7 +75,7 @@ module.exports = { { node, suggest: false, - } + }, ); return; } @@ -119,11 +119,11 @@ module.exports = { if (expectedSetterVariableNames.length > 0) { return fixer.replaceTextRange( node.parent.id.range, - `[${valueVariableName}, ${expectedSetterVariableNames[0]}]` + `[${valueVariableName}, ${expectedSetterVariableNames[0]}]`, ); } }, - } + }, ), ]; @@ -169,10 +169,10 @@ module.exports = { // Convert useState call to useMemo + arrow function + dependency array fixer.replaceTextRange( node.range, - `${useMemoCode}(() => ${getText(context, node.arguments[0])}, [])` + `${useMemoCode}(() => ${getText(context, node.arguments[0])}, [])`, ), ].filter(Boolean), - } + }, )); } @@ -184,7 +184,7 @@ module.exports = { { node: node.parent.id, suggest: false, - } + }, ); return; } @@ -196,7 +196,7 @@ module.exports = { { node: node.parent.id, suggest: suggestions, - } + }, ); } }, diff --git a/lib/rules/jsx-closing-bracket-location.js b/lib/rules/jsx-closing-bracket-location.js index eed661e944..dfe1b222f5 100644 --- a/lib/rules/jsx-closing-bracket-location.js +++ b/lib/rules/jsx-closing-bracket-location.js @@ -5,11 +5,8 @@ 'use strict'; -const has = require('hasown'); -const repeat = require('string.prototype.repeat'); - const docsUrl = require('../util/docsUrl'); -const getSourceCode = require('../util/eslint').getSourceCode; +const { getSourceCode } = require('../util/eslint'); const report = require('../util/report'); // ------------------------------------------------------------------------------ @@ -84,16 +81,16 @@ module.exports = { options.selfClosing = config; } else if (typeof config === 'object') { // [1, {location: 'something'}] (back-compat) - if (has(config, 'location')) { + if (Object.hasOwn(config, 'location')) { options.nonEmpty = config.location; options.selfClosing = config.location; } // [1, {nonEmpty: 'something'}] - if (has(config, 'nonEmpty')) { + if (Object.hasOwn(config, 'nonEmpty')) { options.nonEmpty = config.nonEmpty; } // [1, {selfClosing: 'something'}] - if (has(config, 'selfClosing')) { + if (Object.hasOwn(config, 'selfClosing')) { options.selfClosing = config.selfClosing; } } @@ -185,7 +182,7 @@ module.exports = { } if (indentation.length + 1 < newColumn) { // Non-whitespace characters were included in the column offset - spaces = repeat(' ', +correctColumn - indentation.length); + spaces = ' '.repeat(+correctColumn - indentation.length); } return indentation + spaces; } diff --git a/lib/rules/jsx-closing-tag-location.js b/lib/rules/jsx-closing-tag-location.js index 5f6f6efe38..f73df901ca 100644 --- a/lib/rules/jsx-closing-tag-location.js +++ b/lib/rules/jsx-closing-tag-location.js @@ -5,12 +5,9 @@ 'use strict'; -const repeat = require('string.prototype.repeat'); -const has = require('hasown'); - const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); -const getSourceCode = require('../util/eslint').getSourceCode; +const { getSourceCode } = require('../util/eslint'); const report = require('../util/report'); // ------------------------------------------------------------------------------ @@ -66,7 +63,7 @@ module.exports = { if (typeof config === 'string') { option = config; } else if (typeof config === 'object') { - if (has(config, 'location')) { + if (Object.hasOwn(config, 'location')) { option = config.location; } } @@ -117,15 +114,14 @@ module.exports = { node, loc: node.loc, fix(fixer) { - const indent = repeat( - ' ', - getIndentation(openingStartOfLine, opening) + const indent = ' '.repeat( + getIndentation(openingStartOfLine, opening), ); if (astUtil.isNodeFirstInLine(context, node)) { return fixer.replaceTextRange( [node.range[0] - node.loc.start.column, node.range[0]], - indent + indent, ); } diff --git a/lib/rules/jsx-curly-brace-presence.js b/lib/rules/jsx-curly-brace-presence.js index 0f17143ffa..57dcc23481 100755 --- a/lib/rules/jsx-curly-brace-presence.js +++ b/lib/rules/jsx-curly-brace-presence.js @@ -6,15 +6,10 @@ 'use strict'; -const arrayIncludes = require('array-includes'); - const docsUrl = require('../util/docsUrl'); const jsxUtil = require('../util/jsx'); const report = require('../util/report'); -const eslintUtil = require('../util/eslint'); - -const getSourceCode = eslintUtil.getSourceCode; -const getText = eslintUtil.getText; +const { getSourceCode, getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Constants @@ -38,7 +33,7 @@ function containsLineTerminators(rawStringValue) { } function containsBackslash(rawStringValue) { - return arrayIncludes(rawStringValue, '\\'); + return rawStringValue.includes('\\'); } function containsHTMLEntity(rawStringValue) { @@ -179,7 +174,7 @@ module.exports = { const ruleOptions = context.options[0]; const userConfig = typeof ruleOptions === 'string' ? { props: ruleOptions, children: ruleOptions, propElementValues: OPTION_IGNORE } - : Object.assign({}, DEFAULT_CONFIG, ruleOptions); + : { ...DEFAULT_CONFIG, ...ruleOptions }; /** * Report and fix an unnecessary curly brace violation on a node @@ -241,7 +236,7 @@ module.exports = { const expression = literalNode.parent.type === 'JSXAttribute' ? `{"${escapeDoubleQuotes(escapeBackslashes( - literalNode.raw.slice(1, -1) + literalNode.raw.slice(1, -1), ))}"}` : wrapWithCurlyBraces(literalNode.raw); @@ -335,7 +330,7 @@ module.exports = { const childrenExcludingWhitespaceLiteral = children.filter((child) => !isWhiteSpaceLiteral(child)); const adjSiblings = getAdjacentSiblings(node, childrenExcludingWhitespaceLiteral); - return adjSiblings.some((x) => x.type && arrayIncludes(['JSXExpressionContainer', 'JSXElement'], x.type)); + return adjSiblings.some((x) => x.type && ['JSXExpressionContainer', 'JSXElement'].includes(x.type)); } function shouldCheckForUnnecessaryCurly(node, config) { const parent = node.parent; diff --git a/lib/rules/jsx-curly-spacing.js b/lib/rules/jsx-curly-spacing.js index fda49381ce..bd75eacd7c 100644 --- a/lib/rules/jsx-curly-spacing.js +++ b/lib/rules/jsx-curly-spacing.js @@ -11,9 +11,8 @@ 'use strict'; -const has = require('hasown'); const docsUrl = require('../util/docsUrl'); -const getSourceCode = require('../util/eslint').getSourceCode; +const { getSourceCode } = require('../util/eslint'); const report = require('../util/report'); // ------------------------------------------------------------------------------ @@ -120,7 +119,7 @@ module.exports = { function normalizeConfig(configOrTrue, defaults, lastPass) { const config = configOrTrue === true ? {} : configOrTrue; const when = config.when || defaults.when; - const allowMultiline = has(config, 'allowMultiline') ? config.allowMultiline : defaults.allowMultiline; + const allowMultiline = Object.hasOwn(config, 'allowMultiline') ? config.allowMultiline : defaults.allowMultiline; const spacing = config.spacing || {}; let objectLiteralSpaces = spacing.objectLiterals || defaults.objectLiteralSpaces; if (lastPass) { @@ -142,15 +141,15 @@ module.exports = { let originalConfig = context.options[0] || {}; if (SPACING_VALUES.indexOf(originalConfig) !== -1) { - originalConfig = Object.assign({ when: context.options[0] }, context.options[1]); + originalConfig = { when: context.options[0], ...context.options[1] }; } const defaultConfig = normalizeConfig(originalConfig, { when: DEFAULT_WHEN, allowMultiline: DEFAULT_ALLOW_MULTILINE, }); - const attributes = has(originalConfig, 'attributes') ? originalConfig.attributes : DEFAULT_ATTRIBUTES; + const attributes = Object.hasOwn(originalConfig, 'attributes') ? originalConfig.attributes : DEFAULT_ATTRIBUTES; const attributesConfig = attributes ? normalizeConfig(attributes, defaultConfig, true) : null; - const children = has(originalConfig, 'children') ? originalConfig.children : DEFAULT_CHILDREN; + const children = Object.hasOwn(originalConfig, 'children') ? originalConfig.children : DEFAULT_CHILDREN; const childrenConfig = children ? normalizeConfig(children, defaultConfig, true) : null; // -------------------------------------------------------------------------- diff --git a/lib/rules/jsx-handler-names.js b/lib/rules/jsx-handler-names.js index 652e125d6e..28bf3b46ad 100644 --- a/lib/rules/jsx-handler-names.js +++ b/lib/rules/jsx-handler-names.js @@ -168,7 +168,7 @@ module.exports = { const expression = node.value.expression; const propValue = getText( context, - checkInlineFunction && isInlineHandler(node) ? expression.body.callee : expression + checkInlineFunction && isInlineHandler(node) ? expression.body.callee : expression, ).replace(/\s*/g, '').replace(/^this\.|.*::/, ''); if (propKey === 'ref') { diff --git a/lib/rules/jsx-indent-props.js b/lib/rules/jsx-indent-props.js index 8504878731..a788c3112a 100644 --- a/lib/rules/jsx-indent-props.js +++ b/lib/rules/jsx-indent-props.js @@ -30,11 +30,9 @@ 'use strict'; -const repeat = require('string.prototype.repeat'); - const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); const reportC = require('../util/report'); // ------------------------------------------------------------------------------ @@ -133,7 +131,7 @@ module.exports = { data: msgContext, fix(fixer) { return fixer.replaceTextRange([node.range[0] - node.loc.start.column, node.range[0]], - repeat(indentType === 'space' ? ' ' : '\t', needed) + (indentType === 'space' ? ' ' : '\t').repeat(needed), ); }, }); diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js index f27eca029d..0269aa1aae 100644 --- a/lib/rules/jsx-indent.js +++ b/lib/rules/jsx-indent.js @@ -30,17 +30,11 @@ 'use strict'; -const matchAll = require('string.prototype.matchall'); -const repeat = require('string.prototype.repeat'); - const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); const reportC = require('../util/report'); const jsxUtil = require('../util/jsx'); -const eslintUtil = require('../util/eslint'); - -const getSourceCode = eslintUtil.getSourceCode; -const getText = eslintUtil.getText; +const { getSourceCode, getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Rule Definition @@ -111,7 +105,7 @@ module.exports = { * @private */ function getFixerFunction(node, needed) { - const indent = repeat(indentChar, needed); + const indent = indentChar.repeat(needed); if (node.type === 'JSXText' || node.type === 'Literal') { return function fix(fixer) { @@ -130,7 +124,7 @@ module.exports = { const lastLine = raw.slice(lastLineStart).replace(/^\n[\t ]*(\S)/, (match, p1) => `\n${indent}${p1}`); return fixer.replaceTextRange( [node.range[0] + lastLineStart, node.range[1]], - lastLine + lastLine, ); }; } @@ -139,7 +133,7 @@ module.exports = { return function fix(fixer) { return fixer.replaceTextRange( [node.range[0] - node.loc.start.column, node.range[0]], - indent + indent, ); }; } @@ -159,11 +153,12 @@ module.exports = { gotten, }; - reportC(context, messages.wrongIndent, 'wrongIndent', Object.assign({ + reportC(context, messages.wrongIndent, 'wrongIndent', { node, data: msgContext, fix: getFixerFunction(node, needed), - }, loc && { loc })); + ...(loc ? { loc } : {}), + }); } /** @@ -325,8 +320,8 @@ module.exports = { const value = node.value; const regExp = indentType === 'space' ? /\n( *)[\t ]*\S/g : /\n(\t*)[\t ]*\S/g; const nodeIndentsPerLine = Array.from( - matchAll(String(value), regExp), - (match) => (match[1] ? match[1].length : 0) + String(value).matchAll(regExp), + (match) => (match[1] ? match[1].length : 0), ); const hasFirstInLineNode = nodeIndentsPerLine.length > 0; if ( diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js index 825d21f4bb..6f42123d19 100644 --- a/lib/rules/jsx-key.js +++ b/lib/rules/jsx-key.js @@ -7,12 +7,11 @@ const hasProp = require('jsx-ast-utils/hasProp'); const propName = require('jsx-ast-utils/propName'); -const values = require('object.values'); const docsUrl = require('../util/docsUrl'); const pragmaUtil = require('../util/pragma'); const report = require('../util/report'); const astUtil = require('../util/ast'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Rule Definition @@ -66,7 +65,7 @@ module.exports = { }, create(context) { - const options = Object.assign({}, defaultOptions, context.options[0]); + const options = { ...defaultOptions, ...context.options[0] }; const checkFragmentShorthand = options.checkFragmentShorthand; const checkKeyMustBeforeSpread = options.checkKeyMustBeforeSpread; const warnOnDuplicates = options.warnOnDuplicates; @@ -109,8 +108,8 @@ module.exports = { } } - function getReturnStatements(node) { - const returnStatements = arguments[1] || []; + function getReturnStatements(node, ...args) { + const returnStatements = args[1] || []; if (node.type === 'IfStatement') { if (node.consequent) { getReturnStatements(node.consequent, returnStatements); @@ -234,7 +233,7 @@ module.exports = { }); if (warnOnDuplicates) { - values(map).filter((v) => v.length > 1).forEach((v) => { + Object.values(map).filter((v) => v.length > 1).forEach((v) => { v.forEach((n) => { if (!seen.has(n)) { seen.add(n); diff --git a/lib/rules/jsx-max-depth.js b/lib/rules/jsx-max-depth.js index 12625fa704..a9d9bfb8ca 100644 --- a/lib/rules/jsx-max-depth.js +++ b/lib/rules/jsx-max-depth.js @@ -5,8 +5,6 @@ 'use strict'; -const has = require('hasown'); -const includes = require('array-includes'); const variableUtil = require('../util/variable'); const jsxUtil = require('../util/jsx'); const docsUrl = require('../util/docsUrl'); @@ -49,7 +47,7 @@ module.exports = { const DEFAULT_DEPTH = 2; const option = context.options[0] || {}; - const maxDepth = has(option, 'max') ? option.max : DEFAULT_DEPTH; + const maxDepth = Object.hasOwn(option, 'max') ? option.max : DEFAULT_DEPTH; function isExpression(node) { return node.type === 'JSXExpressionContainer'; @@ -106,7 +104,7 @@ module.exports = { const variable = variableUtil.getVariableFromContext(context, startNode, name); if (variable && variable.references) { - const containDuplicates = previousReferences.some((ref) => includes(variable.references, ref)); + const containDuplicates = previousReferences.some((ref) => variable.references.includes(ref)); // Prevent getting stuck in circular references if (containDuplicates) { diff --git a/lib/rules/jsx-newline.js b/lib/rules/jsx-newline.js index 7fd395c72f..23b9b48e69 100644 --- a/lib/rules/jsx-newline.js +++ b/lib/rules/jsx-newline.js @@ -122,7 +122,7 @@ module.exports = { fix(fixer) { return fixer.replaceText( firstAdjacentSibling, - getText(context, firstAdjacentSibling).replace(regex, replacement) + getText(context, firstAdjacentSibling).replace(regex, replacement), ); }, }); @@ -150,7 +150,7 @@ module.exports = { return fixer.replaceText( firstAdjacentSibling, // double or remove the last newline - getText(context, firstAdjacentSibling).replace(regex, replacement) + getText(context, firstAdjacentSibling).replace(regex, replacement), ); }, }); diff --git a/lib/rules/jsx-no-bind.js b/lib/rules/jsx-no-bind.js index 2e8aa687dc..4abcd9cef3 100644 --- a/lib/rules/jsx-no-bind.js +++ b/lib/rules/jsx-no-bind.js @@ -126,7 +126,7 @@ module.exports = { function getBlockStatementAncestors(node) { return getAncestors(context, node).filter( - (ancestor) => ancestor.type === 'BlockStatement' + (ancestor) => ancestor.type === 'BlockStatement', ).reverse(); } @@ -148,7 +148,7 @@ module.exports = { function findVariableViolation(node, name) { getBlockStatementAncestors(node).find( - (block) => reportVariableViolation(node, name, block.range[0]) + (block) => reportVariableViolation(node, name, block.range[0]), ); } diff --git a/lib/rules/jsx-no-constructed-context-values.js b/lib/rules/jsx-no-constructed-context-values.js index 2e9ef93422..f5b1d7d459 100644 --- a/lib/rules/jsx-no-constructed-context-values.js +++ b/lib/rules/jsx-no-constructed-context-values.js @@ -162,7 +162,7 @@ module.exports = { // Contexts can take in more than just a value prop // so we need to iterate through all of them const jsxValueAttribute = node.attributes.find( - (attribute) => attribute.type === 'JSXAttribute' && attribute.name.name === 'value' + (attribute) => attribute.type === 'JSXAttribute' && attribute.name.name === 'value', ); if (jsxValueAttribute == null) { diff --git a/lib/rules/jsx-no-duplicate-props.js b/lib/rules/jsx-no-duplicate-props.js index 77de5bde51..0e40879094 100644 --- a/lib/rules/jsx-no-duplicate-props.js +++ b/lib/rules/jsx-no-duplicate-props.js @@ -5,7 +5,6 @@ 'use strict'; -const has = require('hasown'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); @@ -63,7 +62,7 @@ module.exports = { name = name.toLowerCase(); } - if (has(props, name)) { + if (Object.hasOwn(props, name)) { report(context, messages.noDuplicateProps, 'noDuplicateProps', { node: decl, }); diff --git a/lib/rules/jsx-no-leaked-render.js b/lib/rules/jsx-no-leaked-render.js index 1e271b2a68..6939357e26 100644 --- a/lib/rules/jsx-no-leaked-render.js +++ b/lib/rules/jsx-no-leaked-render.js @@ -51,7 +51,7 @@ function extractExpressionBetweenLogicalAnds(node) { if (node.operator !== '&&') return [node]; return [].concat( extractExpressionBetweenLogicalAnds(node.left), - extractExpressionBetweenLogicalAnds(node.right) + extractExpressionBetweenLogicalAnds(node.right), ); } diff --git a/lib/rules/jsx-no-literals.js b/lib/rules/jsx-no-literals.js index 230d33a18d..59be186cab 100644 --- a/lib/rules/jsx-no-literals.js +++ b/lib/rules/jsx-no-literals.js @@ -10,12 +10,10 @@ const iterFrom = require('es-iterator-helpers/Iterator.from'); const map = require('es-iterator-helpers/Iterator.prototype.map'); const some = require('es-iterator-helpers/Iterator.prototype.some'); const flatMap = require('es-iterator-helpers/Iterator.prototype.flatMap'); -const fromEntries = require('object.fromentries'); -const entries = require('object.entries'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Rule Definition @@ -140,9 +138,9 @@ function normalizeConfig(config) { }); if (config.elementOverrides) { - normalizedConfig.elementOverrides = fromEntries( + normalizedConfig.elementOverrides = Object.fromEntries( flatMap( - iterFrom(entries(config.elementOverrides)), + iterFrom(Object.entries(config.elementOverrides)), (entry) => { const elementName = entry[0]; const rawElementConfig = entry[1]; @@ -160,8 +158,8 @@ function normalizeConfig(config) { applyToNestedElements: typeof rawElementConfig.applyToNestedElements === 'undefined' || !!rawElementConfig.applyToNestedElements, }), ]]; - } - ) + }, + ), ); } @@ -173,10 +171,10 @@ const elementOverrides = { patternProperties: { [reOverridableElement.source]: { type: 'object', - properties: Object.assign( - { applyToNestedElements: { type: 'boolean' } }, - commonPropertiesSchema - ), + properties: { + applyToNestedElements: { type: 'boolean' }, + ...commonPropertiesSchema, + }, }, }, @@ -195,10 +193,10 @@ module.exports = { schema: [{ type: 'object', - properties: Object.assign( - { elementOverrides }, - commonPropertiesSchema - ), + properties: { + elementOverrides, + ...commonPropertiesSchema, + }, additionalProperties: false, }], }), @@ -379,15 +377,15 @@ module.exports = { */ function getOverrideConfig(node) { if (!hasElementOverrides) { - return; + return undefined; } const allAncestorElements = getJSXElementAncestors(node); if (!allAncestorElements.length) { - return; + return undefined; } - for (const ancestorElement of allAncestorElements) { + allAncestorElements.forEach((ancestorElement) => { const isClosestJSXAncestor = ancestorElement === allAncestorElements[0]; const ancestor = getJSXElementName(ancestorElement); @@ -405,7 +403,7 @@ module.exports = { } } } - } + }); } /** @@ -460,7 +458,7 @@ module.exports = { .forEach((specifier) => { renamedImportMap.set( (specifier.local || specifier.imported).name, - specifier.imported.name + specifier.imported.name, ); }); }, diff --git a/lib/rules/jsx-no-script-url.js b/lib/rules/jsx-no-script-url.js index b18ce2ccb3..d180630df0 100644 --- a/lib/rules/jsx-no-script-url.js +++ b/lib/rules/jsx-no-script-url.js @@ -5,7 +5,6 @@ 'use strict'; -const includes = require('array-includes'); const docsUrl = require('../util/docsUrl'); const linkComponentsUtil = require('../util/linkComponents'); const report = require('../util/report'); @@ -30,7 +29,7 @@ function shouldVerifyProp(node, config) { if (!name || !parentName || !config.has(parentName)) return false; const attributes = config.get(parentName); - return includes(attributes, name); + return attributes.includes(name); } function parseLegacyOption(config, option) { diff --git a/lib/rules/jsx-no-target-blank.js b/lib/rules/jsx-no-target-blank.js index 9f5d239d6c..c1cacf8743 100644 --- a/lib/rules/jsx-no-target-blank.js +++ b/lib/rules/jsx-no-target-blank.js @@ -5,7 +5,6 @@ 'use strict'; -const includes = require('array-includes'); const docsUrl = require('../util/docsUrl'); const linkComponentsUtil = require('../util/linkComponents'); const report = require('../util/report'); @@ -50,7 +49,7 @@ function attributeValuePossiblyBlank(attribute) { } function hasExternalLink(node, linkAttributes, warnOnSpreadAttributes, spreadAttributeIndex) { - const linkIndex = findLastIndex(node.attributes, (attr) => attr.name && includes(linkAttributes, attr.name.name)); + const linkIndex = findLastIndex(node.attributes, (attr) => attr.name && linkAttributes.includes(attr.name.name)); const foundExternalLink = linkIndex !== -1 && ((attr) => attr.value && attr.value.type === 'Literal' && /^(?:\w+:|\/\/)/.test(attr.value.value))( node.attributes[linkIndex]); return foundExternalLink || (warnOnSpreadAttributes && linkIndex < spreadAttributeIndex); @@ -58,7 +57,7 @@ function hasExternalLink(node, linkAttributes, warnOnSpreadAttributes, spreadAtt function hasDynamicLink(node, linkAttributes) { const dynamicLinkIndex = findLastIndex(node.attributes, (attr) => attr.name - && includes(linkAttributes, attr.name.name) + && linkAttributes.includes(attr.name.name) && attr.value && attr.value.type === 'JSXExpressionContainer'); if (dynamicLinkIndex !== -1) { @@ -165,15 +164,13 @@ module.exports = { }, create(context) { - const configuration = Object.assign( - { - allowReferrer: false, - warnOnSpreadAttributes: false, - links: true, - forms: false, - }, - context.options[0] - ); + const configuration = { + allowReferrer: false, + warnOnSpreadAttributes: false, + links: true, + forms: false, + ...context.options[0], + }; const allowReferrer = configuration.allowReferrer; const warnOnSpreadAttributes = configuration.warnOnSpreadAttributes; const enforceDynamicLinks = configuration.enforceDynamicLinks || 'always'; diff --git a/lib/rules/jsx-no-useless-fragment.js b/lib/rules/jsx-no-useless-fragment.js index 9827560f0e..858534b379 100644 --- a/lib/rules/jsx-no-useless-fragment.js +++ b/lib/rules/jsx-no-useless-fragment.js @@ -4,14 +4,12 @@ 'use strict'; -const arrayIncludes = require('array-includes'); - const pragmaUtil = require('../util/pragma'); const astUtil = require('../util/ast'); const jsxUtil = require('../util/jsx'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); function isJSXText(node) { return !!node && (node.type === 'JSXText' || node.type === 'Literal'); @@ -52,8 +50,8 @@ function trimLikeReact(text) { const leadingSpaces = /^\s*/.exec(text)[0]; const trailingSpaces = /\s*$/.exec(text)[0]; - const start = arrayIncludes(leadingSpaces, '\n') ? leadingSpaces.length : 0; - const end = arrayIncludes(trailingSpaces, '\n') ? text.length - trailingSpaces.length : text.length; + const start = leadingSpaces.includes('\n') ? leadingSpaces.length : 0; + const end = trailingSpaces.includes('\n') ? text.length - trailingSpaces.length : text.length; return text.slice(start, end); } @@ -121,7 +119,7 @@ module.exports = { function isPaddingSpaces(node) { return isJSXText(node) && isOnlyWhitespace(node.raw) - && arrayIncludes(node.raw, '\n'); + && node.raw.includes('\n'); } function isFragmentWithSingleExpression(node) { @@ -145,7 +143,7 @@ module.exports = { /** @type {ASTNode[]} */ const nonPaddingChildren = node.children.filter( - (child) => !isPaddingSpaces(child) + (child) => !isPaddingSpaces(child), ); if (nonPaddingChildren.length < 2) { diff --git a/lib/rules/jsx-one-expression-per-line.js b/lib/rules/jsx-one-expression-per-line.js index 3ae61e3d96..8222cff1b3 100644 --- a/lib/rules/jsx-one-expression-per-line.js +++ b/lib/rules/jsx-one-expression-per-line.js @@ -53,7 +53,7 @@ module.exports = { }, create(context) { - const options = Object.assign({}, optionDefaults, context.options[0]); + const options = { ...optionDefaults, ...context.options[0] }; function nodeKey(node) { return `${node.loc.start.line},${node.loc.start.column}`; diff --git a/lib/rules/jsx-pascal-case.js b/lib/rules/jsx-pascal-case.js index efeef4032a..213f5496f7 100644 --- a/lib/rules/jsx-pascal-case.js +++ b/lib/rules/jsx-pascal-case.js @@ -32,14 +32,14 @@ function testPascalCase(name) { } const anyNonAlphaNumeric = Array.prototype.some.call( name.slice(1), - (char) => char.toLowerCase() === char.toUpperCase() && !testDigit(char) + (char) => char.toLowerCase() === char.toUpperCase() && !testDigit(char), ); if (anyNonAlphaNumeric) { return false; } return Array.prototype.some.call( name.slice(1), - (char) => testLowerCase(char) || testDigit(char) + (char) => testLowerCase(char) || testDigit(char), ); } @@ -63,7 +63,7 @@ function testAllCaps(name) { function ignoreCheck(ignore, name) { return ignore.some( - (entry) => name === entry || minimatch(name, entry, { noglobstar: true }) + (entry) => name === entry || minimatch(name, entry, { noglobstar: true }), ); } diff --git a/lib/rules/jsx-props-no-multi-spaces.js b/lib/rules/jsx-props-no-multi-spaces.js index 8402c6d4ff..7d9e403a85 100644 --- a/lib/rules/jsx-props-no-multi-spaces.js +++ b/lib/rules/jsx-props-no-multi-spaces.js @@ -117,16 +117,13 @@ module.exports = { if (containsGenericType(node)) { const nodeTypeArguments = propsUtil.getTypeArguments(node); - return Object.assign( - {}, - node, - { - range: [ - name.range[0], - nodeTypeArguments.range[1], - ], - } - ); + return { + ...node, + range: [ + name.range[0], + nodeTypeArguments.range[1], + ], + }; } return name; diff --git a/lib/rules/jsx-props-no-spread-multi.js b/lib/rules/jsx-props-no-spread-multi.js index 2eeed0be49..5c6c8bd269 100644 --- a/lib/rules/jsx-props-no-spread-multi.js +++ b/lib/rules/jsx-props-no-spread-multi.js @@ -32,7 +32,7 @@ module.exports = { JSXOpeningElement(node) { const spreads = node.attributes.filter( (attr) => attr.type === 'JSXSpreadAttribute' - && attr.argument.type === 'Identifier' + && attr.argument.type === 'Identifier', ); if (spreads.length < 2) { return; diff --git a/lib/rules/jsx-sort-props.js b/lib/rules/jsx-sort-props.js index ec9d869b74..7091ba96ae 100644 --- a/lib/rules/jsx-sort-props.js +++ b/lib/rules/jsx-sort-props.js @@ -6,17 +6,13 @@ 'use strict'; const propName = require('jsx-ast-utils/propName'); -const includes = require('array-includes'); const toSorted = require('array.prototype.tosorted'); const docsUrl = require('../util/docsUrl'); const jsxUtil = require('../util/jsx'); const report = require('../util/report'); const propTypesSortUtil = require('../util/propTypesSort'); -const eslintUtil = require('../util/eslint'); - -const getText = eslintUtil.getText; -const getSourceCode = eslintUtil.getSourceCode; +const { getSourceCode, getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Rule Definition @@ -286,7 +282,7 @@ function validateReservedFirstConfig(context, reservedFirst) { // Only allow a subset of reserved words in customized lists const nonReservedWords = reservedFirst.filter((word) => !isReservedPropName( word, - RESERVED_PROPS_LIST + RESERVED_PROPS_LIST, )); if (reservedFirst.length === 0) { @@ -324,7 +320,7 @@ const reportedNodeAttributes = new WeakMap(); function reportNodeAttribute(nodeAttribute, errorType, node, context, reservedList) { const errors = reportedNodeAttributes.get(nodeAttribute) || []; - if (includes(errors, errorType)) { + if (errors.includes(errorType)) { return; } diff --git a/lib/rules/jsx-tag-spacing.js b/lib/rules/jsx-tag-spacing.js index ac7c693278..c14599cc7c 100644 --- a/lib/rules/jsx-tag-spacing.js +++ b/lib/rules/jsx-tag-spacing.js @@ -295,7 +295,7 @@ module.exports = { ], }, create(context) { - const options = Object.assign({}, optionDefaults, context.options[0]); + const options = { ...optionDefaults, ...context.options[0] }; return { JSXOpeningElement(node) { diff --git a/lib/rules/jsx-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js index 6f5ad50bbf..b940540eaf 100644 --- a/lib/rules/jsx-wrap-multilines.js +++ b/lib/rules/jsx-wrap-multilines.js @@ -5,15 +5,11 @@ 'use strict'; -const has = require('hasown'); const docsUrl = require('../util/docsUrl'); -const eslintUtil = require('../util/eslint'); +const { getSourceCode, getText } = require('../util/eslint'); const jsxUtil = require('../util/jsx'); const reportC = require('../util/report'); -const isParenthesized = require('../util/ast').isParenthesized; - -const getSourceCode = eslintUtil.getSourceCode; -const getText = eslintUtil.getText; +const { isParenthesized } = require('../util/ast'); // ------------------------------------------------------------------------------ // Constants @@ -85,7 +81,7 @@ module.exports = { create(context) { function getOption(type) { const userOptions = context.options[0] || {}; - if (has(userOptions, type)) { + if (Object.hasOwn(userOptions, type)) { return userOptions[type]; } return DEFAULTS[type]; @@ -166,8 +162,8 @@ module.exports = { 'missingParens', (fixer) => fixer.replaceTextRange( [tokenBefore.range[0], tokenAfter && (tokenAfter.value === ';' || tokenAfter.value === '}') ? tokenAfter.range[0] : node.range[1]], - `${trimTokenBeforeNewline(node, tokenBefore)}(\n${start.column > 0 ? ' '.repeat(start.column) : ''}${getText(context, node)}\n${start.column > 0 ? ' '.repeat(start.column - 2) : ''})` - ) + `${trimTokenBeforeNewline(node, tokenBefore)}(\n${start.column > 0 ? ' '.repeat(start.column) : ''}${getText(context, node)}\n${start.column > 0 ? ' '.repeat(start.column - 2) : ''})`, + ), ); } else { report(node, 'missingParens', (fixer) => fixer.replaceText(node, `(\n${getText(context, node)}\n)`)); @@ -196,7 +192,7 @@ module.exports = { const tokenAfter = sourceCode.getTokenAfter(node); report(node, 'extraParens', (fixer) => fixer.replaceTextRange( [tokenBefore.range[0], tokenAfter.range[1]], - getText(context, node) + getText(context, node), )); } } diff --git a/lib/rules/no-array-index-key.js b/lib/rules/no-array-index-key.js index 90381b3a08..c4a3d54d0f 100644 --- a/lib/rules/no-array-index-key.js +++ b/lib/rules/no-array-index-key.js @@ -5,7 +5,6 @@ 'use strict'; -const has = require('hasown'); const astUtil = require('../util/ast'); const docsUrl = require('../util/docsUrl'); const pragma = require('../util/pragma'); @@ -113,7 +112,7 @@ module.exports = { if (callee.property.type !== 'Identifier') { return null; } - if (!has(iteratorFunctionsToIndexParamPosition, callee.property.name)) { + if (!Object.hasOwn(iteratorFunctionsToIndexParamPosition, callee.property.name)) { return null; } diff --git a/lib/rules/no-arrow-function-lifecycle.js b/lib/rules/no-arrow-function-lifecycle.js index e56cb78601..374f26ee39 100644 --- a/lib/rules/no-arrow-function-lifecycle.js +++ b/lib/rules/no-arrow-function-lifecycle.js @@ -5,18 +5,13 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const astUtil = require('../util/ast'); const componentUtil = require('../util/componentUtil'); const docsUrl = require('../util/docsUrl'); const lifecycleMethods = require('../util/lifecycleMethods'); const report = require('../util/report'); -const eslintUtil = require('../util/eslint'); - -const getSourceCode = eslintUtil.getSourceCode; -const getText = eslintUtil.getText; +const { getSourceCode, getText } = require('../util/eslint'); function getRuleText(node) { const params = node.value.params.map((p) => p.name); @@ -127,11 +122,11 @@ module.exports = { fixer.replaceTextRange(headRange, getRuleText(node)), isBlockBody ? [] : fixer.replaceTextRange( [bodyRange[0], bodyRange[1] + (hasSemi ? 1 : 0)], - `{ return ${previousComment.map((x) => getText(context, x)).join('')}${getText(context, body)}${nextComment.map((x) => getText(context, x)).join('')}; }` - ) + `{ return ${previousComment.map((x) => getText(context, x)).join('')}${getText(context, body)}${nextComment.map((x) => getText(context, x)).join('')}; }`, + ), ); }, - } + }, ); } }); @@ -139,7 +134,7 @@ module.exports = { return { 'Program:exit'() { - values(components.list()).forEach((component) => { + Object.values(components.list()).forEach((component) => { const properties = astUtil.getComponentProperties(component.node); reportNoArrowFunctionLifecycle(properties); }); diff --git a/lib/rules/no-danger.js b/lib/rules/no-danger.js index 54dbed49cf..c1b494b200 100644 --- a/lib/rules/no-danger.js +++ b/lib/rules/no-danger.js @@ -5,8 +5,6 @@ 'use strict'; -const has = require('hasown'); -const fromEntries = require('object.fromentries/polyfill')(); const minimatch = require('minimatch'); const docsUrl = require('../util/docsUrl'); @@ -21,7 +19,7 @@ const DANGEROUS_PROPERTY_NAMES = [ 'dangerouslySetInnerHTML', ]; -const DANGEROUS_PROPERTIES = fromEntries(DANGEROUS_PROPERTY_NAMES.map((prop) => [prop, prop])); +const DANGEROUS_PROPERTIES = Object.fromEntries(DANGEROUS_PROPERTY_NAMES.map((prop) => [prop, prop])); // ------------------------------------------------------------------------------ // Helpers @@ -33,7 +31,7 @@ const DANGEROUS_PROPERTIES = fromEntries(DANGEROUS_PROPERTY_NAMES.map((prop) => * @returns {boolean} Whether or not the attribute is dangerous. */ function isDangerous(name) { - return has(DANGEROUS_PROPERTIES, name); + return Object.hasOwn(DANGEROUS_PROPERTIES, name); } // ------------------------------------------------------------------------------ diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js index 9f5ddf7082..8b19090751 100644 --- a/lib/rules/no-deprecated.js +++ b/lib/rules/no-deprecated.js @@ -7,14 +7,13 @@ 'use strict'; -const entries = require('object.entries'); const astUtil = require('../util/ast'); const componentUtil = require('../util/componentUtil'); const docsUrl = require('../util/docsUrl'); const pragmaUtil = require('../util/pragma'); -const testReactVersion = require('../util/version').testReactVersion; +const { testReactVersion } = require('../util/version'); const report = require('../util/report'); -const getText = require('../util/eslint').getText; +const { getText } = require('../util/eslint'); // ------------------------------------------------------------------------------ // Constants @@ -167,7 +166,7 @@ module.exports = { return false; } - entries(MODULES).some((entry) => { + Object.entries(MODULES).some((entry) => { const key = entry[0]; const moduleNames = entry[1]; if ( @@ -258,7 +257,7 @@ module.exports = { checkDeprecation( node, 'key' in property && 'name' in property.key && `${reactModuleName || pragma}.${property.key.name}`, - property + property, ); }); }, diff --git a/lib/rules/no-direct-mutation-state.js b/lib/rules/no-direct-mutation-state.js index 761151fbb8..c7539cc5f5 100644 --- a/lib/rules/no-direct-mutation-state.js +++ b/lib/rules/no-direct-mutation-state.js @@ -6,8 +6,6 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const componentUtil = require('../util/componentUtil'); const docsUrl = require('../util/docsUrl'); @@ -144,7 +142,7 @@ module.exports = { }, 'Program:exit'() { - values(components.list()) + Object.values(components.list()) .filter((component) => !isValid(component)) .forEach((component) => { reportMutations(component); diff --git a/lib/rules/no-invalid-html-attribute.js b/lib/rules/no-invalid-html-attribute.js index b8a14d1ab1..b18e263b7f 100644 --- a/lib/rules/no-invalid-html-attribute.js +++ b/lib/rules/no-invalid-html-attribute.js @@ -5,7 +5,6 @@ 'use strict'; -const matchAll = require('string.prototype.matchall'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); @@ -245,7 +244,7 @@ const messages = { function splitIntoRangedParts(node, regex) { const valueRangeStart = node.range[0] + 1; // the plus one is for the initial quote - return Array.from(matchAll(node.value, regex), (match) => { + return Array.from(node.value.matchAll(regex), (match) => { const start = match.index + valueRangeStart; const end = start + match[0].length; @@ -396,7 +395,7 @@ function checkAttribute(context, node) { if (!COMPONENT_ATTRIBUTE_MAP.has(attribute) || !COMPONENT_ATTRIBUTE_MAP.get(attribute).has(parentNodeName)) { const tagNames = Array.from( COMPONENT_ATTRIBUTE_MAP.get(attribute).values(), - (tagName) => `"<${tagName}>"` + (tagName) => `"<${tagName}>"`, ).join(', '); const data = { attributeName: attribute, @@ -528,21 +527,19 @@ function checkCreateProps(context, node, attribute) { return; // can't check variables, computed, or shorthands } - for (const prop of propsArg.properties) { + propsArg.properties.forEach((prop) => { if (!prop.key || prop.key.type !== 'Identifier') { - // eslint-disable-next-line no-continue - continue; // cannot check computed keys + return; // cannot check computed keys } if (prop.key.name !== attribute) { - // eslint-disable-next-line no-continue - continue; // ignore not this attribute + return; // ignore not this attribute } if (!COMPONENT_ATTRIBUTE_MAP.get(attribute).has(node.arguments[0].value)) { const tagNames = Array.from( COMPONENT_ATTRIBUTE_MAP.get(attribute).values(), - (tagName) => `"<${tagName}>"` + (tagName) => `"<${tagName}>"`, ).join(', '); report(context, messages.onlyMeaningfulFor, 'onlyMeaningfulFor', { @@ -554,8 +551,7 @@ function checkCreateProps(context, node, attribute) { suggest: false, }); - // eslint-disable-next-line no-continue - continue; + return; } if (prop.method) { @@ -567,13 +563,11 @@ function checkCreateProps(context, node, attribute) { suggest: false, }); - // eslint-disable-next-line no-continue - continue; + return; } if (prop.shorthand || prop.computed) { - // eslint-disable-next-line no-continue - continue; // cannot check these + return; // cannot check these } if (prop.value.type === 'ArrayExpression') { @@ -581,12 +575,11 @@ function checkCreateProps(context, node, attribute) { checkPropValidValue(context, node, value, attribute); }); - // eslint-disable-next-line no-continue - continue; + return; } checkPropValidValue(context, node, prop.value, attribute); - } + }); } /** @type {import('eslint').Rule.RuleModule} */ diff --git a/lib/rules/no-multi-comp.js b/lib/rules/no-multi-comp.js index 8cf73c90bc..d3e826cd79 100644 --- a/lib/rules/no-multi-comp.js +++ b/lib/rules/no-multi-comp.js @@ -5,8 +5,6 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); @@ -67,7 +65,7 @@ module.exports = { return; } - values(components.list()) + Object.values(components.list()) .filter((component) => !isIgnored(component)) .slice(1) .forEach((component) => { diff --git a/lib/rules/no-object-type-as-default-prop.js b/lib/rules/no-object-type-as-default-prop.js index 2683bfea4c..0bad2dd5f6 100644 --- a/lib/rules/no-object-type-as-default-prop.js +++ b/lib/rules/no-object-type-as-default-prop.js @@ -5,8 +5,6 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); const astUtil = require('../util/ast'); @@ -93,7 +91,7 @@ module.exports = { create: Components.detect((context, components) => ({ 'Program:exit'() { const list = components.list(); - values(list) + Object.values(list) .filter((component) => hasUsedObjectDestructuringSyntax(component.node.params)) .forEach((component) => { const node = component.node; diff --git a/lib/rules/no-set-state.js b/lib/rules/no-set-state.js index 44967bf03c..e3db687b46 100644 --- a/lib/rules/no-set-state.js +++ b/lib/rules/no-set-state.js @@ -5,8 +5,6 @@ 'use strict'; -const values = require('object.values'); - const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); const report = require('../util/report'); @@ -77,7 +75,7 @@ module.exports = { }, 'Program:exit'() { - values(components.list()) + Object.values(components.list()) .filter((component) => !isValid(component)) .forEach((component) => { reportSetStateUsages(component); diff --git a/lib/rules/no-unescaped-entities.js b/lib/rules/no-unescaped-entities.js index 3ec2cb23b6..b9d8f110bb 100644 --- a/lib/rules/no-unescaped-entities.js +++ b/lib/rules/no-unescaped-entities.js @@ -137,7 +137,7 @@ module.exports = { return fixer.replaceText(node, newText); }, - } + }, )), }); } diff --git a/lib/rules/no-unknown-property.js b/lib/rules/no-unknown-property.js index dc5018007a..d323633829 100644 --- a/lib/rules/no-unknown-property.js +++ b/lib/rules/no-unknown-property.js @@ -5,10 +5,9 @@ 'use strict'; -const has = require('hasown'); const docsUrl = require('../util/docsUrl'); -const getText = require('../util/eslint').getText; -const testReactVersion = require('../util/version').testReactVersion; +const { getText } = require('../util/eslint'); +const { testReactVersion } = require('../util/version'); const report = require('../util/report'); // ------------------------------------------------------------------------------ @@ -494,10 +493,10 @@ function tagNameHasDot(node) { * @returns {string | undefined} The standard name of the attribute, or undefined if no standard name was found. */ function getStandardName(name, context) { - if (has(DOM_ATTRIBUTE_NAMES, name)) { + if (Object.hasOwn(DOM_ATTRIBUTE_NAMES, name)) { return DOM_ATTRIBUTE_NAMES[/** @type {keyof DOM_ATTRIBUTE_NAMES} */ (name)]; } - if (has(SVGDOM_ATTRIBUTE_NAMES, name)) { + if (Object.hasOwn(SVGDOM_ATTRIBUTE_NAMES, name)) { return SVGDOM_ATTRIBUTE_NAMES[/** @type {keyof SVGDOM_ATTRIBUTE_NAMES} */ (name)]; } const names = getDOMPropertyNames(context); @@ -597,7 +596,7 @@ module.exports = { // Let's dive deeper into tags that are HTML/DOM elements (`