From cfabdcec19b229a55a25aeee25d9a68af0a97b59 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= <info@michaeldeboey.be>
Date: Tue, 29 Oct 2024 15:58:13 +0100
Subject: [PATCH 1/2] feat: drop Node 4, 6, 8, 10, 12, 14 & 16 support

BREAKING CHANGE: Requires Node@^18.18.0 || ^20.9.0 || >=21.1.0
---
 .eslintrc                                     |  14 +--
 .github/workflows/node-minors.yml             | 117 ------------------
 .github/workflows/{node-18+.yml => node.yml}  |   4 +-
 lib/rules/boolean-prop-naming.js              |  12 +-
 lib/rules/button-has-type.js                  |   2 +-
 .../checked-requires-onchange-or-readonly.js  |  10 +-
 lib/rules/default-props-match-prop-types.js   |   2 +-
 lib/rules/display-name.js                     |   2 +-
 lib/rules/forbid-component-props.js           |   4 +-
 lib/rules/forbid-elements.js                  |   2 +-
 lib/rules/forward-ref-uses-ref.js             |   6 +-
 lib/rules/function-component-definition.js    |  10 +-
 lib/rules/hook-use-state.js                   |  14 +--
 lib/rules/jsx-closing-tag-location.js         |   4 +-
 lib/rules/jsx-curly-brace-presence.js         |   4 +-
 lib/rules/jsx-curly-spacing.js                |   2 +-
 lib/rules/jsx-handler-names.js                |   2 +-
 lib/rules/jsx-indent-props.js                 |   2 +-
 lib/rules/jsx-indent.js                       |  11 +-
 lib/rules/jsx-key.js                          |   6 +-
 lib/rules/jsx-newline.js                      |   4 +-
 lib/rules/jsx-no-bind.js                      |   4 +-
 .../jsx-no-constructed-context-values.js      |   2 +-
 lib/rules/jsx-no-leaked-render.js             |   2 +-
 lib/rules/jsx-no-literals.js                  |  30 ++---
 lib/rules/jsx-no-target-blank.js              |  16 ++-
 lib/rules/jsx-no-useless-fragment.js          |   2 +-
 lib/rules/jsx-one-expression-per-line.js      |   2 +-
 lib/rules/jsx-pascal-case.js                  |   6 +-
 lib/rules/jsx-props-no-multi-spaces.js        |  17 ++-
 lib/rules/jsx-props-no-spread-multi.js        |   2 +-
 lib/rules/jsx-sort-props.js                   |   2 +-
 lib/rules/jsx-tag-spacing.js                  |   2 +-
 lib/rules/jsx-wrap-multilines.js              |   6 +-
 lib/rules/no-arrow-function-lifecycle.js      |   6 +-
 lib/rules/no-deprecated.js                    |   2 +-
 lib/rules/no-invalid-html-attribute.js        |  26 ++--
 lib/rules/no-unescaped-entities.js            |   2 +-
 lib/rules/no-unstable-nested-components.js    |   2 +-
 .../no-unused-class-component-methods.js      |   2 +-
 lib/rules/no-unused-prop-types.js             |   2 +-
 lib/rules/no-will-update-set-state.js         |   2 +-
 lib/rules/prefer-read-only-props.js           |   2 +-
 lib/rules/prop-types.js                       |   2 +-
 lib/rules/require-default-props.js            |   4 +-
 lib/rules/self-closing-comp.js                |   2 +-
 lib/rules/sort-comp.js                        |   2 +-
 lib/rules/sort-prop-types.js                  |  67 +++++-----
 lib/util/Components.js                        |  25 ++--
 lib/util/ast.js                               |  10 +-
 lib/util/defaultProps.js                      |   9 +-
 lib/util/eslint.js                            |  26 ++--
 lib/util/propTypes.js                         |  16 +--
 lib/util/propTypesSort.js                     |   6 +-
 lib/util/report.js                            |   4 +-
 package.json                                  |   2 +-
 test/eslint-remote-tester.config.js           |   2 +-
 tests/helpers/parsers.js                      |  78 ++++++------
 tests/helpers/ruleTester.js                   |   2 +-
 tests/index.js                                |   4 +-
 tests/lib/rules/boolean-prop-naming.js        |   2 +-
 tests/lib/rules/button-has-type.js            |   2 +-
 .../checked-requires-onchange-or-readonly.js  |   2 +-
 .../rules/default-props-match-prop-types.js   |   6 +-
 tests/lib/rules/destructuring-assignment.js   |   4 +-
 tests/lib/rules/display-name.js               |   2 +-
 tests/lib/rules/forbid-component-props.js     |   2 +-
 tests/lib/rules/forbid-dom-props.js           |   2 +-
 tests/lib/rules/forbid-elements.js            |   2 +-
 tests/lib/rules/forbid-foreign-prop-types.js  |   2 +-
 tests/lib/rules/forbid-prop-types.js          |   4 +-
 tests/lib/rules/forward-ref-uses-ref.js       |   2 +-
 .../rules/function-component-definition.js    |   2 +-
 tests/lib/rules/hook-use-state.js             |   2 +-
 tests/lib/rules/iframe-missing-sandbox.js     |   2 +-
 tests/lib/rules/jsx-boolean-value.js          |   2 +-
 tests/lib/rules/jsx-child-element-spacing.js  |   2 +-
 .../lib/rules/jsx-closing-bracket-location.js |   2 +-
 tests/lib/rules/jsx-closing-tag-location.js   |   2 +-
 tests/lib/rules/jsx-curly-brace-presence.js   |   6 +-
 tests/lib/rules/jsx-curly-newline.js          |   2 +-
 tests/lib/rules/jsx-curly-spacing.js          |   2 +-
 tests/lib/rules/jsx-equals-spacing.js         |   4 +-
 tests/lib/rules/jsx-filename-extension.js     |   2 +-
 tests/lib/rules/jsx-first-prop-new-line.js    |   2 +-
 tests/lib/rules/jsx-fragments.js              |   2 +-
 tests/lib/rules/jsx-handler-names.js          |   2 +-
 tests/lib/rules/jsx-indent-props.js           |   2 +-
 tests/lib/rules/jsx-indent.js                 |   4 +-
 tests/lib/rules/jsx-key.js                    |   2 +-
 tests/lib/rules/jsx-max-depth.js              |   2 +-
 tests/lib/rules/jsx-max-props-per-line.js     |   2 +-
 tests/lib/rules/jsx-newline.js                |  12 +-
 tests/lib/rules/jsx-no-bind.js                |   2 +-
 tests/lib/rules/jsx-no-comment-textnodes.js   |   2 +-
 .../jsx-no-constructed-context-values.js      |   2 +-
 tests/lib/rules/jsx-no-duplicate-props.js     |   2 +-
 tests/lib/rules/jsx-no-leaked-render.js       |   4 +-
 tests/lib/rules/jsx-no-literals.js            |   2 +-
 tests/lib/rules/jsx-no-script-url.js          |   2 +-
 tests/lib/rules/jsx-no-target-blank.js        |   2 +-
 tests/lib/rules/jsx-no-undef.js               |   6 +-
 tests/lib/rules/jsx-no-useless-fragment.js    |   4 +-
 .../lib/rules/jsx-one-expression-per-line.js  |   2 +-
 tests/lib/rules/jsx-pascal-case.js            |   2 +-
 tests/lib/rules/jsx-props-no-multi-spaces.js  |   6 +-
 tests/lib/rules/jsx-props-no-spread-multi.js  |   2 +-
 tests/lib/rules/jsx-props-no-spreading.js     |   2 +-
 tests/lib/rules/jsx-sort-default-props.js     |   4 +-
 tests/lib/rules/jsx-sort-props.js             |   6 +-
 tests/lib/rules/jsx-space-before-closing.js   |   2 +-
 tests/lib/rules/jsx-tag-spacing.js            |   2 +-
 tests/lib/rules/jsx-uses-react.js             |   2 +-
 tests/lib/rules/jsx-uses-vars.js              |   2 +-
 tests/lib/rules/jsx-wrap-multilines.js        |   2 +-
 .../lib/rules/no-access-state-in-setstate.js  |   2 +-
 .../lib/rules/no-adjacent-inline-elements.js  |   2 +-
 tests/lib/rules/no-array-index-key.js         |   4 +-
 .../lib/rules/no-arrow-function-lifecycle.js  |   2 +-
 tests/lib/rules/no-children-prop.js           |   2 +-
 tests/lib/rules/no-danger-with-children.js    |   2 +-
 tests/lib/rules/no-danger.js                  |   2 +-
 tests/lib/rules/no-deprecated.js              |  89 +++++++------
 tests/lib/rules/no-did-mount-set-state.js     |  14 ++-
 tests/lib/rules/no-did-update-set-state.js    |  14 ++-
 tests/lib/rules/no-direct-mutation-state.js   |   2 +-
 tests/lib/rules/no-find-dom-node.js           |   2 +-
 tests/lib/rules/no-invalid-html-attribute.js  |   4 +-
 tests/lib/rules/no-is-mounted.js              |   2 +-
 tests/lib/rules/no-multi-comp.js              |   4 +-
 tests/lib/rules/no-namespace.js               |   2 +-
 .../rules/no-object-type-as-default-prop.js   |   6 +-
 .../no-redundant-should-component-update.js   |   2 +-
 tests/lib/rules/no-render-return-value.js     |   2 +-
 tests/lib/rules/no-set-state.js               |   2 +-
 tests/lib/rules/no-string-refs.js             |   2 +-
 tests/lib/rules/no-this-in-sfc.js             |   2 +-
 tests/lib/rules/no-typos.js                   |  13 +-
 tests/lib/rules/no-unescaped-entities.js      |   4 +-
 tests/lib/rules/no-unknown-property.js        |   2 +-
 tests/lib/rules/no-unsafe.js                  |   2 +-
 .../rules/no-unstable-nested-components.js    |   2 +-
 .../no-unused-class-component-methods.js      |   2 +-
 tests/lib/rules/no-unused-prop-types.js       |  14 +--
 tests/lib/rules/no-unused-state.js            |   4 +-
 tests/lib/rules/no-will-update-set-state.js   |   2 +-
 tests/lib/rules/prefer-es6-class.js           |   2 +-
 tests/lib/rules/prefer-exact-props.js         |   2 +-
 tests/lib/rules/prefer-read-only-props.js     |   2 +-
 tests/lib/rules/prefer-stateless-function.js  |   2 +-
 tests/lib/rules/prop-types.js                 |  22 ++--
 tests/lib/rules/react-in-jsx-scope.js         |   2 +-
 tests/lib/rules/require-default-props.js      |   6 +-
 tests/lib/rules/require-optimization.js       |   2 +-
 tests/lib/rules/require-render-return.js      |   2 +-
 tests/lib/rules/self-closing-comp.js          |   2 +-
 tests/lib/rules/sort-comp.js                  |   2 +-
 tests/lib/rules/sort-default-props.js         |   4 +-
 tests/lib/rules/sort-prop-types.js            |   6 +-
 tests/lib/rules/state-in-constructor.js       |   2 +-
 tests/lib/rules/static-property-placement.js  |   2 +-
 tests/lib/rules/style-prop-object.js          |   4 +-
 .../rules/void-dom-elements-no-children.js    |   2 +-
 tests/util/Components.js                      |  22 ++--
 tests/util/ast.js                             |   2 +-
 tests/util/jsx.js                             |   4 +-
 tests/util/pragma.js                          |   6 +-
 167 files changed, 478 insertions(+), 620 deletions(-)
 delete mode 100644 .github/workflows/node-minors.yml
 rename .github/workflows/{node-18+.yml => node.yml} (97%)

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 9e227f2b89..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.17' || (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 5a48b15a88..3843caaafc 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/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js
index afa844a903..c867e622b5 100644
--- a/lib/rules/boolean-prop-naming.js
+++ b/lib/rules/boolean-prop-naming.js
@@ -260,7 +260,7 @@ module.exports = {
       }
 
       const annotationTypeArguments = propsUtil.getTypeArguments(
-        component.node.parent.id.typeAnnotation.typeAnnotation
+        component.node.parent.id.typeAnnotation.typeAnnotation,
       );
       if (
         annotationTypeArguments && (
@@ -269,7 +269,7 @@ module.exports = {
         )
       ) {
         return annotationTypeArguments.params.find(
-          (param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation'
+          (param) => param.type === 'TSTypeReference' || param.type === 'GenericTypeAnnotation',
         );
       }
     }
@@ -278,7 +278,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 +317,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 +343,7 @@ module.exports = {
           astUtil.isCallExpression(right)
           && propWrapperUtil.isPropWrapperFunction(
             context,
-            getText(context, right.callee)
+            getText(context, right.callee),
           )
         ) {
           checkPropWrapperArguments(component.node, right.arguments);
@@ -407,7 +407,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..7358426af9 100644
--- a/lib/rules/checked-requires-onchange-or-readonly.js
+++ b/lib/rules/checked-requires-onchange-or-readonly.js
@@ -36,8 +36,8 @@ function extractTargetProps(properties, keyName) {
         prop[keyName] && targetPropSet.has(prop[keyName].name)
           ? [prop[keyName].name]
           : []
-      )
-    )
+      ),
+    ),
   );
 }
 
@@ -64,14 +64,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 +80,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..de30f0d6ac 100644
--- a/lib/rules/default-props-match-prop-types.js
+++ b/lib/rules/default-props-match-prop-types.js
@@ -100,7 +100,7 @@ module.exports = {
           .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..4b07f74de7 100644
--- a/lib/rules/display-name.js
+++ b/lib/rules/display-name.js
@@ -276,7 +276,7 @@ module.exports = {
           // 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..299ee3b849 100644
--- a/lib/rules/forbid-elements.js
+++ b/lib/rules/forbid-elements.js
@@ -86,7 +86,7 @@ module.exports = {
               element,
               message,
             },
-          }
+          },
         );
       }
     }
diff --git a/lib/rules/forward-ref-uses-ref.js b/lib/rules/forward-ref-uses-ref.js
index 3a0b7de4c9..f853f7bbc5 100644
--- a/lib/rules/forward-ref-uses-ref.js
+++ b/lib/rules/forward-ref-uses-ref.js
@@ -78,10 +78,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),
@@ -89,7 +89,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..4801463b10 100644
--- a/lib/rules/function-component-definition.js
+++ b/lib/rules/function-component-definition.js
@@ -19,7 +19,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 +72,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 +176,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 +214,7 @@ module.exports = {
           body: getBody(node, source),
           name: getName(node),
           varType,
-        })
+        }),
       );
     }
 
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-tag-location.js b/lib/rules/jsx-closing-tag-location.js
index 5f6f6efe38..f55570f3ca 100644
--- a/lib/rules/jsx-closing-tag-location.js
+++ b/lib/rules/jsx-closing-tag-location.js
@@ -119,13 +119,13 @@ module.exports = {
         fix(fixer) {
           const indent = repeat(
             ' ',
-            getIndentation(openingStartOfLine, opening)
+            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..695e08a075 100755
--- a/lib/rules/jsx-curly-brace-presence.js
+++ b/lib/rules/jsx-curly-brace-presence.js
@@ -179,7 +179,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 +241,7 @@ module.exports = {
 
           const expression = literalNode.parent.type === 'JSXAttribute'
             ? `{"${escapeDoubleQuotes(escapeBackslashes(
-              literalNode.raw.slice(1, -1)
+              literalNode.raw.slice(1, -1),
             ))}"}`
             : wrapWithCurlyBraces(literalNode.raw);
 
diff --git a/lib/rules/jsx-curly-spacing.js b/lib/rules/jsx-curly-spacing.js
index fda49381ce..277297403b 100644
--- a/lib/rules/jsx-curly-spacing.js
+++ b/lib/rules/jsx-curly-spacing.js
@@ -142,7 +142,7 @@ 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,
diff --git a/lib/rules/jsx-handler-names.js b/lib/rules/jsx-handler-names.js
index f89f24413e..900e23381f 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..9badb7f4cc 100644
--- a/lib/rules/jsx-indent-props.js
+++ b/lib/rules/jsx-indent-props.js
@@ -133,7 +133,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)
+            repeat(indentType === 'space' ? ' ' : '\t', needed),
           );
         },
       });
diff --git a/lib/rules/jsx-indent.js b/lib/rules/jsx-indent.js
index f27eca029d..9d5e0c034a 100644
--- a/lib/rules/jsx-indent.js
+++ b/lib/rules/jsx-indent.js
@@ -130,7 +130,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 +139,7 @@ module.exports = {
       return function fix(fixer) {
         return fixer.replaceTextRange(
           [node.range[0] - node.loc.start.column, node.range[0]],
-          indent
+          indent,
         );
       };
     }
