Skip to content

linter: eslint/no-loop-func flags safe let-scoped callbacks #22804

@jeanne-cai

Description

@jeanne-cai

What version of Oxlint are you using?

1.67.0

What command did you run?

yarn oxlint -c oxlint.config.mjs

What does your .oxlintrc.json (or oxlint.config.ts) config file look like?

import { defineConfig } from 'oxlint';

export default defineConfig({
    categories: {
        correctness: 'off',
    },
    rules: {
        'eslint/no-loop-func': 'error',
    },
});

What happened?

Oxlint reports eslint(no-loop-func) for functions inside loops, even when loop variables use let, incorrectly flagging safe closures.

To reproduce:

const callbacks = [];
for (let row = 0; row < 5; row++) {
    for (let col = 0; col < 5; col++) {
        // flag
        callbacks.push(function () {
            return row + col;
        });
    }
}

let factor = 0;
if (factor < 5) {
    factor++;
} else {
    for (let index = 0; index < 5; index++) {
        // flag
        const compute = (value, index) => factor * value + index;
    }
}

let isOn = false;
if (isOn) {
    isOn = true;
}

for (let imageId = 0; imageId < 5; imageId++) {
    // flag
    image.onload = () => (isOn ? 'enabled' : 'disabled');
}

Output:

  × eslint(no-loop-func): Function declared in a loop contains unsafe references to variable(s)
   ╭─[test.ts:5:24]
 4 │             // flag
 5 │ ╭─▶         callbacks.push(function () {
 6 │ │               return row + col;
 7 │ ╰─▶         });
 8 │         }
   ╰────
  help: Variables declared with 'var' are function-scoped, not block-scoped. Consider using 'let' or 'const' for block-scoped variables, or move the function outside the loop.

  × eslint(no-loop-func): Function declared in a loop contains unsafe references to variable(s)
    ╭─[test.ts:17:25]
 16 │         // flag
 17 │         const compute = (value, index) => factor * value + index;
    ·                         ────────────────────────────────────────
 18 │     }
    ╰────
  help: Variables declared with 'var' are function-scoped, not block-scoped. Consider using 'let' or 'const' for block-scoped variables, or move the function outside the loop.

  × eslint(no-loop-func): Function declared in a loop contains unsafe references to variable(s)
    ╭─[test.ts:28:20]
 27 │     // flag
 28 │     image.onload = () => (isOn ? 'enabled' : 'disabled');
    ·                    ─────────────────────────────────────
 29 │ }
    ╰────
  help: Variables declared with 'var' are function-scoped, not block-scoped. Consider using 'let' or 'const' for block-scoped variables, or move the function outside the loop.

Metadata

Metadata

Assignees

Labels

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions