-
-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Describe the bug
I noticed that after prolonged use of @antfu/eslint-config
ESLint extension in VS Code will crash with an exception indicating infinite recursion like this one:
RangeError: Error while loading rule 'prefer-const': Maximum call stack size exceeded
Occurred while linting <input>
at Reflect.get (<anonymous>)
at Object.get (file:///Users/roman/Documents/dev/eslint-flat-config-recursion/node_modules/eslint-flat-config-utils/dist/index.mjs:32:24)
at Reflect.get (<anonymous>)
at Object.get (file:///Users/roman/Documents/dev/eslint-flat-config-recursion/node_modules/eslint-flat-config-utils/dist/index.mjs:32:24)
at Reflect.get (<anonymous>)
at Object.get (file:///Users/roman/Documents/dev/eslint-flat-config-recursion/node_modules/eslint-flat-config-utils/dist/index.mjs:32:24)
at Reflect.get (<anonymous>)
at Object.get (file:///Users/roman/Documents/dev/eslint-flat-config-recursion/node_modules/eslint-flat-config-utils/dist/index.mjs:32:24)
at Reflect.get (<anonymous>)
at Object.get (file:///Users/roman/Documents/dev/eslint-flat-config-recursion/node_modules/eslint-flat-config-utils/dist/index.mjs:32:24)
It was getting quite annoying to keep restarting ESLint server each time that happened so I decided to investigate and it led me to disableRuleFixes
function in this repo.
eslint-flat-config-utils/src/hijack.ts
Lines 26 to 56 in 45c6e98
export function disableRuleFixes(rule: Rule.RuleModule): Rule.RuleModule { | |
if ((rule as any)[FLAG_DISABLE_FIXES]) { | |
return rule | |
} | |
const originalCreate = rule.create.bind(rule) | |
rule.create = (context): any => { | |
const clonedContext = { ...context } | |
const proxiedContext = new Proxy(clonedContext, { | |
get(target, prop, receiver): any { | |
if (prop === 'report') { | |
return function (report: any) { | |
if (report.fix) { | |
delete report.fix | |
} | |
return (Reflect.get(context, prop, receiver) as any)({ | |
...report, | |
fix: undefined, | |
}) | |
} | |
} | |
return Reflect.get(context, prop, receiver) | |
}, | |
set(target, prop, value, receiver): any { | |
return Reflect.set(context, prop, value, receiver) | |
}, | |
}) | |
Object.defineProperty(proxiedContext, FLAG_DISABLE_FIXES, { value: true, enumerable: false }) | |
return originalCreate(proxiedContext) | |
} | |
return rule | |
} |
Here FLAG_DISABLE_FIXES
is used to guard against repeatedly setting proxy. But the flag is set on proxiedContext
while it's checked on the rule
itself causing proxy to be set again and again. Which eventually leads to stack trace overflow.
Kind of hard to come up with a proper minimal repro so I created an artificial example that calls disableRuleFixes
10_000 times on a single rule and then runs that rule through ESLint. This consistently crashes it on my machine but you may need to increase number of iterations.
After I update disableRuleFixes
function to correctly set flag on the rule itself - stack overflow error goes away.
Repro steps:
- Clone https://github.com/romansp/eslint-flat-config-recursion
- npm install
- run
node test-disable-rule-fixes.mjs
Expected: No exception is thrown.
Actual: Maximum call stack size exceeded exception is thrown.
Relevant thread in Discord: https://discord.com/channels/937808017016119440/937977751472840704/threads/1344413385986408561
Fix seems to be trivial and I'd like to submit a PR.
Reproduction
https://github.com/romansp/eslint-flat-config-recursion
System Info
System:
OS: macOS 15.5
CPU: (10) arm64 Apple M1 Pro
Memory: 133.66 MB / 32.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 22.17.1 - ~/.nvm/versions/node/v22.17.1/bin/node
Yarn: 4.9.2 - ~/.nvm/versions/node/v22.17.1/bin/yarn
npm: 10.9.2 - ~/.nvm/versions/node/v22.17.1/bin/npm
bun: 1.2.19 - ~/.bun/bin/bun
Browsers:
Chrome: 138.0.7204.169
Safari: 18.5
Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guide.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A, please open a GitHub Discussion instead.
- The provided reproduction is a minimal reproducible of the bug.
Contributions
- I am willing to submit a PR to fix this issue
- I am willing to submit a PR with failing tests (actually just go ahead and do it, thanks!)