@@ -159,11 +159,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 } : {}),
+      });
     }
 
     /**
@@ -326,7 +327,7 @@ module.exports = {
       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)
+        (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..ab15bdf2b4 100644
--- a/lib/rules/jsx-key.js
+++ b/lib/rules/jsx-key.js
@@ -66,7 +66,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 +109,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);
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 19af331253..a9032c4d68 100644
--- a/lib/rules/jsx-no-constructed-context-values.js
+++ b/lib/rules/jsx-no-constructed-context-values.js
@@ -207,7 +207,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-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 45c9a54c48..fac347d198 100644
--- a/lib/rules/jsx-no-literals.js
+++ b/lib/rules/jsx-no-literals.js
@@ -124,8 +124,8 @@ function normalizeConfig(config) {
               applyToNestedElements: typeof rawElementConfig.applyToNestedElements === 'undefined' || !!rawElementConfig.applyToNestedElements,
             }),
           ]];
-        }
-      )
+        },
+      ),
     );
   }
 
@@ -137,10 +137,10 @@ const elementOverrides = {
   patternProperties: {
     [reOverridableElement.source]: {
       type: 'object',
-      properties: Object.assign(
-        { applyToNestedElements: { type: 'boolean' } },
-        commonPropertiesSchema
-      ),
+      properties: {
+        applyToNestedElements: { type: 'boolean' },
+        ...commonPropertiesSchema,
+      },
 
     },
   },
@@ -160,10 +160,10 @@ module.exports = {
 
     schema: [{
       type: 'object',
-      properties: Object.assign(
-        { elementOverrides },
-        commonPropertiesSchema
-      ),
+      properties: {
+        elementOverrides,
+        ...commonPropertiesSchema,
+      },
       additionalProperties: false,
     }],
   }),
@@ -346,15 +346,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);
@@ -372,7 +372,7 @@ module.exports = {
             }
           }
         }
-      }
+      });
     }
 
     // eslint-disable-next-line valid-jsdoc
@@ -430,7 +430,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-target-blank.js b/lib/rules/jsx-no-target-blank.js
index 9f5d239d6c..779346e268 100644
--- a/lib/rules/jsx-no-target-blank.js
+++ b/lib/rules/jsx-no-target-blank.js
@@ -165,15 +165,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..979b805787 100644
--- a/lib/rules/jsx-no-useless-fragment.js
+++ b/lib/rules/jsx-no-useless-fragment.js
@@ -145,7 +145,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 3103be86da..1a8913435a 100644
--- a/lib/rules/jsx-props-no-spread-multi.js
+++ b/lib/rules/jsx-props-no-spread-multi.js
@@ -33,7 +33,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..09ff604a37 100644
--- a/lib/rules/jsx-sort-props.js
+++ b/lib/rules/jsx-sort-props.js
@@ -286,7 +286,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) {
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..05600cef58 100644
--- a/lib/rules/jsx-wrap-multilines.js
+++ b/lib/rules/jsx-wrap-multilines.js
@@ -166,8 +166,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 +196,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-arrow-function-lifecycle.js b/lib/rules/no-arrow-function-lifecycle.js
index e56cb78601..26596d91ea 100644
--- a/lib/rules/no-arrow-function-lifecycle.js
+++ b/lib/rules/no-arrow-function-lifecycle.js
@@ -127,11 +127,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('')}; }`,
+                  ),
                 );
               },
-            }
+            },
           );
         }
       });
diff --git a/lib/rules/no-deprecated.js b/lib/rules/no-deprecated.js
index 0c5931345f..638b7677cf 100644
--- a/lib/rules/no-deprecated.js
+++ b/lib/rules/no-deprecated.js
@@ -258,7 +258,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-invalid-html-attribute.js b/lib/rules/no-invalid-html-attribute.js
index b8a14d1ab1..3fd69db8ca 100644
--- a/lib/rules/no-invalid-html-attribute.js
+++ b/lib/rules/no-invalid-html-attribute.js
@@ -396,7 +396,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 +528,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 +552,7 @@ function checkCreateProps(context, node, attribute) {
         suggest: false,
       });
 
-      // eslint-disable-next-line no-continue
-      continue;
+      return;
     }
 
     if (prop.method) {
@@ -567,13 +564,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 +576,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-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-unstable-nested-components.js b/lib/rules/no-unstable-nested-components.js
index c330795ff0..f2ce130219 100644
--- a/lib/rules/no-unstable-nested-components.js
+++ b/lib/rules/no-unstable-nested-components.js
@@ -451,7 +451,7 @@ module.exports = {
       const parentComponent = getClosestMatchingParent(
         node,
         context,
-        (nodeToMatch) => components.get(nodeToMatch)
+        (nodeToMatch) => components.get(nodeToMatch),
       );
 
       if (parentComponent) {
diff --git a/lib/rules/no-unused-class-component-methods.js b/lib/rules/no-unused-class-component-methods.js
index 4356cc2a5e..a82ae6f87a 100644
--- a/lib/rules/no-unused-class-component-methods.js
+++ b/lib/rules/no-unused-class-component-methods.js
@@ -151,7 +151,7 @@ module.exports = {
                 name,
                 className,
               },
-            }
+            },
           );
         }
       }
diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js
index 09dcfb5b58..24fcee4173 100644
--- a/lib/rules/no-unused-prop-types.js
+++ b/lib/rules/no-unused-prop-types.js
@@ -69,7 +69,7 @@ module.exports = {
 
   create: Components.detect((context, components) => {
     const defaults = { skipShapeProps: true, customValidators: [], ignore: [] };
-    const configuration = Object.assign({}, defaults, context.options[0] || {});
+    const configuration = { ...defaults, ...context.options[0] || {} };
 
     /**
      * Checks if the prop is ignored
diff --git a/lib/rules/no-will-update-set-state.js b/lib/rules/no-will-update-set-state.js
index 16e6be43b9..b69656a79f 100644
--- a/lib/rules/no-will-update-set-state.js
+++ b/lib/rules/no-will-update-set-state.js
@@ -11,5 +11,5 @@ const testReactVersion = require('../util/version').testReactVersion;
 /** @type {import('eslint').Rule.RuleModule} */
 module.exports = makeNoMethodSetStateRule(
   'componentWillUpdate',
-  (context) => testReactVersion(context, '>= 16.3.0')
+  (context) => testReactVersion(context, '>= 16.3.0'),
 );
