Skip to content

Fix ESLint v10 RuleContext API removal (follow-up to #3972) - #3979

Open
ledsun wants to merge 2 commits into
jsx-eslint:masterfrom
ledsun:update-deprecated-calls-v8
Open

Fix ESLint v10 RuleContext API removal (follow-up to #3972)#3979
ledsun wants to merge 2 commits into
jsx-eslint:masterfrom
ledsun:update-deprecated-calls-v8

Conversation

@ledsun

@ledsun ledsun commented Feb 9, 2026

Copy link
Copy Markdown

This PR follows up on the feedback in the comments of #3972 and incorporates the requested changes.

I think this PR will fix #3977.

@ljharb ljharb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we'll need regression tests - it might be as simple as adding eslint 10 to the GHA matrix.

@codecov

codecov Bot commented Feb 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.56%. Comparing base (c9a2de7) to head (4b25647).
⚠️ Report is 2 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3979      +/-   ##
==========================================
- Coverage   97.71%   97.56%   -0.15%     
==========================================
  Files         137      134       -3     
  Lines       10188    10177      -11     
  Branches     3797     3797              
==========================================
- Hits         9955     9929      -26     
- Misses        233      248      +15     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ledsun
ledsun marked this pull request as ready for review February 11, 2026 12:08
Comment thread lib/util/eslint.js Outdated
Comment thread lib/util/version.js Outdated
Comment thread lib/util/makeNoMethodSetStateRule.js
Comment thread .github/workflows/node-18+.yml Outdated
Comment thread lib/util/version.js Outdated
Comment thread package.json Outdated
Comment thread .github/workflows/eslint-9+.yml Outdated
Comment thread .github/workflows/eslint-8-.yml
Comment thread .github/workflows/eslint-9+.yml Outdated
@karlnorling

Copy link
Copy Markdown

@ledsun do you have time to address the failing checks. I'm looking at updating to eslint 10 and we're using the eslint-plugin-react

@plthomasva

Copy link
Copy Markdown

I’ve rebased the PR onto the latest master and force-pushed the updated branch so that all CI checks run again and give us a clear picture of the current status. Once they finish, we can review the remaining failures and decide on the next steps.

I took a look at the logs for the first few failures. I'm wondering @ljharb , if it's time to prune the test matrix. The deprecation warnings for many dependencies are pretty dire ["unsupported" is the least dramatic].

It's very hard to tell whether there's actually a problem with this pull request or whether the matrix is untestable, as-is.

@Trott

Trott commented Jul 23, 2026

Copy link
Copy Markdown

I don't think it will get everything passing, but I believe this patch will get us closer, if it is an acceptable approach.

EDIT: To explain what's going on: New TypeScript parsers need a newer TypeScript. The tests were giving them an old TypeScript, so they crashed. The older, deprecated parser has the opposite problem: it cannot work with the newer TypeScript.

So the patch does this: When testing a modern TypeScript parser, install TypeScript 5 so that parser can run. In those same tests, don’t also test the deprecated parser, because it cannot run with TypeScript 5.

There are still other problems, so I think there will still be tests failures to sort through, but this should greatly reduce the noise. But I don't know if this approach is compatible with the compatibility goals. (I sure hope so, though.)

diff --git a/.github/workflows/eslint-8-.yml b/.github/workflows/eslint-8-.yml
index 42168ae7..55b049a9 100644
--- a/.github/workflows/eslint-8-.yml
+++ b/.github/workflows/eslint-8-.yml
@@ -100,7 +100,7 @@ jobs:
         with:
           node-version: ${{ matrix.node-version }}
           after_install: |
-            npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.typescript-eslint == 8 && 8.17 || matrix.typescript-eslint }}" "babel-eslint@${{ matrix.babel-eslint }}"
+            npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.typescript-eslint == 8 && 8.17 || matrix.typescript-eslint }}" "babel-eslint@${{ matrix.babel-eslint }}" ${{ matrix.typescript-eslint >= 6 && '"typescript@5"' || '' }}
         env:
           NPM_CONFIG_LEGACY_PEER_DEPS: "${{ matrix.typescript-eslint >= 6 && 'false' || 'true' }}"
       - run: npx ls-engines
diff --git a/.github/workflows/eslint-9+.yml b/.github/workflows/eslint-9+.yml
index 91a8ddc4..6c889ea9 100644
--- a/.github/workflows/eslint-9+.yml
+++ b/.github/workflows/eslint-9+.yml
@@ -50,7 +50,7 @@ jobs:
         with:
           node-version: ${{ matrix.node-version }}
           after_install: |
-            npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.eslint == 10 && 'canary' || (matrix.typescript-eslint == 8 && 8.17 || matrix.typescript-eslint) }}" "babel-eslint@${{ matrix.babel-eslint }}" ${{ matrix.eslint == 10 && '"typescript@5"' || '' }}
+            npm install --no-save "eslint@${{ matrix.eslint }}" "@typescript-eslint/parser@${{ matrix.eslint == 10 && 'canary' || (matrix.typescript-eslint == 8 && 8.17 || matrix.typescript-eslint) }}" "babel-eslint@${{ matrix.babel-eslint }}" "typescript@5"
           skip-ls-check: true
       - run: npx ls-engines
       - run: npm run unit-test
diff --git a/tests/helpers/parsers.js b/tests/helpers/parsers.js
index f0a1e679..a9fe5ecb 100644
--- a/tests/helpers/parsers.js
+++ b/tests/helpers/parsers.js
@@ -150,8 +150,11 @@ const parsers = {
         || features.has('jsx namespace')
         || features.has('bind operator')
         || features.has('do expressions');
-      // typescript-eslint-parser (deprecated) cannot parse a TS 5 tsconfig, used by the eslint 10 matrix.
-      const tsOld = !skipTS && !features.has('no-ts-old') && !semver.satisfies(version, '>= 10');
+      // typescript-eslint-parser (deprecated) cannot parse the TS 5 tsconfig used with modern TS parsers.
+      const tsOld = !skipTS
+        && !features.has('no-ts-old')
+        && !semver.satisfies(version, '>= 10')
+        && !semver.satisfies(tsParserVersion, '>= 6');
       const tsNew = !skipTS && !features.has('no-ts-new');
 
       return [].concat(

@Trott

Trott commented Jul 24, 2026

Copy link
Copy Markdown

@ljharb What is the right approach to take with react/jsx-no-undef now that ESLint 10 no-undef will flag the same issues (since it tracks JSX references)? The options would seem to be:

  1. Do nothing. Enabling both rules means both rules report errors about the same undefined references.
  2. Make react/jsx-no-undef a no-op on ESLint 10. This avoids duplicate errors but leaves users unprotected if no-undef is disabled.
  3. Deprecate react/jsx-no-undef for ESLint 10. Tell users to use no-undef instead.

One thing I wanted to do which does not seem possible to reliably do is "Check if no-undef is enabled and, if ESLint 10, make react/jsx-no-undef a no-op." Rules cannot reliably see what other rules are enabled/disabled, I don't think.

(Apologies if this is covered above. I'm having trouble getting GitHub to load the entire conversation.)

@Trott

Trott commented Jul 24, 2026

Copy link
Copy Markdown

Here's a branch that adds three commits on top of the two that are in this PR. It gets us most of the way there. Just 18 remaining failed tests, 10 of which are the jsx-no-undef failures I asked about in the previous comment.

https://github.com/Trott/eslint-plugin-react/tree/patch-1

@haimuhaimu haimuhaimu left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the new ESLint 10 matrix against the package published Node.js engine range and the generated Actions cells.

Finding (.github/workflows/eslint-9+.yml, matrix exclusions around lines 37-44): the >=18 matrix also generates Node 21 and 23, but eslint@10.8.0 declares engines.node as ^20.19.0 || ^22.13.0 || >=24. The current Actions run contains ESLint 10 jobs for both unsupported odd-numbered releases, so engine-related failures in those cells cannot validate this plugin ESLint 10 support. Could we exclude Node 21 and 23 as well and update the comment from the broader “20+” wording, or derive the supported cells from the ESLint engine range?

@plthomasva

plthomasva commented Jul 28, 2026

Copy link
Copy Markdown

Here's a branch that adds three commits on top of the two that are in this PR. It gets us most of the way there. Just 18 remaining failed tests, 10 of which are the jsx-no-undef failures I asked about in the previous comment.

https://github.com/Trott/eslint-plugin-react/tree/patch-1

@ledsun : how does this patch look to you? getting us down to a handful less than four hands full of failing tests feels like a big move towards wrapping this work up

@plthomasva

Copy link
Copy Markdown

Reviewed the new ESLint 10 matrix against the package published Node.js engine range and the generated Actions cells.

Finding (.github/workflows/eslint-9+.yml, matrix exclusions around lines 37-44): the >=18 matrix also generates Node 21 and 23, but eslint@10.8.0 declares engines.node as ^20.19.0 || ^22.13.0 || >=24. The current Actions run contains ESLint 10 jobs for both unsupported odd-numbered releases, so engine-related failures in those cells cannot validate this plugin ESLint 10 support. Could we exclude Node 21 and 23 as well and update the comment from the broader “20+” wording, or derive the supported cells from the ESLint engine range?

@ljharb : it does seem like the matrix is extremely wide-ranging, possibly into version permutations nobody would be using in practice today. I believe we are all in support of maximalist compatibility: you never know what weird edge cases result in strange version pin combinations out in the wild. That said, eventually pruning long-unsupported versions is also thing.

@plthomasva

Copy link
Copy Markdown

I have prepared a complete, 100% green patch branch built on top of this PR (#3979) and subsequent community contributions, fully resolving all remaining unit test failures under ESLint 10.

Patched Branch: plthomasva/eslint-plugin-react@update-deprecated-calls-v8


History & Summary of Integrated Changes

This branch consolidates and builds upon the work of several contributors across the PR history:

  1. RuleContext & getFilename API adaptations (by @ledsun & @tylermumford):

    • Replaced deprecated/removed context.getFilename() calls with eslintUtil.getFilename(context).
  2. RuleTester type: property stripping (by @captaindonald in [Tests] drop ESLint-10-incompatible 'type:' property from RuleTester error assertions #4006):

    • Added helper in tests/helpers/ruleTester.js to strip type: from expected error objects when running on ESLint >= 10.
  3. Matrix & Spacing API updates (from @Trott's patch-1 branch):

    • CI Matrix: Added typescript@5 installation to ESLint 9+ test matrices so modern TS parsers don't fail against old matrix TypeScript versions.
    • isSpaceBetween Fallback: Added eslintUtil.isSpaceBetween helper in lib/util/eslint.js replacing the removed sourceCode.isSpaceBetweenTokens.
    • RuleTester Valid Cases: Stripped invalid output and errors fields from valid test cases in jsx-indent-props, jsx-indent, jsx-no-bind, and require-optimization.
  4. Additional Fixes in this Patch Branch:

    • JSDoc Comment Fallback (lib/util/componentUtil.js): Added a fallback checking sourceCode.getCommentsBefore(node) when the removed sourceCode.getJSDocComment is unavailable on ESLint 10. This fixes JSDoc @extends React.Component detection for no-typos and prop-types. Also refactored out the legacy try/catch block.
    • Canary Parser Support (tests/helpers/parsers.js): Passed { includePrerelease: true } to semver.satisfies so canary/prerelease versions of @typescript-eslint/parser (e.g. 10.0.0-canary...) are matched correctly by parsers.disableNewTS. Fixes failures in jsx-uses-react.
    • no-undef JSX Comment Override (tests/lib/rules/jsx-no-undef.js): Added a test code map replacing /*eslint no-undef:1*/ with /*eslint no-undef:0*/ on ESLint >= 10, preventing ESLint 10's native JSX no-undef tracking from producing duplicate errors alongside jsx-no-undef.
    • Windows Path Resolution (lib/util/version.js): Added ENOENT handling alongside ENOTDIR in resolveBasedir for virtual file paths on Windows.

Verification Results

All 11,923 unit tests pass 100% locally on ESLint 10:

  11923 passing (40s)

=============================== Coverage summary ===============================
Statements   : 95.35% ( 8118/8514 )
Branches     : 92.11% ( 6946/7541 )
Functions    : 97.75% ( 1085/1110 )
Lines        : 95.6% ( 7987/8355 )
================================================================================
  • Type-check (npm run type-check): Clean exit code 0.

Acknowledgment

These additional changes and verification were developed with the assistance of Antigravity and the Gemini 3.6 Flash model.

@ledsun

ledsun commented Jul 29, 2026

Copy link
Copy Markdown
Author

@plthomasva
How about creating a new pull request based on the https://github.com/plthomasva/eslint-plugin-react/tree/update-deprecated-calls-v8 branch you created? I think that would make the current progress of the work clearer.
It would be helpful to include a reference to this pull request so that people can refer back to the previous discussion.

Please note that I am not a maintainer, so this is not advice implying that “if you recreate the pull request, it can be merged.”

@plthomasva

Copy link
Copy Markdown

I'm a little worried that this doesn't actually make as much progress as I thought based on the simulated matrix run in PR#1 of my fork. :(

@manzoorwanijk

Copy link
Copy Markdown

Any update on this?

@lorand-horvath

Copy link
Copy Markdown

Any update on this?

import-js/eslint-plugin-import#3227 (comment)

@plthomasva

Copy link
Copy Markdown

Everyone, thank you for your patience! I'm brand new to this repository, so it took me a while to massage the test matrix. #4022 has a clean board and is just awaiting maintainer review and any changes needed.

It is a breaking change, but it's the easiest kind of breaking change. Anyone who still wants to use the (generally abandoned by now) oldest ESLint versions will have to pin to v7.x here. Similarly, anyone who wants to use Node versions less than 16 will have to pin, becuse ESLint no longer supports them.

I don't really see these as particularly breaking: You aren't using the ESLint React plugin without ESLint! See you over in comments on my follow-on PR.

@BearCooder

Copy link
Copy Markdown

Great work and thank you for your efforts! @plthomasva This is getting increasingly urgent as ESLint 9.x goes EOL on August 6th, so any comment from maintainers would be nice..

@codler

codler commented Aug 16, 2026

Copy link
Copy Markdown

Moved to Oxlint while waiting.

@rburgstaller

Copy link
Copy Markdown

Moved to Oxlint while waiting.

Did so too but did you manage to replicate all of the rules with oxlint?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

Upgrade to ESLint v10 ESLint v10 compatibility