diff --git a/lib/rules/prefer-read-only-props.js b/lib/rules/prefer-read-only-props.js
index c00b09f9e4..0729752db6 100644
--- a/lib/rules/prefer-read-only-props.js
+++ b/lib/rules/prefer-read-only-props.js
@@ -78,7 +78,7 @@ module.exports = {
       'Program:exit'() {
         flatMap(
           values(components.list()),
-          (component) => component.declaredPropTypes || []
+          (component) => component.declaredPropTypes || [],
         ).forEach((declaredPropTypes) => {
           Object.keys(declaredPropTypes).forEach((propName) => {
             const prop = declaredPropTypes[propName];
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index dabe5b0e7b..424a1557b9 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -130,7 +130,7 @@ module.exports = {
             unionPropType[key] = unionTypes[k];
             const isValid = internalIsDeclaredInComponent(
               unionPropType,
-              keyList.slice(i)
+              keyList.slice(i),
             );
             if (isValid) {
               return true;
diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js
index c186279cd4..d82d6b9e25 100644
--- a/lib/rules/require-default-props.js
+++ b/lib/rules/require-default-props.js
@@ -194,12 +194,12 @@ module.exports = {
             reportFunctionComponent(
               component.node,
               component.declaredPropTypes,
-              component.defaultProps
+              component.defaultProps,
             );
           } else {
             reportPropTypesWithoutDefault(
               component.declaredPropTypes,
-              component.defaultProps || {}
+              component.defaultProps || {},
             );
           }
         });
diff --git a/lib/rules/self-closing-comp.js b/lib/rules/self-closing-comp.js
index 23e168605f..0e74f9de0d 100644
--- a/lib/rules/self-closing-comp.js
+++ b/lib/rules/self-closing-comp.js
@@ -73,7 +73,7 @@ module.exports = {
 
   create(context) {
     function isShouldBeSelfClosed(node) {
-      const configuration = Object.assign({}, optionDefaults, context.options[0]);
+      const configuration = { ...optionDefaults, ...context.options[0] };
       return (
         (configuration.component && isComponent(node))
         || (configuration.html && jsxUtil.isDOMComponent(node))
diff --git a/lib/rules/sort-comp.js b/lib/rules/sort-comp.js
index ee409b780d..edb052ffce 100644
--- a/lib/rules/sort-comp.js
+++ b/lib/rules/sort-comp.js
@@ -61,7 +61,7 @@ const defaultConfig = {
 function getMethodsOrder(userConfig) {
   userConfig = userConfig || {};
 
-  const groups = Object.assign({}, defaultConfig.groups, userConfig.groups);
+  const groups = { ...defaultConfig.groups, ...userConfig.groups };
   const order = userConfig.order || defaultConfig.order;
 
   let config = [];
diff --git a/lib/rules/sort-prop-types.js b/lib/rules/sort-prop-types.js
index 6aaebea184..f659a7c663 100644
--- a/lib/rules/sort-prop-types.js
+++ b/lib/rules/sort-prop-types.js
@@ -109,7 +109,7 @@ module.exports = {
           callbacksLast,
           noSortAlphabetically,
           sortShapeProp,
-          checkTypes
+          checkTypes,
         );
       }
 
@@ -233,7 +233,7 @@ module.exports = {
       }
     }
 
-    return Object.assign({
+    return {
       CallExpression(node) {
         if (!sortShapeProp || !propTypesSortUtil.isShapeProp(node) || !(node.arguments && node.arguments[0])) {
           return;
@@ -279,38 +279,39 @@ module.exports = {
           }
         });
       },
-    }, checkTypes ? {
-      TSTypeLiteral(node) {
-        if (node && node.parent.id) {
-          const currentNode = [].concat(
-            typeAnnotations.get(node.parent.id.name) || [],
-            node
-          );
-          typeAnnotations.set(node.parent.id.name, currentNode);
-        }
-      },
+      ...(checkTypes ? {
+        TSTypeLiteral(node) {
+          if (node && node.parent.id) {
+            const currentNode = [].concat(
+              typeAnnotations.get(node.parent.id.name) || [],
+              node,
+            );
+            typeAnnotations.set(node.parent.id.name, currentNode);
+          }
+        },
 
-      TypeAlias(node) {
-        if (node.right.type === 'ObjectTypeAnnotation') {
-          const currentNode = [].concat(
-            typeAnnotations.get(node.id.name) || [],
-            node.right
-          );
-          typeAnnotations.set(node.id.name, currentNode);
-        }
-      },
+        TypeAlias(node) {
+          if (node.right.type === 'ObjectTypeAnnotation') {
+            const currentNode = [].concat(
+              typeAnnotations.get(node.id.name) || [],
+              node.right,
+            );
+            typeAnnotations.set(node.id.name, currentNode);
+          }
+        },
 
-      TSTypeAliasDeclaration(node) {
-        if (node.typeAnnotation.type === 'TSTypeLiteral' || node.typeAnnotation.type === 'ObjectTypeAnnotation') {
-          const currentNode = [].concat(
-            typeAnnotations.get(node.id.name) || [],
-            node.typeAnnotation
-          );
-          typeAnnotations.set(node.id.name, currentNode);
-        }
-      },
-      FunctionDeclaration: handleFunctionComponent,
-      ArrowFunctionExpression: handleFunctionComponent,
-    } : null);
+        TSTypeAliasDeclaration(node) {
+          if (node.typeAnnotation.type === 'TSTypeLiteral' || node.typeAnnotation.type === 'ObjectTypeAnnotation') {
+            const currentNode = [].concat(
+              typeAnnotations.get(node.id.name) || [],
+              node.typeAnnotation,
+            );
+            typeAnnotations.set(node.id.name, currentNode);
+          }
+        },
+        FunctionDeclaration: handleFunctionComponent,
+        ArrowFunctionExpression: handleFunctionComponent,
+      } : null),
+    };
   },
 };
diff --git a/lib/util/Components.js b/lib/util/Components.js
index 446fd9022a..d58b4fd45a 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -129,9 +129,9 @@ class Components {
       {
         usedPropTypes: mergeUsedPropTypes(
           component.usedPropTypes || [],
-          props.usedPropTypes || []
+          props.usedPropTypes || [],
         ),
-      }
+      },
     );
   }
 
@@ -218,9 +218,10 @@ class Components {
    */
   addDefaultReactImport(specifier) {
     const info = ReactImports.get(this);
-    ReactImports.set(this, Object.assign({}, info, {
+    ReactImports.set(this, {
+      ...info,
       defaultReactImports: (info.defaultReactImports || []).concat(specifier),
-    }));
+    });
   }
 
   /**
@@ -231,9 +232,10 @@ class Components {
    */
   addNamedReactImport(specifier) {
     const info = ReactImports.get(this);
-    ReactImports.set(this, Object.assign({}, info, {
+    ReactImports.set(this, {
+      ...info,
       namedReactImports: (info.namedReactImports || []).concat(specifier),
-    }));
+    });
   }
 }
 
@@ -244,7 +246,8 @@ function getWrapperFunctions(context, pragma) {
   return componentWrapperFunctions.map((wrapperFunction) => {
     return typeof wrapperFunction === 'string'
       ? { property: wrapperFunction }
-      : Object.assign({}, wrapperFunction, {
+      : ({
+        ...wrapperFunction,
         object: wrapperFunction.object === '<pragma>' ? pragma : wrapperFunction.object,
       });
   }).concat([
@@ -794,7 +797,7 @@ function componentRule(rule, context) {
       const reactResolvedDefs = isPotentialReactHookCall
         && scope.references
         && scope.references.find(
-          (reference) => reference.identifier.name === defaultReactImportName
+          (reference) => reference.identifier.name === defaultReactImportName,
         ).resolved.defs;
 
       const isReactShadowed = isPotentialReactHookCall && reactResolvedDefs
@@ -803,7 +806,7 @@ function componentRule(rule, context) {
       const potentialHookReference = isPotentialHookCall
         && scope.references
         && scope.references.find(
-          (reference) => reactHookImportNames[reference.identifier.name]
+          (reference) => reactHookImportNames[reference.identifier.name],
         );
 
       const hookResolvedDefs = potentialHookReference && potentialHookReference.resolved.defs;
@@ -819,7 +822,7 @@ function componentRule(rule, context) {
         && hookResolvedDefs
         && hookResolvedDefs.some(
           (hookDef) => hookDef.name.name === localHookName
-          && hookDef.type !== 'ImportBinding'
+          && hookDef.type !== 'ImportBinding',
         );
 
       const isHookCall = (isPotentialReactHookCall && !isReactShadowed)
@@ -835,7 +838,7 @@ function componentRule(rule, context) {
 
       return arrayIncludes(
         expectedHookNames,
-        (reactHookImportNames && reactHookImportNames[localHookName]) || localHookName
+        (reactHookImportNames && reactHookImportNames[localHookName]) || localHookName,
       );
     },
   };
diff --git a/lib/util/ast.js b/lib/util/ast.js
index 4cc140254c..25b43e5ff5 100644
--- a/lib/util/ast.js
+++ b/lib/util/ast.js
@@ -19,16 +19,18 @@ const getSourceCode = eslintUtil.getSourceCode;
  * @param {Object} visitor Visitor Object for estraverse
  */
 function traverse(ASTnode, visitor) {
-  const opts = Object.assign({}, {
+  const opts = {
     fallback(node) {
       return Object.keys(node).filter((key) => key === 'children' || key === 'argument');
     },
-  }, visitor);
+    ...visitor,
+  };
 
-  opts.keys = Object.assign({}, visitor.keys, {
+  opts.keys = {
+    ...visitor.keys,
     JSXElement: ['children'],
     JSXFragment: ['children'],
-  });
+  };
 
   estraverse.traverse(ASTnode, opts);
 }
diff --git a/lib/util/defaultProps.js b/lib/util/defaultProps.js
index b0e88844d5..5bd476394d 100644
--- a/lib/util/defaultProps.js
+++ b/lib/util/defaultProps.js
@@ -87,11 +87,10 @@ module.exports = function defaultPropsInstructions(context, components, utils) {
     }
 
     const defaults = component.defaultProps || {};
-    const newDefaultProps = Object.assign(
-      {},
-      defaults,
-      fromEntries(defaultProps.map((prop) => [prop.name, prop]))
-    );
+    const newDefaultProps = {
+      ...defaults,
+      ...fromEntries(defaultProps.map((prop) => [prop.name, prop])),
+    };
 
     components.set(component.node, {
       defaultProps: newDefaultProps,
diff --git a/lib/util/eslint.js b/lib/util/eslint.js
index 79a0537f3b..b2a3c7de93 100644
--- a/lib/util/eslint.js
+++ b/lib/util/eslint.js
@@ -1,39 +1,27 @@
 'use strict';
 
 function getSourceCode(context) {
-  return context.getSourceCode ? context.getSourceCode() : context.sourceCode;
+  return context.getSourceCode?.() ?? context.sourceCode;
 }
 
 function getAncestors(context, node) {
-  const sourceCode = getSourceCode(context);
-  return sourceCode.getAncestors ? sourceCode.getAncestors(node) : context.getAncestors();
+  return getSourceCode(context).getAncestors?.(node) ?? context.getAncestors();
 }
 
 function getScope(context, node) {
-  const sourceCode = getSourceCode(context);
-  if (sourceCode.getScope) {
-    return sourceCode.getScope(node);
-  }
-
-  return context.getScope();
+  return getSourceCode(context).getScope?.(node) ?? context.getScope();
 }
 
 function markVariableAsUsed(name, node, context) {
-  const sourceCode = getSourceCode(context);
-  return sourceCode.markVariableAsUsed
-    ? sourceCode.markVariableAsUsed(name, node)
-    : context.markVariableAsUsed(name);
+  return getSourceCode(context).markVariableAsUsed?.(name, node) ?? context.markVariableAsUsed(name);
 }
 
 function getFirstTokens(context, node, count) {
-  const sourceCode = getSourceCode(context);
-  return sourceCode.getFirstTokens ? sourceCode.getFirstTokens(node, count) : context.getFirstTokens(node, count);
+  return getSourceCode(context).getFirstTokens?.(node, count) ?? context.getFirstTokens(node, count);
 }
 
-function getText(context) {
-  const sourceCode = getSourceCode(context);
-  const args = Array.prototype.slice.call(arguments, 1);
-  return sourceCode.getText ? sourceCode.getText.apply(sourceCode, args) : context.getSource.apply(context, args);
+function getText(context, arg) {
+  return getSourceCode(context).getText?.(arg) ?? context.getSource(arg);
 }
 
 module.exports = {
diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js
index 7cec5abbdd..1e073fff88 100644
--- a/lib/util/propTypes.js
+++ b/lib/util/propTypes.js
@@ -105,7 +105,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
 
   const classExpressions = [];
   const defaults = { customValidators: [] };
-  const configuration = Object.assign({}, defaults, context.options[0] || {});
+  const configuration = { ...defaults, ...context.options[0] || {} };
   const customValidators = configuration.customValidators;
   const allowedGenericTypes = new Set(['ComponentProps', 'ComponentPropsWithRef', 'ComponentPropsWithoutRef', 'forwardRef', 'ForwardRefRenderFunction', 'VFC', 'VoidFunctionComponent', 'PropsWithChildren', 'SFC', 'StatelessComponent', 'FunctionComponent', 'FC']);
   const genericTypeParamIndexWherePropsArePresent = {
@@ -204,7 +204,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
             Object.assign(shapeTypeDefinition, types.children);
           }
           containsSpread = true;
-        }
+        },
       );
 
       // Mark if this shape has spread or an indexer. We will know to consider all props from this shape as having propTypes,
@@ -382,7 +382,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
     ) {
       const scope = getScope(context, rootNode);
       const identVariable = scope.variableScope.variables.find(
-        (variable) => variable.name === node.name
+        (variable) => variable.name === node.name,
       );
       if (identVariable) {
         const definition = identVariable.defs[identVariable.defs.length - 1];
@@ -708,7 +708,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
             && type.declaration.declarations
           )
           || type.declaration
-        )
+        ),
       );
 
       // we tried to find either an interface or a type with the TypeReference name
@@ -776,7 +776,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
           if (astUtil.isTSTypeQuery(returnType)) {
             const returnTypeFunction = flatMap(this.sourceCode.ast.body
               .filter((item) => item.type === 'VariableDeclaration'
-                && item.declarations.find((dec) => dec.id.name === returnType.exprName.name)
+                && item.declarations.find((dec) => dec.id.name === returnType.exprName.name),
               ), (type) => type.declarations).map((dec) => dec.init);
 
             if (Array.isArray(returnTypeFunction)) {
@@ -951,7 +951,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
           const types = buildReactDeclarationTypes(
             propTypes.parent.right,
             parentProp,
-            rootNode
+            rootNode,
           );
 
           types.name = propTypes.property.name;
@@ -992,7 +992,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
         if (
           propWrapperUtil.isPropWrapperFunction(
             context,
-            getText(context, propTypes.callee)
+            getText(context, propTypes.callee),
           )
           && propTypes.arguments && propTypes.arguments[0]
         ) {
@@ -1009,7 +1009,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
           const propTypeArguments = propsUtil.getTypeArguments(propTypes);
           ignorePropsValidation = declarePropTypesForObjectTypeAnnotation(
             propTypeArguments.params[0],
-            declaredPropTypes
+            declaredPropTypes,
           );
         } else {
           ignorePropsValidation = true;
diff --git a/lib/util/propTypesSort.js b/lib/util/propTypesSort.js
index 4b42904c63..342e1cb054 100644
--- a/lib/util/propTypesSort.js
+++ b/lib/util/propTypesSort.js
@@ -145,7 +145,7 @@ function fixPropTypesSort(
   callbacksLast,
   noSortAlphabetically,
   sortShapeProp,
-  checkTypes
+  checkTypes,
 ) {
   function sortInSource(allNodes, source) {
     const originalSource = source;
@@ -188,7 +188,7 @@ function fixPropTypesSort(
     nodeGroups.forEach((nodes) => {
       const sortedAttributes = toSorted(
         nodes,
-        (a, b) => sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast, noSortAlphabetically)
+        (a, b) => sorter(a, b, context, ignoreCase, requiredFirst, callbacksLast, noSortAlphabetically),
       );
 
       const sourceCodeText = getText(context);
@@ -206,7 +206,7 @@ function fixPropTypesSort(
           if (shape) {
             const attrSource = sortInSource(
               shape,
-              originalSource
+              originalSource,
             );
             sortedAttrText = attrSource.slice(sortedAttr.range[0], sortedAttr.range[1]);
           }
diff --git a/lib/util/report.js b/lib/util/report.js
index 9c10a13501..312971bc64 100644
--- a/lib/util/report.js
+++ b/lib/util/report.js
@@ -6,7 +6,7 @@ module.exports = function report(context, message, messageId, data) {
   context.report(
     Object.assign(
       getMessageData(messageId, message),
-      data
-    )
+      data,
+    ),
   );
 };
diff --git a/package.json b/package.json
index 56a2abf018..a54490d1ec 100644
--- a/package.json
+++ b/package.json
@@ -92,7 +92,7 @@
     "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
   },
   "engines": {
-    "node": ">=4"
+    "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
   },
   "keywords": [
     "eslint",
diff --git a/test/eslint-remote-tester.config.js b/test/eslint-remote-tester.config.js
index 69ed6abc69..92d0f17ee5 100644
--- a/test/eslint-remote-tester.config.js
+++ b/test/eslint-remote-tester.config.js
@@ -28,7 +28,7 @@ module.exports = {
       },
     ],
     parserOptions: {
-      ecmaVersion: 2020,
+      ecmaVersion: 2022,
       sourceType: 'module',
       ecmaFeatures: {
         jsx: true,
diff --git a/tests/helpers/parsers.js b/tests/helpers/parsers.js
index cbd6568d01..a4d55252a5 100644
--- a/tests/helpers/parsers.js
+++ b/tests/helpers/parsers.js
@@ -7,7 +7,7 @@ const flatMap = require('array.prototype.flatmap');
 const tsParserVersion = require('@typescript-eslint/parser/package.json').version;
 
 const disableNewTS = semver.satisfies(tsParserVersion, '>= 4.1') // this rule is not useful on v4.1+ of the TS parser
-  ? (x) => Object.assign({}, x, { features: [].concat(x.features, 'no-ts-new') })
+  ? (x) => ({ ...x, features: [].concat(x.features, 'no-ts-new') })
   : (x) => x;
 
 function minEcmaVersion(features, parserOptions) {
@@ -16,7 +16,7 @@ function minEcmaVersion(features, parserOptions) {
     'optional chaining': 2020,
     'nullish coalescing': 2020,
   };
-  const result = Math.max.apply(
+  const result = Math.max(
     Math,
     [].concat(
       (parserOptions && parserOptions.ecmaVersion) || [],
@@ -24,8 +24,8 @@ function minEcmaVersion(features, parserOptions) {
         const f = entry[0];
         const y = entry[1];
         return features.has(f) ? y : [];
-      })
-    ).map((y) => (y > 5 && y < 2015 ? y + 2009 : y)) // normalize editions to years
+      }),
+    ).map((y) => (y > 5 && y < 2015 ? y + 2009 : y)), // normalize editions to years
   );
   return Number.isFinite(result) ? result : undefined;
 }
@@ -38,7 +38,8 @@ const parsers = {
   disableNewTS,
   skipDueToMultiErrorSorting: semver.satisfies(process.versions.node, '^8 || ^9'),
   babelParserOptions: function parserOptions(test, features) {
-    return Object.assign({}, test.parserOptions, {
+    return {
+      ...test.parserOptions,
       requireConfigFile: false,
       babelOptions: {
         presets: [
@@ -54,16 +55,14 @@ const parsers = {
           allowReturnOutsideFunction: false,
         },
       },
-      ecmaFeatures: Object.assign(
-        {},
-        test.parserOptions && test.parserOptions.ecmaFeatures,
-        {
-          jsx: true,
-          modules: true,
-          legacyDecorators: features.has('decorators'),
-        }
-      ),
-    });
+      ecmaFeatures: {
+
+        ...test.parserOptions && test.parserOptions.ecmaFeatures,
+        jsx: true,
+        modules: true,
+        legacyDecorators: features.has('decorators'),
+      },
+    };
   },
   all: function all(tests) {
     const t = flatMap(tests, (test) => {
@@ -85,7 +84,7 @@ const parsers = {
           `parser: ${parser}`,
           testObject.parserOptions ? `parserOptions: ${JSON.stringify(testObject.parserOptions)}` : [],
           testObject.options ? `options: ${JSON.stringify(testObject.options)}` : [],
-          testObject.settings ? `settings: ${JSON.stringify(testObject.settings)}` : []
+          testObject.settings ? `settings: ${JSON.stringify(testObject.settings)}` : [],
         );
 
         const extraComment = `\n// ${extras.join(', ')}`;
@@ -103,23 +102,21 @@ const parsers = {
             errors: testObject.errors.map(
               (errorObject) => {
                 const nextSuggestions = errorObject.suggestions && typeof errorObject.suggestions !== 'number' && {
-                  suggestions: errorObject.suggestions.map((suggestion) => Object.assign({}, suggestion, {
-                    output: suggestion.output + extraComment,
-                  })),
+                  suggestions: errorObject.suggestions.map((suggestion) => ({ ...suggestion, output: suggestion.output + extraComment })),
                 };
 
-                return Object.assign({}, errorObject, nextSuggestions);
-              }
+                return { ...errorObject, ...nextSuggestions };
+              },
             ),
           };
 
-        return Object.assign(
-          {},
-          testObject,
-          nextCode,
-          nextOutput,
-          nextErrors
-        );
+        return {
+
+          ...testObject,
+          ...nextCode,
+          ...nextOutput,
+          ...nextErrors,
+        };
       }
 
       const skipBase = (features.has('class fields') && semver.satisfies(version, '< 8'))
@@ -155,21 +152,26 @@ const parsers = {
 
       return [].concat(
         skipBase ? [] : addComment(
-          Object.assign({}, test, typeof es === 'number' && {
-            parserOptions: Object.assign({}, test.parserOptions, { ecmaVersion: es }),
-          }),
-          'default'
+          {
+            ...test,
+            ...typeof es === 'number' && {
+              parserOptions: { ...test.parserOptions, ecmaVersion: es },
+            },
+          },
+          'default',
         ),
-        skipOldBabel ? [] : addComment(Object.assign({}, test, {
+        skipOldBabel ? [] : addComment({
+          ...test,
           parser: parsers.BABEL_ESLINT,
           parserOptions: parsers.babelParserOptions(test, features),
-        }), 'babel-eslint'),
-        skipNewBabel ? [] : addComment(Object.assign({}, test, {
+        }, 'babel-eslint'),
+        skipNewBabel ? [] : addComment({
+          ...test,
           parser: parsers['@BABEL_ESLINT'],
           parserOptions: parsers.babelParserOptions(test, features),
-        }), '@babel/eslint-parser'),
-        tsOld ? addComment(Object.assign({}, test, { parser: parsers.TYPESCRIPT_ESLINT }), 'typescript-eslint') : [],
-        tsNew ? addComment(Object.assign({}, test, { parser: parsers['@TYPESCRIPT_ESLINT'] }), '@typescript-eslint/parser') : []
+        }, '@babel/eslint-parser'),
+        tsOld ? addComment({ ...test, parser: parsers.TYPESCRIPT_ESLINT }, 'typescript-eslint') : [],
+        tsNew ? addComment({ ...test, parser: parsers['@TYPESCRIPT_ESLINT'] }, '@typescript-eslint/parser') : [],
       );
     });
 
diff --git a/tests/helpers/ruleTester.js b/tests/helpers/ruleTester.js
index f754c13e04..9a8c20a704 100644
--- a/tests/helpers/ruleTester.js
+++ b/tests/helpers/ruleTester.js
@@ -14,7 +14,7 @@ function convertToFlat(item, plugins) {
     throw new TypeError('Invalid value for "item" option. Expected an object or a string.');
   }
 
-  const newItem = Object.assign({}, item, { languageOptions: {} });
+  const newItem = { ...item, languageOptions: {} };
 
   if (newItem.parserOptions) {
     newItem.languageOptions.parserOptions = newItem.parserOptions;
diff --git a/tests/index.js b/tests/index.js
index 3539f48136..ac1137a6ec 100644
--- a/tests/index.js
+++ b/tests/index.js
@@ -19,14 +19,14 @@ describe('all rule files should be exported by the plugin', () => {
     it(`should export ${ruleName}`, () => {
       assert.equal(
         plugin.rules[ruleName],
-        require(path.join('../lib/rules', ruleName)) // eslint-disable-line global-require, import/no-dynamic-require
+        require(path.join('../lib/rules', ruleName)), // eslint-disable-line global-require, import/no-dynamic-require
       );
     });
 
     it(`should export ${ruleName} from lib/rules/index`, () => {
       assert.equal(
         plugin.rules[ruleName],
-        index[ruleName]
+        index[ruleName],
       );
     });
   });
diff --git a/tests/lib/rules/boolean-prop-naming.js b/tests/lib/rules/boolean-prop-naming.js
index 84a50c9187..eddbfab2d5 100644
--- a/tests/lib/rules/boolean-prop-naming.js
+++ b/tests/lib/rules/boolean-prop-naming.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/boolean-prop-naming');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/button-has-type.js b/tests/lib/rules/button-has-type.js
index e5d6be6d5e..b323569cc6 100644
--- a/tests/lib/rules/button-has-type.js
+++ b/tests/lib/rules/button-has-type.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/button-has-type');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/checked-requires-onchange-or-readonly.js b/tests/lib/rules/checked-requires-onchange-or-readonly.js
index 1f8bb551db..9f1a32036b 100644
--- a/tests/lib/rules/checked-requires-onchange-or-readonly.js
+++ b/tests/lib/rules/checked-requires-onchange-or-readonly.js
@@ -12,7 +12,7 @@ const parsers = require('../../helpers/parsers');
 
 const ruleTester = new RuleTester({
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
     ecmaFeatures: {
       jsx: true,
diff --git a/tests/lib/rules/default-props-match-prop-types.js b/tests/lib/rules/default-props-match-prop-types.js
index fdc86dc357..99ed892d08 100644
--- a/tests/lib/rules/default-props-match-prop-types.js
+++ b/tests/lib/rules/default-props-match-prop-types.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/default-props-match-prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -403,7 +403,7 @@ ruleTester.run('default-props-match-prop-types', rule, {
           return <div>{foo}{bar}</div>;
         }
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     {
       code: `
@@ -418,7 +418,7 @@ ruleTester.run('default-props-match-prop-types', rule, {
           return <div>{foo}{bar}</div>;
         }
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     // using spread operator
     {
diff --git a/tests/lib/rules/destructuring-assignment.js b/tests/lib/rules/destructuring-assignment.js
index 13d0c10ac7..3adcbd4819 100644
--- a/tests/lib/rules/destructuring-assignment.js
+++ b/tests/lib/rules/destructuring-assignment.js
@@ -12,7 +12,7 @@ const rule = require('../../../lib/rules/destructuring-assignment');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -935,6 +935,6 @@ ${'            '}
           data: { type: 'props' },
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/display-name.js b/tests/lib/rules/display-name.js
index 18fd1ca83c..f6e38fbb71 100644
--- a/tests/lib/rules/display-name.js
+++ b/tests/lib/rules/display-name.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/display-name');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/forbid-component-props.js b/tests/lib/rules/forbid-component-props.js
index 566860d139..7714f7431f 100644
--- a/tests/lib/rules/forbid-component-props.js
+++ b/tests/lib/rules/forbid-component-props.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/forbid-component-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/forbid-dom-props.js b/tests/lib/rules/forbid-dom-props.js
index a11d39fe00..380d9c5a19 100644
--- a/tests/lib/rules/forbid-dom-props.js
+++ b/tests/lib/rules/forbid-dom-props.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/forbid-dom-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/forbid-elements.js b/tests/lib/rules/forbid-elements.js
index d0c179b131..ffb1019080 100644
--- a/tests/lib/rules/forbid-elements.js
+++ b/tests/lib/rules/forbid-elements.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/forbid-elements');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/forbid-foreign-prop-types.js b/tests/lib/rules/forbid-foreign-prop-types.js
index 000d7eb4a9..751503ca91 100644
--- a/tests/lib/rules/forbid-foreign-prop-types.js
+++ b/tests/lib/rules/forbid-foreign-prop-types.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/forbid-foreign-prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/forbid-prop-types.js b/tests/lib/rules/forbid-prop-types.js
index 67ac1b47f6..dd2d903665 100644
--- a/tests/lib/rules/forbid-prop-types.js
+++ b/tests/lib/rules/forbid-prop-types.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/forbid-prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -712,7 +712,7 @@ ruleTester.run('forbid-prop-types', rule, {
           b: PropTypes.array(),
         }
       `,
-    }
+    },
   )),
 
   invalid: parsers.all([
diff --git a/tests/lib/rules/forward-ref-uses-ref.js b/tests/lib/rules/forward-ref-uses-ref.js
index 906baaca1e..2b0519aa47 100644
--- a/tests/lib/rules/forward-ref-uses-ref.js
+++ b/tests/lib/rules/forward-ref-uses-ref.js
@@ -19,7 +19,7 @@ const parsers = require('../../helpers/parsers');
 
 const ruleTester = new RuleTester({
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
   },
 });
diff --git a/tests/lib/rules/function-component-definition.js b/tests/lib/rules/function-component-definition.js
index dda2a10ec8..158ce6e164 100644
--- a/tests/lib/rules/function-component-definition.js
+++ b/tests/lib/rules/function-component-definition.js
@@ -13,7 +13,7 @@ const RuleTester = require('../../helpers/ruleTester');
 const rule = require('../../../lib/rules/function-component-definition');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/hook-use-state.js b/tests/lib/rules/hook-use-state.js
index 031ad6ce55..7f80138ab8 100644
--- a/tests/lib/rules/hook-use-state.js
+++ b/tests/lib/rules/hook-use-state.js
@@ -19,7 +19,7 @@ const parsers = require('../../helpers/parsers');
 
 const ruleTester = new RuleTester({
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
   },
 });
diff --git a/tests/lib/rules/iframe-missing-sandbox.js b/tests/lib/rules/iframe-missing-sandbox.js
index 628eea3adf..e7adf2729a 100644
--- a/tests/lib/rules/iframe-missing-sandbox.js
+++ b/tests/lib/rules/iframe-missing-sandbox.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/iframe-missing-sandbox');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-boolean-value.js b/tests/lib/rules/jsx-boolean-value.js
index 95be0709f4..c7f87b21a4 100644
--- a/tests/lib/rules/jsx-boolean-value.js
+++ b/tests/lib/rules/jsx-boolean-value.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-boolean-value');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-child-element-spacing.js b/tests/lib/rules/jsx-child-element-spacing.js
index 4788b7db49..f9ecc60cc0 100644
--- a/tests/lib/rules/jsx-child-element-spacing.js
+++ b/tests/lib/rules/jsx-child-element-spacing.js
@@ -7,7 +7,7 @@ const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
   sourceType: 'module',
-  ecmaVersion: 2015,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
diff --git a/tests/lib/rules/jsx-closing-bracket-location.js b/tests/lib/rules/jsx-closing-bracket-location.js
index 0e20084785..40b9c0a686 100644
--- a/tests/lib/rules/jsx-closing-bracket-location.js
+++ b/tests/lib/rules/jsx-closing-bracket-location.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-closing-bracket-location');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-closing-tag-location.js b/tests/lib/rules/jsx-closing-tag-location.js
index 23b71cdca5..8deee5b4ac 100644
--- a/tests/lib/rules/jsx-closing-tag-location.js
+++ b/tests/lib/rules/jsx-closing-tag-location.js
@@ -16,7 +16,7 @@ const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
   sourceType: 'module',
-  ecmaVersion: 2015,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
diff --git a/tests/lib/rules/jsx-curly-brace-presence.js b/tests/lib/rules/jsx-curly-brace-presence.js
index 59d756737b..94863fda12 100755
--- a/tests/lib/rules/jsx-curly-brace-presence.js
+++ b/tests/lib/rules/jsx-curly-brace-presence.js
@@ -20,7 +20,7 @@ const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
   sourceType: 'module',
-  ecmaVersion: 2015,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -477,7 +477,7 @@ ruleTester.run('jsx-curly-brace-presence', rule, {
     {
       code: '<App>{`${label}`}</App>',
       options: ['never'],
-    }
+    },
   )),
 
   invalid: parsers.all([].concat(
@@ -954,6 +954,6 @@ ruleTester.run('jsx-curly-brace-presence', rule, {
         <Foo help='The maximum time range for searches. (i.e. "P30D" for 30 days, "PT24H" for 24 hours)' />
       `,
       errors: [{ messageId: 'unnecessaryCurly' }],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/jsx-curly-newline.js b/tests/lib/rules/jsx-curly-newline.js
index 8b0a82b26a..baf79bf5a5 100644
--- a/tests/lib/rules/jsx-curly-newline.js
+++ b/tests/lib/rules/jsx-curly-newline.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/jsx-curly-newline');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-curly-spacing.js b/tests/lib/rules/jsx-curly-spacing.js
index f7a778bbe0..5dbda54318 100644
--- a/tests/lib/rules/jsx-curly-spacing.js
+++ b/tests/lib/rules/jsx-curly-spacing.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/jsx-curly-spacing');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-equals-spacing.js b/tests/lib/rules/jsx-equals-spacing.js
index 843372d3cd..cdcf9fc1a8 100644
--- a/tests/lib/rules/jsx-equals-spacing.js
+++ b/tests/lib/rules/jsx-equals-spacing.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-equals-spacing');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -156,6 +156,6 @@ ruleTester.run('jsx-equals-spacing', rule, {
         { messageId: 'needSpaceAfter', type: 'JSXAttribute' },
         { messageId: 'needSpaceAfter', type: 'JSXAttribute' },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/jsx-filename-extension.js b/tests/lib/rules/jsx-filename-extension.js
index adf3c78e79..deb503dfb2 100644
--- a/tests/lib/rules/jsx-filename-extension.js
+++ b/tests/lib/rules/jsx-filename-extension.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-filename-extension');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-first-prop-new-line.js b/tests/lib/rules/jsx-first-prop-new-line.js
index b53c9ee05b..14f8b30753 100644
--- a/tests/lib/rules/jsx-first-prop-new-line.js
+++ b/tests/lib/rules/jsx-first-prop-new-line.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-first-prop-new-line');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-fragments.js b/tests/lib/rules/jsx-fragments.js
index 6ed7302a47..03fe1bb54e 100644
--- a/tests/lib/rules/jsx-fragments.js
+++ b/tests/lib/rules/jsx-fragments.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-fragments');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-handler-names.js b/tests/lib/rules/jsx-handler-names.js
index 3ad3378abf..7c72e9e510 100644
--- a/tests/lib/rules/jsx-handler-names.js
+++ b/tests/lib/rules/jsx-handler-names.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-handler-names');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-indent-props.js b/tests/lib/rules/jsx-indent-props.js
index 2e4a618b81..3516a6cc68 100644
--- a/tests/lib/rules/jsx-indent-props.js
+++ b/tests/lib/rules/jsx-indent-props.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-indent-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-indent.js b/tests/lib/rules/jsx-indent.js
index 95e98ac2da..3803747ad2 100644
--- a/tests/lib/rules/jsx-indent.js
+++ b/tests/lib/rules/jsx-indent.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/jsx-indent');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -3163,6 +3163,6 @@ const Component = () => (
         { messageId: 'wrongIndent', line: 6 },
         { messageId: 'wrongIndent', line: 9 },
       ],
-    } : []
+    } : [],
   )),
 });
diff --git a/tests/lib/rules/jsx-key.js b/tests/lib/rules/jsx-key.js
index 2c5ba7a5c1..3e848a3bcd 100644
--- a/tests/lib/rules/jsx-key.js
+++ b/tests/lib/rules/jsx-key.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-key');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-max-depth.js b/tests/lib/rules/jsx-max-depth.js
index 9b83b02cde..a41b6a28cd 100644
--- a/tests/lib/rules/jsx-max-depth.js
+++ b/tests/lib/rules/jsx-max-depth.js
@@ -16,7 +16,7 @@ const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
   sourceType: 'module',
-  ecmaVersion: 2015,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
diff --git a/tests/lib/rules/jsx-max-props-per-line.js b/tests/lib/rules/jsx-max-props-per-line.js
index 88ac920493..4ada74d551 100644
--- a/tests/lib/rules/jsx-max-props-per-line.js
+++ b/tests/lib/rules/jsx-max-props-per-line.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-max-props-per-line');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-newline.js b/tests/lib/rules/jsx-newline.js
index 1090dff063..b3e89d08fd 100644
--- a/tests/lib/rules/jsx-newline.js
+++ b/tests/lib/rules/jsx-newline.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-newline');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -665,16 +665,16 @@ new RuleTester({ parserOptions }).run('jsx-newline', rule, {
               type="control"
               onClick={ () => this.onClickNavigate('left') }
             />
-    
+
             <sni-sequence-editor-tool
               name="rotate"
               direction="right"
               type="control"
               onClick={ (): void => this.onClickNavigate('right') }
             />
-    
+
             <div className="sni-sequence-editor-control-panel__delete" data-name="delete" onClick={ this.onDeleteCommand } />
-    
+
             {
               ...Array.from(this.children)
             }
@@ -704,9 +704,9 @@ ${'    '}
               type="control"
               onClick={ (): void => this.onClickNavigate('right') }
             />
-    
+
             <div className="sni-sequence-editor-control-panel__delete" data-name="delete" onClick={ this.onDeleteCommand } />
-    
+
             {
               ...Array.from(this.children)
             }
diff --git a/tests/lib/rules/jsx-no-bind.js b/tests/lib/rules/jsx-no-bind.js
index 71e3e63717..e5b922959c 100644
--- a/tests/lib/rules/jsx-no-bind.js
+++ b/tests/lib/rules/jsx-no-bind.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/jsx-no-bind');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-comment-textnodes.js b/tests/lib/rules/jsx-no-comment-textnodes.js
index e3742eab60..65f3de3a64 100644
--- a/tests/lib/rules/jsx-no-comment-textnodes.js
+++ b/tests/lib/rules/jsx-no-comment-textnodes.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-no-comment-textnodes');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-constructed-context-values.js b/tests/lib/rules/jsx-no-constructed-context-values.js
index 0fe74dab5e..d037a900a7 100644
--- a/tests/lib/rules/jsx-no-constructed-context-values.js
+++ b/tests/lib/rules/jsx-no-constructed-context-values.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/jsx-no-constructed-context-values');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-duplicate-props.js b/tests/lib/rules/jsx-no-duplicate-props.js
index f85287a854..11f8a4e4b5 100644
--- a/tests/lib/rules/jsx-no-duplicate-props.js
+++ b/tests/lib/rules/jsx-no-duplicate-props.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-no-duplicate-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-leaked-render.js b/tests/lib/rules/jsx-no-leaked-render.js
index 071ecd68ab..40f07f3a9f 100644
--- a/tests/lib/rules/jsx-no-leaked-render.js
+++ b/tests/lib/rules/jsx-no-leaked-render.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/jsx-no-leaked-render');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -1002,6 +1002,6 @@ ruleTester.run('jsx-no-leaked-render', rule, {
         line: 4,
         column: 33,
       }],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/jsx-no-literals.js b/tests/lib/rules/jsx-no-literals.js
index d1f6135f82..77387fc3e2 100644
--- a/tests/lib/rules/jsx-no-literals.js
+++ b/tests/lib/rules/jsx-no-literals.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/jsx-no-literals');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-script-url.js b/tests/lib/rules/jsx-no-script-url.js
index b97c9ce567..f988be1ee6 100644
--- a/tests/lib/rules/jsx-no-script-url.js
+++ b/tests/lib/rules/jsx-no-script-url.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-no-script-url');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-target-blank.js b/tests/lib/rules/jsx-no-target-blank.js
index 01dcb360ff..969e0954bf 100644
--- a/tests/lib/rules/jsx-no-target-blank.js
+++ b/tests/lib/rules/jsx-no-target-blank.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-no-target-blank');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-no-undef.js b/tests/lib/rules/jsx-no-undef.js
index 84ffeb0c35..188d061c2f 100644
--- a/tests/lib/rules/jsx-no-undef.js
+++ b/tests/lib/rules/jsx-no-undef.js
@@ -19,7 +19,7 @@ const rule = require('../../../lib/rules/jsx-no-undef');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -86,7 +86,7 @@ ruleTester.run('jsx-no-undef', rule, {
           );
         };
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
       options: [{ allowGlobals: false }],
     },
   ].map(parsers.disableNewTS)),
@@ -137,7 +137,7 @@ ruleTester.run('jsx-no-undef', rule, {
         };
         export default TextWrapper;
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
       errors: [
         {
           messageId: 'undefined',
diff --git a/tests/lib/rules/jsx-no-useless-fragment.js b/tests/lib/rules/jsx-no-useless-fragment.js
index eb5b227bcd..5edcf87f96 100644
--- a/tests/lib/rules/jsx-no-useless-fragment.js
+++ b/tests/lib/rules/jsx-no-useless-fragment.js
@@ -13,7 +13,7 @@ const rule = require('../../../lib/rules/jsx-no-useless-fragment');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -274,6 +274,6 @@ ruleTester.run('jsx-no-useless-fragment', rule, {
       errors: [{ messageId: 'NeedsMoreChildren', type: 'JSXFragment' }],
       output: '<Foo>{moo}</Foo>',
       features: ['fragment', 'no-ts-old'], // TODO: FIXME: remove no-ts-old
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/jsx-one-expression-per-line.js b/tests/lib/rules/jsx-one-expression-per-line.js
index 72615c2679..f858923383 100644
--- a/tests/lib/rules/jsx-one-expression-per-line.js
+++ b/tests/lib/rules/jsx-one-expression-per-line.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-one-expression-per-line');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-pascal-case.js b/tests/lib/rules/jsx-pascal-case.js
index bc90773ef7..9e9a055af5 100644
--- a/tests/lib/rules/jsx-pascal-case.js
+++ b/tests/lib/rules/jsx-pascal-case.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-pascal-case');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-props-no-multi-spaces.js b/tests/lib/rules/jsx-props-no-multi-spaces.js
index d85573702f..e71642f595 100644
--- a/tests/lib/rules/jsx-props-no-multi-spaces.js
+++ b/tests/lib/rules/jsx-props-no-multi-spaces.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/jsx-props-no-multi-spaces');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -149,7 +149,7 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
           />
         `,
       },
-    ] : [])
+    ] : []),
   )),
 
   invalid: parsers.all([].concat(
@@ -365,6 +365,6 @@ ruleTester.run('jsx-props-no-multi-spaces', rule, {
           },
         ],
       },
-    ] : [])
+    ] : []),
   )),
 });
diff --git a/tests/lib/rules/jsx-props-no-spread-multi.js b/tests/lib/rules/jsx-props-no-spread-multi.js
index 2e5df66668..77b8b8a7fd 100644
--- a/tests/lib/rules/jsx-props-no-spread-multi.js
+++ b/tests/lib/rules/jsx-props-no-spread-multi.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/jsx-props-no-spread-multi');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-props-no-spreading.js b/tests/lib/rules/jsx-props-no-spreading.js
index dc9c0203ed..54708542e8 100644
--- a/tests/lib/rules/jsx-props-no-spreading.js
+++ b/tests/lib/rules/jsx-props-no-spreading.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/jsx-props-no-spreading');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-sort-default-props.js b/tests/lib/rules/jsx-sort-default-props.js
index 15d651db3a..668bdba9b8 100644
--- a/tests/lib/rules/jsx-sort-default-props.js
+++ b/tests/lib/rules/jsx-sort-default-props.js
@@ -18,7 +18,7 @@ const rule = require('../../../lib/rules/jsx-sort-default-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -374,7 +374,7 @@ ruleTester.run('jsx-sort-default-props', rule, {
             z: PropTypes.string,
         };
       `,
-    }
+    },
   )),
 
   invalid: parsers.all([
diff --git a/tests/lib/rules/jsx-sort-props.js b/tests/lib/rules/jsx-sort-props.js
index 797dc26650..676df97f18 100644
--- a/tests/lib/rules/jsx-sort-props.js
+++ b/tests/lib/rules/jsx-sort-props.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/jsx-sort-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -296,7 +296,7 @@ ruleTester.run('jsx-sort-props', rule, {
         />
       `,
       options: [{ locale: 'sk-SK' }],
-    } : []
+    } : [],
   )),
   invalid: parsers.all([].concat(
     {
@@ -1101,6 +1101,6 @@ ruleTester.run('jsx-sort-props', rule, {
           line: 11,
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/jsx-space-before-closing.js b/tests/lib/rules/jsx-space-before-closing.js
index 01f80be41a..9201f26b73 100644
--- a/tests/lib/rules/jsx-space-before-closing.js
+++ b/tests/lib/rules/jsx-space-before-closing.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-space-before-closing');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-tag-spacing.js b/tests/lib/rules/jsx-tag-spacing.js
index cc98cb2b05..dd20969b8e 100644
--- a/tests/lib/rules/jsx-tag-spacing.js
+++ b/tests/lib/rules/jsx-tag-spacing.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-tag-spacing');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-uses-react.js b/tests/lib/rules/jsx-uses-react.js
index 381b44bc89..821c30f9d2 100644
--- a/tests/lib/rules/jsx-uses-react.js
+++ b/tests/lib/rules/jsx-uses-react.js
@@ -17,7 +17,7 @@ const getRuleDefiner = require('../../helpers/getRuleDefiner');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-uses-vars.js b/tests/lib/rules/jsx-uses-vars.js
index 8b9db2a956..34155a5178 100644
--- a/tests/lib/rules/jsx-uses-vars.js
+++ b/tests/lib/rules/jsx-uses-vars.js
@@ -19,7 +19,7 @@ const getRuleDefiner = require('../../helpers/getRuleDefiner');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/jsx-wrap-multilines.js b/tests/lib/rules/jsx-wrap-multilines.js
index 8db8fe79d9..051c37ab20 100644
--- a/tests/lib/rules/jsx-wrap-multilines.js
+++ b/tests/lib/rules/jsx-wrap-multilines.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/jsx-wrap-multilines');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-access-state-in-setstate.js b/tests/lib/rules/no-access-state-in-setstate.js
index bdf104d0cc..68ce790f6c 100644
--- a/tests/lib/rules/no-access-state-in-setstate.js
+++ b/tests/lib/rules/no-access-state-in-setstate.js
@@ -14,7 +14,7 @@ const parsers = require('../../helpers/parsers');
 const rule = require('../../../lib/rules/no-access-state-in-setstate');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
diff --git a/tests/lib/rules/no-adjacent-inline-elements.js b/tests/lib/rules/no-adjacent-inline-elements.js
index a757fb869d..eeede351de 100644
--- a/tests/lib/rules/no-adjacent-inline-elements.js
+++ b/tests/lib/rules/no-adjacent-inline-elements.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/no-adjacent-inline-elements');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 6,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     experimentalObjectRestSpread: true,
     jsx: true,
diff --git a/tests/lib/rules/no-array-index-key.js b/tests/lib/rules/no-array-index-key.js
index 2269e208ca..ab7999f8e5 100644
--- a/tests/lib/rules/no-array-index-key.js
+++ b/tests/lib/rules/no-array-index-key.js
@@ -14,7 +14,7 @@ const parsers = require('../../helpers/parsers');
 const rule = require('../../../lib/rules/no-array-index-key');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -374,6 +374,6 @@ ruleTester.run('no-array-index-key', rule, {
         ))
       `,
       errors: [{ messageId: 'noArrayIndex' }],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-arrow-function-lifecycle.js b/tests/lib/rules/no-arrow-function-lifecycle.js
index de2c67cbc3..4a314964a8 100644
--- a/tests/lib/rules/no-arrow-function-lifecycle.js
+++ b/tests/lib/rules/no-arrow-function-lifecycle.js
@@ -13,7 +13,7 @@ const rule = require('../../../lib/rules/no-arrow-function-lifecycle');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-children-prop.js b/tests/lib/rules/no-children-prop.js
index fdd7f501f8..c65e576762 100644
--- a/tests/lib/rules/no-children-prop.js
+++ b/tests/lib/rules/no-children-prop.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-children-prop');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-danger-with-children.js b/tests/lib/rules/no-danger-with-children.js
index 53013f5a58..c881058c99 100644
--- a/tests/lib/rules/no-danger-with-children.js
+++ b/tests/lib/rules/no-danger-with-children.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-danger-with-children');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-danger.js b/tests/lib/rules/no-danger.js
index 9403a220bf..2e66080d8e 100644
--- a/tests/lib/rules/no-danger.js
+++ b/tests/lib/rules/no-danger.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-danger');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-deprecated.js b/tests/lib/rules/no-deprecated.js
index a523eb1b6c..8d5a935d02 100644
--- a/tests/lib/rules/no-deprecated.js
+++ b/tests/lib/rules/no-deprecated.js
@@ -17,7 +17,7 @@ const rule = require('../../../lib/rules/no-deprecated');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -25,17 +25,16 @@ const parserOptions = {
 };
 
 function errorMessage(oldMethod, version, newMethod, refs, extraProps) {
-  return (
-    Object.assign({
-      messageId: 'deprecated',
-      data: {
-        oldMethod,
-        version,
-        newMethod: newMethod ? `, use ${newMethod} instead` : '',
-        refs: refs ? `, see ${refs}` : '',
-      },
-    }, extraProps)
-  );
+  return {
+    messageId: 'deprecated',
+    data: {
+      oldMethod,
+      version,
+      newMethod: newMethod ? `, use ${newMethod} instead` : '',
+      refs: refs ? `, see ${refs}` : '',
+    },
+    ...extraProps,
+  };
 }
 
 // ------------------------------------------------------------------------------
@@ -236,14 +235,14 @@ ruleTester.run('no-deprecated', rule, {
           '15.5.0',
           'the npm module create-react-class',
           null,
-          { type: 'Property', column: 6 }
+          { type: 'Property', column: 6 },
         ),
         errorMessage(
           'React.PropTypes',
           '15.5.0',
           'the npm module prop-types',
           null,
-          { type: 'Property', column: 19 }
+          { type: 'Property', column: 19 },
         ),
       ],
     },
@@ -269,14 +268,14 @@ ruleTester.run('no-deprecated', rule, {
           '15.5.0',
           'the npm module create-react-class',
           null,
-          { type: 'Property', line: 3, column: 14 }
+          { type: 'Property', line: 3, column: 14 },
         ),
         errorMessage(
           'React.PropTypes',
           '15.5.0',
           'the npm module prop-types',
           null,
-          { type: 'Property', line: 3, column: 27 }
+          { type: 'Property', line: 3, column: 27 },
         ),
       ],
     },
@@ -309,21 +308,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 3, column: 11 }
+          { type: 'Identifier', line: 3, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
       ],
     },
@@ -343,21 +342,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 13 }
+          { type: 'Identifier', line: 4, column: 13 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 13 }
+          { type: 'Identifier', line: 5, column: 13 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 6, column: 13 }
+          { type: 'Identifier', line: 6, column: 13 },
         ),
       ],
     },
@@ -375,21 +374,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 3, column: 11 }
+          { type: 'Identifier', line: 3, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
       ],
     },
@@ -407,21 +406,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 3, column: 11 }
+          { type: 'Identifier', line: 3, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
       ],
     },
@@ -439,21 +438,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 3, column: 11 }
+          { type: 'Identifier', line: 3, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
       ],
     },
@@ -471,21 +470,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 3, column: 11 }
+          { type: 'Identifier', line: 3, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
       ],
     },
@@ -504,21 +503,21 @@ ruleTester.run('no-deprecated', rule, {
           '16.9.0',
           'UNSAFE_componentWillMount',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillmount. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 4, column: 11 }
+          { type: 'Identifier', line: 4, column: 11 },
         ),
         errorMessage(
           'componentWillReceiveProps',
           '16.9.0',
           'UNSAFE_componentWillReceiveProps',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillreceiveprops. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 5, column: 11 }
+          { type: 'Identifier', line: 5, column: 11 },
         ),
         errorMessage(
           'componentWillUpdate',
           '16.9.0',
           'UNSAFE_componentWillUpdate',
           'https://reactjs.org/docs/react-component.html#unsafe_componentwillupdate. Use https://github.com/reactjs/react-codemod#rename-unsafe-lifecycles to automatically update your components.',
-          { type: 'Identifier', line: 6, column: 11 }
+          { type: 'Identifier', line: 6, column: 11 },
         ),
       ],
     },
@@ -533,14 +532,14 @@ ruleTester.run('no-deprecated', rule, {
           '18.0.0',
           'createRoot',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'ImportSpecifier', line: 2, column: 18 }
+          { type: 'ImportSpecifier', line: 2, column: 18 },
         ),
         errorMessage(
           'ReactDOM.render',
           '18.0.0',
           'createRoot',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'MemberExpression', line: 3, column: 9 }
+          { type: 'MemberExpression', line: 3, column: 9 },
         ),
       ],
     },
@@ -555,14 +554,14 @@ ruleTester.run('no-deprecated', rule, {
           '18.0.0',
           'hydrateRoot',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'ImportSpecifier', line: 2, column: 18 }
+          { type: 'ImportSpecifier', line: 2, column: 18 },
         ),
         errorMessage(
           'ReactDOM.hydrate',
           '18.0.0',
           'hydrateRoot',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'MemberExpression', line: 3, column: 9 }
+          { type: 'MemberExpression', line: 3, column: 9 },
         ),
       ],
     },
@@ -577,14 +576,14 @@ ruleTester.run('no-deprecated', rule, {
           '18.0.0',
           'root.unmount',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'ImportSpecifier', line: 2, column: 18 }
+          { type: 'ImportSpecifier', line: 2, column: 18 },
         ),
         errorMessage(
           'ReactDOM.unmountComponentAtNode',
           '18.0.0',
           'root.unmount',
           'https://reactjs.org/link/switch-to-createroot',
-          { type: 'MemberExpression', line: 3, column: 9 }
+          { type: 'MemberExpression', line: 3, column: 9 },
         ),
       ],
     },
@@ -599,14 +598,14 @@ ruleTester.run('no-deprecated', rule, {
           '18.0.0',
           'renderToPipeableStream',
           'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
-          { type: 'ImportSpecifier', line: 2, column: 18 }
+          { type: 'ImportSpecifier', line: 2, column: 18 },
         ),
         errorMessage(
           'ReactDOMServer.renderToNodeStream',
           '18.0.0',
           'renderToPipeableStream',
           'https://reactjs.org/docs/react-dom-server.html#rendertonodestream',
-          { type: 'MemberExpression', line: 3, column: 9 }
+          { type: 'MemberExpression', line: 3, column: 9 },
         ),
       ],
     },
diff --git a/tests/lib/rules/no-did-mount-set-state.js b/tests/lib/rules/no-did-mount-set-state.js
index 83a1e9b7b4..785e5295df 100644
--- a/tests/lib/rules/no-did-mount-set-state.js
+++ b/tests/lib/rules/no-did-mount-set-state.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-did-mount-set-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -284,16 +284,18 @@ ruleTester.run('no-did-mount-set-state', rule, {
       `,
     },
     invalid.map((test) => {
-      const newTest = Object.assign({}, test, {
-        settings: Object.assign({}, test.settings, {
+      const newTest = {
+        ...test,
+        settings: {
+          ...test.settings,
           react: {
             version: '16.3.0',
           },
-        }),
-      });
+        },
+      };
       delete newTest.errors;
       return newTest;
-    })
+    }),
   )),
 
   invalid: parsers.all(invalid),
diff --git a/tests/lib/rules/no-did-update-set-state.js b/tests/lib/rules/no-did-update-set-state.js
index f0895531c5..d30a335b19 100644
--- a/tests/lib/rules/no-did-update-set-state.js
+++ b/tests/lib/rules/no-did-update-set-state.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-did-update-set-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -285,16 +285,18 @@ ruleTester.run('no-did-update-set-state', rule, {
       `,
     },
     invalid.map((test) => {
-      const newTest = Object.assign({}, test, {
-        settings: Object.assign({}, test.settings, {
+      const newTest = {
+        ...test,
+        settings: {
+          ...test.settings,
           react: {
             version: '16.3.0',
           },
-        }),
-      });
+        },
+      };
       delete newTest.errors;
       return newTest;
-    })
+    }),
   )),
 
   invalid: parsers.all(invalid),
diff --git a/tests/lib/rules/no-direct-mutation-state.js b/tests/lib/rules/no-direct-mutation-state.js
index ae692a20d0..294e024bd0 100644
--- a/tests/lib/rules/no-direct-mutation-state.js
+++ b/tests/lib/rules/no-direct-mutation-state.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-direct-mutation-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-find-dom-node.js b/tests/lib/rules/no-find-dom-node.js
index 152d7d9c58..2ab9d80e5d 100644
--- a/tests/lib/rules/no-find-dom-node.js
+++ b/tests/lib/rules/no-find-dom-node.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-find-dom-node');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-invalid-html-attribute.js b/tests/lib/rules/no-invalid-html-attribute.js
index d7530cecdd..babc6923a6 100644
--- a/tests/lib/rules/no-invalid-html-attribute.js
+++ b/tests/lib/rules/no-invalid-html-attribute.js
@@ -16,7 +16,7 @@ const rule = require('../../../lib/rules/no-invalid-html-attribute');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -1950,6 +1950,6 @@ ruleTester.run('no-invalid-html-attribute', rule, {
           type: 'Literal',
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-is-mounted.js b/tests/lib/rules/no-is-mounted.js
index c8b22daabb..45f10bf216 100644
--- a/tests/lib/rules/no-is-mounted.js
+++ b/tests/lib/rules/no-is-mounted.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-is-mounted');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-multi-comp.js b/tests/lib/rules/no-multi-comp.js
index db6f09db2c..b0fca68696 100644
--- a/tests/lib/rules/no-multi-comp.js
+++ b/tests/lib/rules/no-multi-comp.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-multi-comp');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -101,7 +101,7 @@ ruleTester.run('no-multi-comp', rule, {
           return createElement("img");
         };
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     {
       code: `
diff --git a/tests/lib/rules/no-namespace.js b/tests/lib/rules/no-namespace.js
index 2d423e8ad6..4c8cf2f2cf 100644
--- a/tests/lib/rules/no-namespace.js
+++ b/tests/lib/rules/no-namespace.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-namespace');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-object-type-as-default-prop.js b/tests/lib/rules/no-object-type-as-default-prop.js
index a2dc01fb85..640e11424a 100644
--- a/tests/lib/rules/no-object-type-as-default-prop.js
+++ b/tests/lib/rules/no-object-type-as-default-prop.js
@@ -14,7 +14,7 @@ const parsers = require('../../helpers/parsers');
 const rule = require('../../../lib/rules/no-object-type-as-default-prop');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -150,7 +150,7 @@ ruleTester.run('no-object-type-as-default-prop', rule, {
     `,
     `
       export default function NotAComponent({foo = {}}) {}
-    `
+    `,
   )),
   invalid: parsers.all([].concat(
     {
@@ -206,6 +206,6 @@ ruleTester.run('no-object-type-as-default-prop', rule, {
         }
       `,
       errors: expectedViolations,
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-redundant-should-component-update.js b/tests/lib/rules/no-redundant-should-component-update.js
index 7aafb1e589..5a052b1892 100644
--- a/tests/lib/rules/no-redundant-should-component-update.js
+++ b/tests/lib/rules/no-redundant-should-component-update.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/no-redundant-should-component-update');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
diff --git a/tests/lib/rules/no-render-return-value.js b/tests/lib/rules/no-render-return-value.js
index bbd7b7f930..5380eb87c7 100644
--- a/tests/lib/rules/no-render-return-value.js
+++ b/tests/lib/rules/no-render-return-value.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-render-return-value');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-set-state.js b/tests/lib/rules/no-set-state.js
index 5f67e705c5..f4044faeb4 100644
--- a/tests/lib/rules/no-set-state.js
+++ b/tests/lib/rules/no-set-state.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-set-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-string-refs.js b/tests/lib/rules/no-string-refs.js
index e52680b446..c7794e1f44 100644
--- a/tests/lib/rules/no-string-refs.js
+++ b/tests/lib/rules/no-string-refs.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-string-refs');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-this-in-sfc.js b/tests/lib/rules/no-this-in-sfc.js
index ce0abb77ba..7619a1e637 100644
--- a/tests/lib/rules/no-this-in-sfc.js
+++ b/tests/lib/rules/no-this-in-sfc.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/no-this-in-sfc');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-typos.js b/tests/lib/rules/no-typos.js
index 0aaddfd290..bfa188ac38 100644
--- a/tests/lib/rules/no-typos.js
+++ b/tests/lib/rules/no-typos.js
@@ -18,7 +18,7 @@ const rule = require('../../../lib/rules/no-typos');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -576,13 +576,14 @@ ruleTester.run('no-typos', rule, {
         }
       `,
       features: [].concat('class fields', semver.satisfies(babelEslintVersion, '< 9') ? 'no-babel-old' : []),
-      parserOptions: Object.assign({}, parserOptions, {
+      parserOptions: {
+        ...parserOptions,
         babelOptions: {
-          // classPrivateMethods: true,
+        // classPrivateMethods: true,
         },
         shippedProposals: true,
-      }),
-    }
+      },
+    },
   )),
 
   invalid: parsers.all([].concat(
@@ -1918,6 +1919,6 @@ ruleTester.run('no-typos', rule, {
       `,
       parserOptions,
       errors: [{ messageId: 'noPropTypesBinding' }],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-unescaped-entities.js b/tests/lib/rules/no-unescaped-entities.js
index 4e62a82eb3..b07b0eecb5 100644
--- a/tests/lib/rules/no-unescaped-entities.js
+++ b/tests/lib/rules/no-unescaped-entities.js
@@ -26,7 +26,7 @@ const rule = require('../../../lib/rules/no-unescaped-entities');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -602,6 +602,6 @@ ruleTester.run('no-unescaped-entities', rule, {
           ],
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-unknown-property.js b/tests/lib/rules/no-unknown-property.js
index f24257a04d..b6913f4241 100644
--- a/tests/lib/rules/no-unknown-property.js
+++ b/tests/lib/rules/no-unknown-property.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-unknown-property');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-unsafe.js b/tests/lib/rules/no-unsafe.js
index 3dc180be22..7412e23912 100644
--- a/tests/lib/rules/no-unsafe.js
+++ b/tests/lib/rules/no-unsafe.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-unsafe');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-unstable-nested-components.js b/tests/lib/rules/no-unstable-nested-components.js
index 8a9c0aad47..3c2589d96e 100644
--- a/tests/lib/rules/no-unstable-nested-components.js
+++ b/tests/lib/rules/no-unstable-nested-components.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-unstable-nested-components');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-unused-class-component-methods.js b/tests/lib/rules/no-unused-class-component-methods.js
index deccb47a07..c4891b4e7d 100644
--- a/tests/lib/rules/no-unused-class-component-methods.js
+++ b/tests/lib/rules/no-unused-class-component-methods.js
@@ -14,7 +14,7 @@ const rule = require('../../../lib/rules/no-unused-class-component-methods');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/no-unused-prop-types.js b/tests/lib/rules/no-unused-prop-types.js
index 943db3048e..5f687827f4 100644
--- a/tests/lib/rules/no-unused-prop-types.js
+++ b/tests/lib/rules/no-unused-prop-types.js
@@ -21,7 +21,7 @@ const rule = require('../../../lib/rules/no-unused-prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -2509,7 +2509,7 @@ ruleTester.run('no-unused-prop-types', rule, {
           bar: PropTypes.func,
         }
       `,
-      parserOptions: Object.assign({}, parserOptions, { ecmaVersion: 2017 }),
+      parserOptions: { ...parserOptions, ecmaVersion: 2022 },
     },
     {
       // Multiple props used inside of an async function
@@ -2528,7 +2528,7 @@ ruleTester.run('no-unused-prop-types', rule, {
           bar: PropTypes.func,
         }
       `,
-      parserOptions: Object.assign({}, parserOptions, { ecmaVersion: 2017 }),
+      parserOptions: { ...parserOptions, ecmaVersion: 2022 },
     },
     {
       // Multiple props used inside of an async arrow function
@@ -2547,7 +2547,7 @@ ruleTester.run('no-unused-prop-types', rule, {
           bar: PropTypes.func,
         }
       `,
-      parserOptions: Object.assign({}, parserOptions, { ecmaVersion: 2017 }),
+      parserOptions: { ...parserOptions, ecmaVersion: 2022 },
     },
     {
       // Destructured assignment with Shape propTypes issue #816
@@ -5438,7 +5438,7 @@ ruleTester.run('no-unused-prop-types', rule, {
           baz: PropTypes.func,
         }
       `,
-      parserOptions: Object.assign({}, parserOptions, { ecmaVersion: 2017 }),
+      parserOptions: { ...parserOptions, ecmaVersion: 2022 },
       errors: [
         {
           messageId: 'unusedPropType',
@@ -5466,7 +5466,7 @@ ruleTester.run('no-unused-prop-types', rule, {
           baz: PropTypes.func,
         }
       `,
-      parserOptions: Object.assign({}, parserOptions, { ecmaVersion: 2017 }),
+      parserOptions: { ...parserOptions, ecmaVersion: 2022 },
       errors: [
         {
           messageId: 'unusedPropType',
@@ -6709,6 +6709,6 @@ ruleTester.run('no-unused-prop-types', rule, {
       errors: [
         { message: '\'bar\' PropType is defined but prop is never used' },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js
index e08197e589..798bf1f0c6 100644
--- a/tests/lib/rules/no-unused-state.js
+++ b/tests/lib/rules/no-unused-state.js
@@ -12,7 +12,7 @@ const rule = require('../../../lib/rules/no-unused-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -1110,7 +1110,7 @@ eslintTester.run('no-unused-state', rule, {
         }
       `,
       features: ['types', 'class fields'],
-    }
+    },
   )),
 
   invalid: parsers.all([
diff --git a/tests/lib/rules/no-will-update-set-state.js b/tests/lib/rules/no-will-update-set-state.js
index be3895c4e6..36e7c1ee3c 100644
--- a/tests/lib/rules/no-will-update-set-state.js
+++ b/tests/lib/rules/no-will-update-set-state.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/no-will-update-set-state');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/prefer-es6-class.js b/tests/lib/rules/prefer-es6-class.js
index 369b22ec58..937d495cd0 100644
--- a/tests/lib/rules/prefer-es6-class.js
+++ b/tests/lib/rules/prefer-es6-class.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/prefer-es6-class');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/prefer-exact-props.js b/tests/lib/rules/prefer-exact-props.js
index 697c35cfa2..d05ea69b73 100644
--- a/tests/lib/rules/prefer-exact-props.js
+++ b/tests/lib/rules/prefer-exact-props.js
@@ -13,7 +13,7 @@ const rule = require('../../../lib/rules/prefer-exact-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 8,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     experimentalObjectRestSpread: true,
diff --git a/tests/lib/rules/prefer-read-only-props.js b/tests/lib/rules/prefer-read-only-props.js
index bf7668042b..175475fce3 100644
--- a/tests/lib/rules/prefer-read-only-props.js
+++ b/tests/lib/rules/prefer-read-only-props.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/prefer-read-only-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/prefer-stateless-function.js b/tests/lib/rules/prefer-stateless-function.js
index 5ceee4ab22..3a25be74a3 100644
--- a/tests/lib/rules/prefer-stateless-function.js
+++ b/tests/lib/rules/prefer-stateless-function.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/prefer-stateless-function');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/prop-types.js b/tests/lib/rules/prop-types.js
index f851057a16..544a07ac3d 100644
--- a/tests/lib/rules/prop-types.js
+++ b/tests/lib/rules/prop-types.js
@@ -19,7 +19,7 @@ const rule = require('../../../lib/rules/prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -4993,7 +4993,7 @@ ruleTester.run('prop-types', rule, {
         );
       `,
       features: ['types'],
-    }
+    },
   )),
 
   invalid: parsers.all([].concat(
@@ -6108,9 +6108,7 @@ ruleTester.run('prop-types', rule, {
           firstname: PropTypes.string
         });
       `,
-      settings: Object.assign({}, settings, {
-        propWrapperFunctions: ['forbidExtraProps'],
-      }),
+      settings: { ...settings, propWrapperFunctions: ['forbidExtraProps'] },
       errors: [
         {
           messageId: 'missingPropType',
@@ -6131,9 +6129,7 @@ ruleTester.run('prop-types', rule, {
           firstname: PropTypes.string
         });
       `,
-      settings: Object.assign({}, settings, {
-        propWrapperFunctions: ['Object.freeze'],
-      }),
+      settings: { ...settings, propWrapperFunctions: ['Object.freeze'] },
       errors: [
         {
           messageId: 'missingPropType',
@@ -6808,9 +6804,7 @@ ruleTester.run('prop-types', rule, {
         }
       `,
       features: ['class fields'],
-      settings: Object.assign({}, settings, {
-        propWrapperFunctions: ['forbidExtraProps'],
-      }),
+      settings: { ...settings, propWrapperFunctions: ['forbidExtraProps'] },
       errors: [
         {
           messageId: 'missingPropType',
@@ -6931,9 +6925,7 @@ ruleTester.run('prop-types', rule, {
         }
       `,
       features: ['class fields'],
-      settings: Object.assign({}, settings, {
-        propWrapperFunctions: ['forbidExtraProps'],
-      }),
+      settings: { ...settings, propWrapperFunctions: ['forbidExtraProps'] },
       errors: [
         {
           messageId: 'missingPropType',
@@ -9102,6 +9094,6 @@ ruleTester.run('prop-types', rule, {
           data: { name: 'prop$.events.map' },
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/react-in-jsx-scope.js b/tests/lib/rules/react-in-jsx-scope.js
index 6828f07ce5..343a7cbbb8 100644
--- a/tests/lib/rules/react-in-jsx-scope.js
+++ b/tests/lib/rules/react-in-jsx-scope.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/react-in-jsx-scope');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/require-default-props.js b/tests/lib/rules/require-default-props.js
index 928cf4ba1d..0e19476818 100644
--- a/tests/lib/rules/require-default-props.js
+++ b/tests/lib/rules/require-default-props.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/require-default-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -811,7 +811,7 @@ ruleTester.run('require-default-props', rule, {
           return <div>{foo}{bar}</div>;
         }
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     {
       code: `
@@ -824,7 +824,7 @@ ruleTester.run('require-default-props', rule, {
           return <div>{foo}{bar}</div>;
         }
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     // using spread operator
     {
diff --git a/tests/lib/rules/require-optimization.js b/tests/lib/rules/require-optimization.js
index 0df43ac2d1..ee86367f65 100644
--- a/tests/lib/rules/require-optimization.js
+++ b/tests/lib/rules/require-optimization.js
@@ -11,7 +11,7 @@ const rule = require('../../../lib/rules/require-optimization');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/require-render-return.js b/tests/lib/rules/require-render-return.js
index 364a2e7c99..e6523ff4cc 100644
--- a/tests/lib/rules/require-render-return.js
+++ b/tests/lib/rules/require-render-return.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/require-render-return');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/self-closing-comp.js b/tests/lib/rules/self-closing-comp.js
index 4cd3b1c5ad..d38535eb5c 100644
--- a/tests/lib/rules/self-closing-comp.js
+++ b/tests/lib/rules/self-closing-comp.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/self-closing-comp');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/sort-comp.js b/tests/lib/rules/sort-comp.js
index da8810cc10..2c61370c9b 100644
--- a/tests/lib/rules/sort-comp.js
+++ b/tests/lib/rules/sort-comp.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/sort-comp');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/lib/rules/sort-default-props.js b/tests/lib/rules/sort-default-props.js
index 3878a29e0b..88630a9955 100644
--- a/tests/lib/rules/sort-default-props.js
+++ b/tests/lib/rules/sort-default-props.js
@@ -18,7 +18,7 @@ const rule = require('../../../lib/rules/sort-default-props');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -374,7 +374,7 @@ ruleTester.run('sort-default-props', rule, {
             z: PropTypes.string,
         };
       `,
-    }
+    },
   )),
 
   invalid: parsers.all([
diff --git a/tests/lib/rules/sort-prop-types.js b/tests/lib/rules/sort-prop-types.js
index a902f54c4c..3347134d45 100644
--- a/tests/lib/rules/sort-prop-types.js
+++ b/tests/lib/rules/sort-prop-types.js
@@ -18,7 +18,7 @@ const rule = require('../../../lib/rules/sort-prop-types');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -513,7 +513,7 @@ ruleTester.run('sort-prop-types', rule, {
       `,
       features: ['types'],
       options: [{ checkTypes: true }],
-    }
+    },
   )),
   invalid: parsers.all([].concat(
     {
@@ -2414,6 +2414,6 @@ ruleTester.run('sort-prop-types', rule, {
           column: 102,
         },
       ],
-    }
+    },
   )),
 });
diff --git a/tests/lib/rules/state-in-constructor.js b/tests/lib/rules/state-in-constructor.js
index e144d4e4cb..1ad33305ac 100644
--- a/tests/lib/rules/state-in-constructor.js
+++ b/tests/lib/rules/state-in-constructor.js
@@ -16,7 +16,7 @@ const parsers = require('../../helpers/parsers');
 
 const ruleTesterConfig = {
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
     ecmaFeatures: {
       jsx: true,
diff --git a/tests/lib/rules/static-property-placement.js b/tests/lib/rules/static-property-placement.js
index 97b49e936b..8d789bf988 100644
--- a/tests/lib/rules/static-property-placement.js
+++ b/tests/lib/rules/static-property-placement.js
@@ -23,7 +23,7 @@ const parsers = require('../../helpers/parsers');
 
 const ruleTesterConfig = {
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
     ecmaFeatures: {
       jsx: true,
diff --git a/tests/lib/rules/style-prop-object.js b/tests/lib/rules/style-prop-object.js
index 9381bad508..1d355bb3c8 100644
--- a/tests/lib/rules/style-prop-object.js
+++ b/tests/lib/rules/style-prop-object.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/style-prop-object');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
@@ -95,7 +95,7 @@ ruleTester.run('style-prop-object', rule, {
         const styles = Object.assign({ color: 'red' }, mystyles);
         React.createElement("div", { style: styles });
       `,
-      parserOptions: Object.assign({ sourceType: 'module' }, parserOptions),
+      parserOptions: { sourceType: 'module', ...parserOptions },
     },
     {
       code: '<div style></div>',
diff --git a/tests/lib/rules/void-dom-elements-no-children.js b/tests/lib/rules/void-dom-elements-no-children.js
index 64c4aadddb..5501ec9823 100644
--- a/tests/lib/rules/void-dom-elements-no-children.js
+++ b/tests/lib/rules/void-dom-elements-no-children.js
@@ -15,7 +15,7 @@ const rule = require('../../../lib/rules/void-dom-elements-no-children');
 const parsers = require('../../helpers/parsers');
 
 const parserOptions = {
-  ecmaVersion: 2018,
+  ecmaVersion: 2022,
   sourceType: 'module',
   ecmaFeatures: {
     jsx: true,
diff --git a/tests/util/Components.js b/tests/util/Components.js
index 414f9a05bd..4e9255678d 100644
--- a/tests/util/Components.js
+++ b/tests/util/Components.js
@@ -11,7 +11,7 @@ const parsers = require('../helpers/parsers');
 
 const ruleTester = new RuleTester({
   parserOptions: {
-    ecmaVersion: 2018,
+    ecmaVersion: 2022,
     sourceType: 'module',
     ecmaFeatures: {
       jsx: true,
@@ -36,28 +36,30 @@ describe('Components', () => {
               return [nodeType, (node) => {
                 instructionResults.push({ type: nodeType, result: handler(node, context, components, util) });
               }];
-            })
+            }),
           );
 
-          return Object.assign({}, augmentedInstructions, {
+          return {
+            ...augmentedInstructions,
             'Program:exit'(node) {
               if (augmentedInstructions['Program:exit']) {
                 augmentedInstructions['Program:exit'](node, context, components, util);
               }
               done(components, instructionResults);
             },
-          });
+          };
         }),
       };
 
       const tests = {
-        valid: parsers.all([Object.assign({}, test, {
+        valid: parsers.all([{
+          ...test,
           settings: {
             react: {
               version: 'detect',
             },
           },
-        })]),
+        }]),
         invalid: [],
       };
 
@@ -76,7 +78,7 @@ describe('Components', () => {
           assert.equal(
             component.node.id.name,
             'MyStatelessComponent',
-            'MyStatelessComponent should be detected component'
+            'MyStatelessComponent should be detected component',
           );
         });
       });
@@ -96,7 +98,7 @@ describe('Components', () => {
           assert.equal(
             component.node.id.name,
             'MyClassComponent',
-            'MyClassComponent should be detected component'
+            'MyClassComponent should be detected component',
           );
         });
       });
@@ -109,13 +111,13 @@ describe('Components', () => {
         assert.deepEqual(
           components.getDefaultReactImports().map((specifier) => specifier.local.name),
           ['React'],
-          'default React import identifier should be "React"'
+          'default React import identifier should be "React"',
         );
 
         assert.deepEqual(
           components.getNamedReactImports().map((specifier) => specifier.local.name),
           ['useCallback', 'useState'],
-          'named React import identifiers should be "useCallback" and "useState"'
+          'named React import identifiers should be "useCallback" and "useState"',
         );
       });
     });
diff --git a/tests/util/ast.js b/tests/util/ast.js
index 16ddd47f35..e794398087 100644
--- a/tests/util/ast.js
+++ b/tests/util/ast.js
@@ -10,7 +10,7 @@ const traverseReturns = ast.traverseReturns;
 const isFunctionLike = ast.isFunctionLike;
 
 const DEFAULT_CONFIG = {
-  ecmaVersion: 6,
+  ecmaVersion: 2022,
 };
 
 const parseCode = (code) => {
diff --git a/tests/util/jsx.js b/tests/util/jsx.js
index 7be16d5410..209932f7ca 100644
--- a/tests/util/jsx.js
+++ b/tests/util/jsx.js
@@ -8,7 +8,7 @@ const jsxUtil = require('../../lib/util/jsx');
 const isReturningJSX = jsxUtil.isReturningJSX;
 
 const DEFAULT_CONFIG = {
-  ecmaVersion: 6,
+  ecmaVersion: 2022,
   ecmaFeatures: {
     jsx: true,
   },
@@ -35,7 +35,7 @@ const mockContext = {
 describe('jsxUtil', () => {
   describe('isReturningJSX', () => {
     const assertValid = (codeStr) => assert(
-      isReturningJSX(mockContext, parseCode(codeStr))
+      isReturningJSX(mockContext, parseCode(codeStr)),
     );
 
     it('Works when returning JSX', () => {
diff --git a/tests/util/pragma.js b/tests/util/pragma.js
index 475f97aaa6..709bee5f3f 100644
--- a/tests/util/pragma.js
+++ b/tests/util/pragma.js
@@ -7,7 +7,7 @@ const espree = require('espree');
 const getFromContext = require('../../lib/util/pragma').getFromContext;
 
 const DEFAULT_CONFIG = {
-  ecmaVersion: 6,
+  ecmaVersion: 2022,
   comment: true,
   tokens: true,
   range: true,
@@ -44,7 +44,7 @@ describe('pragma', () => {
       const code = '// @jsx jsx';
       assert.strictEqual(
         getFromContext(fakeContext(code)),
-        'jsx'
+        'jsx',
       );
     });
 
@@ -52,7 +52,7 @@ describe('pragma', () => {
       const code = '';
       assert.strictEqual(
         getFromContext(fakeContext(code)),
-        DEFAULT_SETTINGS.react.pragma
+        DEFAULT_SETTINGS.react.pragma,
       );
     });
 

From 0750a48eb833d650eff461a172fadddc1c8a12c7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C3=ABl=20De=20Boey?= <info@michaeldeboey.be>
Date: Wed, 30 Oct 2024 01:06:40 +0100
Subject: [PATCH 2/2] feat: remove dependencies for Node built-ins

---
 index.js                                      |  7 ++---
 lib/rules/boolean-prop-naming.js              | 12 +++------
 .../checked-requires-onchange-or-readonly.js  |  4 +--
 lib/rules/default-props-match-prop-types.js   |  4 +--
 lib/rules/display-name.js                     |  3 +--
 lib/rules/forbid-elements.js                  |  5 ++--
 lib/rules/function-component-definition.js    |  7 +++--
 lib/rules/jsx-closing-bracket-location.js     | 13 ++++-----
 lib/rules/jsx-closing-tag-location.js         | 10 +++----
 lib/rules/jsx-curly-brace-presence.js         | 11 +++-----
 lib/rules/jsx-curly-spacing.js                |  9 +++----
 lib/rules/jsx-indent-props.js                 |  6 ++---
 lib/rules/jsx-indent.js                       | 12 +++------
 lib/rules/jsx-key.js                          |  5 ++--
 lib/rules/jsx-max-depth.js                    |  6 ++---
 lib/rules/jsx-no-duplicate-props.js           |  3 +--
 lib/rules/jsx-no-literals.js                  |  8 +++---
 lib/rules/jsx-no-script-url.js                |  3 +--
 lib/rules/jsx-no-target-blank.js              |  5 ++--
 lib/rules/jsx-no-useless-fragment.js          | 10 +++----
 lib/rules/jsx-sort-props.js                   |  8 ++----
 lib/rules/jsx-wrap-multilines.js              | 10 +++----
 lib/rules/no-array-index-key.js               |  3 +--
 lib/rules/no-arrow-function-lifecycle.js      |  9 ++-----
 lib/rules/no-danger.js                        |  6 ++---
 lib/rules/no-deprecated.js                    |  7 +++--
 lib/rules/no-direct-mutation-state.js         |  4 +--
 lib/rules/no-invalid-html-attribute.js        |  3 +--
 lib/rules/no-multi-comp.js                    |  4 +--
 lib/rules/no-object-type-as-default-prop.js   |  4 +--
 lib/rules/no-set-state.js                     |  4 +--
 lib/rules/no-unknown-property.js              | 11 ++++----
 lib/rules/no-unused-prop-types.js             |  4 +--
 lib/rules/prefer-read-only-props.js           |  6 +----
 lib/rules/prefer-stateless-function.js        | 11 +++-----
 lib/rules/prop-types.js                       |  6 ++---
 lib/rules/require-default-props.js            |  8 +++---
 lib/rules/require-optimization.js             |  6 ++---
 lib/rules/require-render-return.js            |  6 ++---
 lib/rules/sort-comp.js                        | 17 +++++-------
 lib/rules/static-property-placement.js        |  7 +++--
 lib/rules/void-dom-elements-no-children.js    |  4 +--
 lib/util/Components.js                        | 27 +++++++------------
 lib/util/defaultProps.js                      |  5 ++--
 lib/util/makeNoMethodSetStateRule.js          |  8 +++---
 lib/util/propTypes.js                         | 18 +++++--------
 lib/util/propTypesSort.js                     |  5 +---
 lib/util/usedPropTypes.js                     |  9 ++-----
 package.json                                  | 11 +-------
 tests/helpers/parsers.js                      |  8 +++---
 tests/util/Components.js                      | 11 +++-----
 types/string.prototype.repeat/index.d.ts      |  4 ---
 52 files changed, 127 insertions(+), 270 deletions(-)
 delete mode 100644 types/string.prototype.repeat/index.d.ts

diff --git a/index.js b/index.js
index 64ff9bbdc4..a12250f0d0 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<string, SEVERITY_ERROR | 'error'>}
  */
 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<typeof allRules>} */
diff --git a/lib/rules/boolean-prop-naming.js b/lib/rules/boolean-prop-naming.js
index c867e622b5..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
@@ -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
diff --git a/lib/rules/checked-requires-onchange-or-readonly.js b/lib/rules/checked-requires-onchange-or-readonly.js
index 7358426af9..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,8 +29,7 @@ const defaultOptions = {
  */
 function extractTargetProps(properties, keyName) {
   return new Set(
-    flatMap(
-      properties,
+    properties.flatMap(
       (prop) => (
         prop[keyName] && targetPropSet.has(prop[keyName].name)
           ? [prop[keyName].name]
diff --git a/lib/rules/default-props-match-prop-types.js b/lib/rules/default-props-match-prop-types.js
index de30f0d6ac..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,7 +93,7 @@ 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(
diff --git a/lib/rules/display-name.js b/lib/rules/display-name.js
index 4b07f74de7..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,7 +268,7 @@ 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) {
diff --git a/lib/rules/forbid-elements.js b/lib/rules/forbid-elements.js
index 299ee3b849..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(
diff --git a/lib/rules/function-component-definition.js b/lib/rules/function-component-definition.js
index 4801463b10..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');
 
 // ------------------------------------------------------------------------------
@@ -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/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 f55570f3ca..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,8 +114,7 @@ module.exports = {
         node,
         loc: node.loc,
         fix(fixer) {
-          const indent = repeat(
-            ' ',
+          const indent = ' '.repeat(
             getIndentation(openingStartOfLine, opening),
           );
 
diff --git a/lib/rules/jsx-curly-brace-presence.js b/lib/rules/jsx-curly-brace-presence.js
index 695e08a075..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) {
@@ -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 277297403b..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) {
@@ -148,9 +147,9 @@ module.exports = {
       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-indent-props.js b/lib/rules/jsx-indent-props.js
index 9badb7f4cc..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 9d5e0c034a..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) {
@@ -326,7 +320,7 @@ 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),
+        String(value).matchAll(regExp),
         (match) => (match[1] ? match[1].length : 0),
       );
       const hasFirstInLineNode = nodeIndentsPerLine.length > 0;
diff --git a/lib/rules/jsx-key.js b/lib/rules/jsx-key.js
index ab15bdf2b4..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
@@ -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-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-literals.js b/lib/rules/jsx-no-literals.js
index fac347d198..0ee35da317 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');
 
 /** @typedef {import('eslint').Rule.RuleModule} RuleModule */
 
@@ -104,9 +102,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];
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 779346e268..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) {
diff --git a/lib/rules/jsx-no-useless-fragment.js b/lib/rules/jsx-no-useless-fragment.js
index 979b805787..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) {
diff --git a/lib/rules/jsx-sort-props.js b/lib/rules/jsx-sort-props.js
index 09ff604a37..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
@@ -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-wrap-multilines.js b/lib/rules/jsx-wrap-multilines.js
index 05600cef58..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];
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 26596d91ea..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);
@@ -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 638b7677cf..ff8218bba5 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 (
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 3fd69db8ca..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;
 
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-unknown-property.js b/lib/rules/no-unknown-property.js
index d702cc4303..b583ae98ef 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');
 
 // ------------------------------------------------------------------------------
@@ -509,10 +508,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);
@@ -613,7 +612,7 @@ module.exports = {
         // Let's dive deeper into tags that are HTML/DOM elements (`<button>`), and not React components (`<Button />`)
 
         // Some attributes are allowed on some tags only
-        const allowedTags = has(ATTRIBUTE_TAGS_MAP, name)
+        const allowedTags = Object.hasOwn(ATTRIBUTE_TAGS_MAP, name)
           ? ATTRIBUTE_TAGS_MAP[/** @type {keyof ATTRIBUTE_TAGS_MAP} */ (name)]
           : null;
         if (tagName && allowedTags) {
diff --git a/lib/rules/no-unused-prop-types.js b/lib/rules/no-unused-prop-types.js
index 24fcee4173..37eed4f59c 100644
--- a/lib/rules/no-unused-prop-types.js
+++ b/lib/rules/no-unused-prop-types.js
@@ -5,8 +5,6 @@
 
 'use strict';
 
-const values = require('object.values');
-
 // As for exceptions for props.children or props.className (and alike) look at
 // https://github.com/jsx-eslint/eslint-plugin-react/issues/7
 
@@ -160,7 +158,7 @@ module.exports = {
     return {
       'Program:exit'() {
         // Report undeclared proptypes for all classes
-        values(components.list())
+        Object.values(components.list())
           .filter((component) => mustBeValidated(component))
           .forEach((component) => {
             reportUnusedPropTypes(component);
diff --git a/lib/rules/prefer-read-only-props.js b/lib/rules/prefer-read-only-props.js
index 0729752db6..61359c84fd 100644
--- a/lib/rules/prefer-read-only-props.js
+++ b/lib/rules/prefer-read-only-props.js
@@ -5,9 +5,6 @@
 
 'use strict';
 
-const flatMap = require('array.prototype.flatmap');
-const values = require('object.values');
-
 const Components = require('../util/Components');
 const docsUrl = require('../util/docsUrl');
 const report = require('../util/report');
@@ -76,8 +73,7 @@ module.exports = {
 
     return {
       'Program:exit'() {
-        flatMap(
-          values(components.list()),
+        Object.values(components.list()).flatMap(
           (component) => component.declaredPropTypes || [],
         ).forEach((declaredPropTypes) => {
           Object.keys(declaredPropTypes).forEach((propName) => {
diff --git a/lib/rules/prefer-stateless-function.js b/lib/rules/prefer-stateless-function.js
index 46847cb195..afff5d4633 100644
--- a/lib/rules/prefer-stateless-function.js
+++ b/lib/rules/prefer-stateless-function.js
@@ -7,18 +7,13 @@
 
 'use strict';
 
-const values = require('object.values');
-
 const Components = require('../util/Components');
-const testReactVersion = require('../util/version').testReactVersion;
+const { testReactVersion } = require('../util/version');
 const astUtil = require('../util/ast');
 const componentUtil = require('../util/componentUtil');
 const docsUrl = require('../util/docsUrl');
 const report = require('../util/report');
-const eslintUtil = require('../util/eslint');
-
-const getScope = eslintUtil.getScope;
-const getText = eslintUtil.getText;
+const { getScope, getText } = require('../util/eslint');
 
 // ------------------------------------------------------------------------------
 // Rule Definition
@@ -372,7 +367,7 @@ module.exports = {
 
       'Program:exit'() {
         const list = components.list();
-        values(list)
+        Object.values(list)
           .filter((component) => (
             !hasOtherProperties(component.node)
             && !component.useThis
diff --git a/lib/rules/prop-types.js b/lib/rules/prop-types.js
index 424a1557b9..1394888d2c 100644
--- a/lib/rules/prop-types.js
+++ b/lib/rules/prop-types.js
@@ -8,8 +8,6 @@
 // As for exceptions for props.children or props.className (and alike) look at
 // https://github.com/jsx-eslint/eslint-plugin-react/issues/7
 
-const values = require('object.values');
-
 const Components = require('../util/Components');
 const docsUrl = require('../util/docsUrl');
 const report = require('../util/report');
@@ -213,10 +211,10 @@ module.exports = {
       'Program:exit'() {
         const list = components.list();
         // Report undeclared proptypes for all classes
-        values(list)
+        Object.values(list)
           .filter((component) => mustBeValidated(component))
           .forEach((component) => {
-            if (checkNestedComponent(component, values(list))) return;
+            if (checkNestedComponent(component, Object.values(list))) return;
             reportUndeclaredPropTypes(component);
           });
       },
diff --git a/lib/rules/require-default-props.js b/lib/rules/require-default-props.js
index d82d6b9e25..e7ef098997 100644
--- a/lib/rules/require-default-props.js
+++ b/lib/rules/require-default-props.js
@@ -5,8 +5,6 @@
 
 'use strict';
 
-const entries = require('object.entries');
-const values = require('object.values');
 const Components = require('../util/Components');
 const docsUrl = require('../util/docsUrl');
 const astUtil = require('../util/ast');
@@ -85,7 +83,7 @@ module.exports = {
      * @return {void}
      */
     function reportPropTypesWithoutDefault(propTypes, defaultProps) {
-      entries(propTypes).forEach((propType) => {
+      Object.entries(propTypes).forEach((propType) => {
         const propName = propType[0];
         const prop = propType[1];
 
@@ -134,7 +132,7 @@ module.exports = {
       }
 
       if (props.type === 'Identifier') {
-        const hasOptionalProp = values(propTypes).some((propType) => !propType.isRequired);
+        const hasOptionalProp = Object.values(propTypes).some((propType) => !propType.isRequired);
         if (hasOptionalProp) {
           report(context, messages.destructureInSignature, 'destructureInSignature', {
             node: props,
@@ -175,7 +173,7 @@ module.exports = {
       'Program:exit'() {
         const list = components.list();
 
-        values(list).filter((component) => {
+        Object.values(list).filter((component) => {
           if (functions === 'ignore' && astUtil.isFunctionLike(component.node)) {
             return false;
           }
diff --git a/lib/rules/require-optimization.js b/lib/rules/require-optimization.js
index add2ccf95a..dfdd099d6e 100644
--- a/lib/rules/require-optimization.js
+++ b/lib/rules/require-optimization.js
@@ -5,13 +5,11 @@
 
 'use strict';
 
-const values = require('object.values');
-
 const Components = require('../util/Components');
 const componentUtil = require('../util/componentUtil');
 const docsUrl = require('../util/docsUrl');
 const report = require('../util/report');
-const getScope = require('../util/eslint').getScope;
+const { getScope } = require('../util/eslint');
 
 const messages = {
   noShouldComponentUpdate: 'Component is not optimized. Please add a shouldComponentUpdate method.',
@@ -229,7 +227,7 @@ module.exports = {
 
       'Program:exit'() {
         // Report missing shouldComponentUpdate for all components
-        values(components.list())
+        Object.values(components.list())
           .filter((component) => !component.hasSCU)
           .forEach((component) => {
             reportMissingOptimization(component);
diff --git a/lib/rules/require-render-return.js b/lib/rules/require-render-return.js
index c46613e420..246a21546c 100644
--- a/lib/rules/require-render-return.js
+++ b/lib/rules/require-render-return.js
@@ -5,14 +5,12 @@
 
 '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 report = require('../util/report');
-const getAncestors = require('../util/eslint').getAncestors;
+const { getAncestors } = require('../util/eslint');
 
 // ------------------------------------------------------------------------------
 // Rule Definition
@@ -86,7 +84,7 @@ module.exports = {
       },
 
       'Program:exit'() {
-        values(components.list())
+        Object.values(components.list())
           .filter((component) => (
             findRenderMethod(component.node)
             && !component.hasReturnStatement
diff --git a/lib/rules/sort-comp.js b/lib/rules/sort-comp.js
index edb052ffce..ae9e7d9798 100644
--- a/lib/rules/sort-comp.js
+++ b/lib/rules/sort-comp.js
@@ -5,11 +5,6 @@
 
 'use strict';
 
-const has = require('hasown');
-const entries = require('object.entries');
-const values = require('object.values');
-const arrayIncludes = require('array-includes');
-
 const Components = require('../util/Components');
 const astUtil = require('../util/ast');
 const docsUrl = require('../util/docsUrl');
@@ -68,7 +63,7 @@ function getMethodsOrder(userConfig) {
   let entry;
   for (let i = 0, j = order.length; i < j; i++) {
     entry = order[i];
-    if (has(groups, entry)) {
+    if (Object.hasOwn(groups, entry)) {
       config = config.concat(groups[entry]);
     } else {
       config.push(entry);
@@ -171,7 +166,7 @@ module.exports = {
           if (method.instanceMethod) {
             methodGroupIndexes.push(groupIndex);
           }
-        } else if (arrayIncludes([
+        } else if ([
           'displayName',
           'propTypes',
           'contextTypes',
@@ -198,7 +193,7 @@ module.exports = {
           'componentDidCatch',
           'componentWillUnmount',
           'render',
-        ], currentGroup)) {
+        ].includes(currentGroup)) {
           if (currentGroup === method.name) {
             methodGroupIndexes.push(groupIndex);
           }
@@ -288,7 +283,7 @@ module.exports = {
      * Dedupe errors, only keep the ones with the highest score and delete the others
      */
     function dedupeErrors() {
-      entries(errors).forEach((entry) => {
+      Object.entries(errors).forEach((entry) => {
         const i = entry[0];
         const error = entry[1];
 
@@ -309,7 +304,7 @@ module.exports = {
     function reportErrors() {
       dedupeErrors();
 
-      entries(errors).forEach((entry) => {
+      Object.entries(errors).forEach((entry) => {
         const nodeA = entry[1].node;
         const nodeB = entry[1].closest.ref.node;
         const indexA = entry[0];
@@ -435,7 +430,7 @@ module.exports = {
 
     return {
       'Program:exit'() {
-        values(components.list()).forEach((component) => {
+        Object.values(components.list()).forEach((component) => {
           const properties = astUtil.getComponentProperties(component.node);
           checkPropsOrder(properties);
         });
diff --git a/lib/rules/static-property-placement.js b/lib/rules/static-property-placement.js
index ce38a8e42e..0a02420edf 100644
--- a/lib/rules/static-property-placement.js
+++ b/lib/rules/static-property-placement.js
@@ -5,14 +5,13 @@
 
 'use strict';
 
-const fromEntries = require('object.fromentries');
 const Components = require('../util/Components');
 const docsUrl = require('../util/docsUrl');
 const astUtil = require('../util/ast');
 const componentUtil = require('../util/componentUtil');
 const propsUtil = require('../util/props');
 const report = require('../util/report');
-const getScope = require('../util/eslint').getScope;
+const { getScope } = require('../util/eslint');
 
 // ------------------------------------------------------------------------------
 // Positioning Options
@@ -44,7 +43,7 @@ const propertiesToCheck = {
 };
 
 const classProperties = Object.keys(propertiesToCheck);
-const schemaProperties = fromEntries(classProperties.map((property) => [property, { enum: POSITION_SETTINGS }]));
+const schemaProperties = Object.fromEntries(classProperties.map((property) => [property, { enum: POSITION_SETTINGS }]));
 
 // ------------------------------------------------------------------------------
 // Rule Definition
@@ -87,7 +86,7 @@ module.exports = {
     const additionalConfig = hasAdditionalConfig ? options[1] : {};
 
     // Set config
-    const config = fromEntries(classProperties.map((property) => [
+    const config = Object.fromEntries(classProperties.map((property) => [
       property,
       additionalConfig[property] || defaultCheckType,
     ]));
diff --git a/lib/rules/void-dom-elements-no-children.js b/lib/rules/void-dom-elements-no-children.js
index f8187b09ea..c1fe8f62fa 100644
--- a/lib/rules/void-dom-elements-no-children.js
+++ b/lib/rules/void-dom-elements-no-children.js
@@ -6,8 +6,6 @@
 
 'use strict';
 
-const has = require('hasown');
-
 const docsUrl = require('../util/docsUrl');
 const isCreateElement = require('../util/isCreateElement');
 const report = require('../util/report');
@@ -38,7 +36,7 @@ const VOID_DOM_ELEMENTS = {
 };
 
 function isVoidDOMElement(elementName) {
-  return has(VOID_DOM_ELEMENTS, elementName);
+  return Object.hasOwn(VOID_DOM_ELEMENTS, elementName);
 }
 
 // ------------------------------------------------------------------------------
diff --git a/lib/util/Components.js b/lib/util/Components.js
index d58b4fd45a..6c309cac71 100644
--- a/lib/util/Components.js
+++ b/lib/util/Components.js
@@ -5,9 +5,6 @@
 
 'use strict';
 
-const arrayIncludes = require('array-includes');
-const fromEntries = require('object.fromentries');
-const values = require('object.values');
 const iterFrom = require('es-iterator-helpers/Iterator.from');
 const map = require('es-iterator-helpers/Iterator.prototype.map');
 
@@ -21,10 +18,7 @@ const usedPropTypesUtil = require('./usedPropTypes');
 const defaultPropsUtil = require('./defaultProps');
 const isFirstLetterCapitalized = require('./isFirstLetterCapitalized');
 const isDestructuredFromPragmaImport = require('./isDestructuredFromPragmaImport');
-const eslintUtil = require('./eslint');
-
-const getScope = eslintUtil.getScope;
-const getText = eslintUtil.getText;
+const { getScope, getText } = require('./eslint');
 
 function getId(node) {
   return node ? `${node.range[0]}:${node.range[1]}` : '';
@@ -187,7 +181,7 @@ class Components {
    */
   length() {
     const list = Lists.get(this);
-    return values(list).filter((component) => component.confidence >= 2).length;
+    return Object.values(list).filter((component) => component.confidence >= 2).length;
   }
 
   /**
@@ -246,10 +240,10 @@ function getWrapperFunctions(context, pragma) {
   return componentWrapperFunctions.map((wrapperFunction) => {
     return typeof wrapperFunction === 'string'
       ? { property: wrapperFunction }
-      : ({
+      : {
         ...wrapperFunction,
         object: wrapperFunction.object === '<pragma>' ? pragma : wrapperFunction.object,
-      });
+      };
   }).concat([
     { property: 'forwardRef', object: pragma },
     { property: 'memo', object: pragma },
@@ -277,7 +271,7 @@ function mergeRules(rules) {
   });
 
   /** @type {{ [key: string]: Function }} */
-  return fromEntries(map(iterFrom(handlersByKey), (entry) => [
+  return Object.fromEntries(map(iterFrom(handlersByKey), (entry) => [
     entry[0],
     function mergedHandler(node) {
       entry[1].forEach((fn) => {
@@ -374,11 +368,11 @@ function componentRule(rule, context) {
 
     /**
      * Get the list of names of components created till now
-     * @returns {string | boolean}
+     * @returns {Array<string>}
      */
     getDetectedComponents() {
       const list = components.list();
-      return values(list).filter((val) => {
+      return Object.values(list).filter((val) => {
         if (val.node.type === 'ClassDeclaration') {
           return true;
         }
@@ -406,7 +400,7 @@ function componentRule(rule, context) {
     nodeWrapsComponent(node) {
       const childComponent = this.getNameOfWrappedComponent(node.arguments);
       const componentList = this.getDetectedComponents();
-      return !!childComponent && arrayIncludes(componentList, childComponent);
+      return !!childComponent && componentList.includes(childComponent);
     },
 
     isPragmaComponentWrapper(node) {
@@ -779,7 +773,7 @@ function componentRule(rule, context) {
       const reactHookImportSpecifiers = namedReactImports
         && namedReactImports.filter((specifier) => USE_HOOK_PREFIX_REGEX.test(specifier.imported.name));
       const reactHookImportNames = reactHookImportSpecifiers
-        && fromEntries(reactHookImportSpecifiers.map((specifier) => [specifier.local.name, specifier.imported.name]));
+        && Object.fromEntries(reactHookImportSpecifiers.map((specifier) => [specifier.local.name, specifier.imported.name]));
 
       const isPotentialReactHookCall = defaultReactImportName
         && node.callee.type === 'MemberExpression'
@@ -836,8 +830,7 @@ function componentRule(rule, context) {
         return true;
       }
 
-      return arrayIncludes(
-        expectedHookNames,
+      return expectedHookNames.includes(
         (reactHookImportNames && reactHookImportNames[localHookName]) || localHookName,
       );
     },
diff --git a/lib/util/defaultProps.js b/lib/util/defaultProps.js
index 5bd476394d..d354020629 100644
--- a/lib/util/defaultProps.js
+++ b/lib/util/defaultProps.js
@@ -4,13 +4,12 @@
 
 'use strict';
 
-const fromEntries = require('object.fromentries');
 const astUtil = require('./ast');
 const componentUtil = require('./componentUtil');
 const propsUtil = require('./props');
 const variableUtil = require('./variable');
 const propWrapperUtil = require('./propWrapper');
-const getText = require('./eslint').getText;
+const { getText } = require('./eslint');
 
 const QUOTES_REGEX = /^["']|["']$/g;
 
@@ -89,7 +88,7 @@ module.exports = function defaultPropsInstructions(context, components, utils) {
     const defaults = component.defaultProps || {};
     const newDefaultProps = {
       ...defaults,
-      ...fromEntries(defaultProps.map((prop) => [prop.name, prop])),
+      ...Object.fromEntries(defaultProps.map((prop) => [prop.name, prop])),
     };
 
     components.set(component.node, {
diff --git a/lib/util/makeNoMethodSetStateRule.js b/lib/util/makeNoMethodSetStateRule.js
index b6c55d5cf6..0f6752c0fa 100644
--- a/lib/util/makeNoMethodSetStateRule.js
+++ b/lib/util/makeNoMethodSetStateRule.js
@@ -5,12 +5,10 @@
 
 'use strict';
 
-const findLast = require('array.prototype.findlast');
-
 const docsUrl = require('./docsUrl');
 const report = require('./report');
-const getAncestors = require('./eslint').getAncestors;
-const testReactVersion = require('./version').testReactVersion;
+const { getAncestors } = require('./eslint');
+const { testReactVersion } = require('./version');
 
 // ------------------------------------------------------------------------------
 // Rule Definition
@@ -103,7 +101,7 @@ module.exports = function makeNoMethodSetStateRule(methodName, shouldCheckUnsafe
           }
           const ancestors = getAncestors(context, node);
           let depth = 0;
-          findLast(ancestors, (ancestor) => {
+          ancestors.findLast((ancestor) => {
           // ancestors.some((ancestor) => {
             if (/Function(Expression|Declaration)$/.test(ancestor.type)) {
               depth += 1;
diff --git a/lib/util/propTypes.js b/lib/util/propTypes.js
index 1e073fff88..82f9951833 100644
--- a/lib/util/propTypes.js
+++ b/lib/util/propTypes.js
@@ -4,8 +4,6 @@
 
 'use strict';
 
-const flatMap = require('array.prototype.flatmap');
-
 const annotations = require('./annotations');
 const propsUtil = require('./props');
 const variableUtil = require('./variable');
@@ -13,12 +11,9 @@ const testFlowVersion = require('./version').testFlowVersion;
 const propWrapperUtil = require('./propWrapper');
 const astUtil = require('./ast');
 const isFirstLetterCapitalized = require('./isFirstLetterCapitalized');
-const eslintUtil = require('./eslint');
-
-const getFirstTokens = eslintUtil.getFirstTokens;
-const getScope = eslintUtil.getScope;
-const getSourceCode = eslintUtil.getSourceCode;
-const getText = eslintUtil.getText;
+const {
+  getFirstTokens, getScope, getSourceCode, getText,
+} = require('./eslint');
 
 /**
  * Check if node is function type.
@@ -699,8 +694,7 @@ module.exports = function propTypesInstructions(context, components, utils) {
        */
       const candidateTypes = this.sourceCode.ast.body.filter((item) => astUtil.isTSTypeDeclaration(item));
 
-      const declarations = flatMap(
-        candidateTypes,
+      const declarations = candidateTypes.flatMap(
         (type) => (
           type.declarations
           || (
@@ -774,10 +768,10 @@ module.exports = function propTypesInstructions(context, components, utils) {
           }
           // Handle ReturnType<typeof mapStateToProps>
           if (astUtil.isTSTypeQuery(returnType)) {
-            const returnTypeFunction = flatMap(this.sourceCode.ast.body
+            const returnTypeFunction = this.sourceCode.ast.body
               .filter((item) => item.type === 'VariableDeclaration'
                 && item.declarations.find((dec) => dec.id.name === returnType.exprName.name),
-              ), (type) => type.declarations).map((dec) => dec.init);
+              ).flatMap((type) => type.declarations).map((dec) => dec.init);
 
             if (Array.isArray(returnTypeFunction)) {
               if (returnTypeFunction.length === 0) {
diff --git a/lib/util/propTypesSort.js b/lib/util/propTypesSort.js
index 342e1cb054..5f3347d778 100644
--- a/lib/util/propTypesSort.js
+++ b/lib/util/propTypesSort.js
@@ -7,10 +7,7 @@
 const toSorted = require('array.prototype.tosorted');
 
 const astUtil = require('./ast');
-const eslintUtil = require('./eslint');
-
-const getSourceCode = eslintUtil.getSourceCode;
-const getText = eslintUtil.getText;
+const { getSourceCode, getText } = require('./eslint');
 
 /**
  * Returns the value name of a node.
diff --git a/lib/util/usedPropTypes.js b/lib/util/usedPropTypes.js
index f0dae34ca4..ba7020c722 100644
--- a/lib/util/usedPropTypes.js
+++ b/lib/util/usedPropTypes.js
@@ -4,15 +4,10 @@
 
 'use strict';
 
-const values = require('object.values');
-
 const astUtil = require('./ast');
 const componentUtil = require('./componentUtil');
 const testReactVersion = require('./version').testReactVersion;
-const eslintUtil = require('./eslint');
-
-const getScope = eslintUtil.getScope;
-const getSourceCode = eslintUtil.getSourceCode;
+const { getScope, getSourceCode } = require('./eslint');
 
 // ------------------------------------------------------------------------------
 // Constants
@@ -555,7 +550,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
     },
 
     'Program:exit'() {
-      values(components.list())
+      Object.values(components.list())
         .filter((component) => mustBeValidated(component))
         .forEach((component) => {
           handleCustomValidators(component);
diff --git a/package.json b/package.json
index a54490d1ec..7ebe931a55 100644
--- a/package.json
+++ b/package.json
@@ -36,24 +36,15 @@
   "homepage": "https://github.com/jsx-eslint/eslint-plugin-react",
   "bugs": "https://github.com/jsx-eslint/eslint-plugin-react/issues",
   "dependencies": {
-    "array-includes": "^3.1.8",
-    "array.prototype.findlast": "^1.2.5",
-    "array.prototype.flatmap": "^1.3.3",
     "array.prototype.tosorted": "^1.1.4",
     "doctrine": "^2.1.0",
     "es-iterator-helpers": "^1.2.1",
     "estraverse": "^5.3.0",
-    "hasown": "^2.0.2",
     "jsx-ast-utils": "^2.4.1 || ^3.0.0",
     "minimatch": "^3.1.2",
-    "object.entries": "^1.1.9",
-    "object.fromentries": "^2.0.8",
-    "object.values": "^1.2.1",
     "prop-types": "^15.8.1",
     "resolve": "^2.0.0-next.5",
-    "semver": "^6.3.1",
-    "string.prototype.matchall": "^4.0.12",
-    "string.prototype.repeat": "^1.0.0"
+    "semver": "^6.3.1"
   },
   "devDependencies": {
     "@babel/core": "^7.26.10",
diff --git a/tests/helpers/parsers.js b/tests/helpers/parsers.js
index a4d55252a5..cd1da223ab 100644
--- a/tests/helpers/parsers.js
+++ b/tests/helpers/parsers.js
@@ -1,9 +1,7 @@
 'use strict';
 
 const semver = require('semver');
-const entries = require('object.entries');
-const version = require('eslint/package.json').version;
-const flatMap = require('array.prototype.flatmap');
+const { version } = require('eslint/package.json');
 const tsParserVersion = require('@typescript-eslint/parser/package.json').version;
 
 const disableNewTS = semver.satisfies(tsParserVersion, '>= 4.1') // this rule is not useful on v4.1+ of the TS parser
@@ -20,7 +18,7 @@ function minEcmaVersion(features, parserOptions) {
     Math,
     [].concat(
       (parserOptions && parserOptions.ecmaVersion) || [],
-      flatMap(entries(minEcmaVersionForFeatures), (entry) => {
+      Object.entries(minEcmaVersionForFeatures).flatMap((entry) => {
         const f = entry[0];
         const y = entry[1];
         return features.has(f) ? y : [];
@@ -65,7 +63,7 @@ const parsers = {
     };
   },
   all: function all(tests) {
-    const t = flatMap(tests, (test) => {
+    const t = tests.flatMap((test) => {
       if (typeof test === 'string') {
         test = { code: test };
       }
diff --git a/tests/util/Components.js b/tests/util/Components.js
index 4e9255678d..8160860c07 100644
--- a/tests/util/Components.js
+++ b/tests/util/Components.js
@@ -1,9 +1,6 @@
 'use strict';
 
 const assert = require('assert');
-const entries = require('object.entries');
-const fromEntries = require('object.fromentries');
-const values = require('object.values');
 
 const RuleTester = require('../helpers/ruleTester');
 const Components = require('../../lib/util/Components');
@@ -29,8 +26,8 @@ describe('Components', () => {
         create: Components.detect((_context, components, util) => {
           const instructionResults = [];
 
-          const augmentedInstructions = fromEntries(
-            entries(instructions || {}).map((nodeTypeAndHandler) => {
+          const augmentedInstructions = Object.fromEntries(
+            Object.entries(instructions || {}).map((nodeTypeAndHandler) => {
               const nodeType = nodeTypeAndHandler[0];
               const handler = nodeTypeAndHandler[1];
               return [nodeType, (node) => {
@@ -74,7 +71,7 @@ describe('Components', () => {
           }`,
       }, (components) => {
         assert.equal(components.length(), 1, 'MyStatelessComponent should be detected component');
-        values(components.list()).forEach((component) => {
+        Object.values(components.list()).forEach((component) => {
           assert.equal(
             component.node.id.name,
             'MyStatelessComponent',
@@ -94,7 +91,7 @@ describe('Components', () => {
         }`,
       }, (components) => {
         assert(components.length() === 1, 'MyClassComponent should be detected component');
-        values(components.list()).forEach((component) => {
+        Object.values(components.list()).forEach((component) => {
           assert.equal(
             component.node.id.name,
             'MyClassComponent',
diff --git a/types/string.prototype.repeat/index.d.ts b/types/string.prototype.repeat/index.d.ts
deleted file mode 100644
index b2e5992712..0000000000
--- a/types/string.prototype.repeat/index.d.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-declare module 'string.prototype.repeat' {
-  function repeat(text: string, count: number): string;
-  export = repeat;
-}