From b871235c8d403cd9f90753fb1b68638cc21c0398 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Thu, 22 Jan 2026 11:39:43 +0000 Subject: [PATCH] fix(linter/plugins): fix identifying "use strict" directives in scope analysis (#18402) Oxlint JS plugins use TS-ESLint's scope manager to build the scope tree. TS-ESLint has a bug where it's too liberal in identifying `"use strict"` directives: https://github.com/typescript-eslint/typescript-eslint/issues/11993 Patch `@typescript-eslint/scope-manager` to fix this bug, pending a fix upstream. Conformance tests now at 100% passing! --- apps/oxlint/conformance/snapshot.md | 51 +++---------------- .../@typescript-eslint__scope-manager.patch | 31 +++++++++++ pnpm-lock.yaml | 7 ++- pnpm-workspace.yaml | 1 + 4 files changed, 43 insertions(+), 47 deletions(-) create mode 100644 patches/@typescript-eslint__scope-manager.patch diff --git a/apps/oxlint/conformance/snapshot.md b/apps/oxlint/conformance/snapshot.md index e320a4b211212..f8464cdeb76fa 100644 --- a/apps/oxlint/conformance/snapshot.md +++ b/apps/oxlint/conformance/snapshot.md @@ -7,8 +7,8 @@ | Status | Count | % | | ----------------- | ----- | ------ | | Total rules | 292 | 100.0% | -| Fully passing | 291 | 99.7% | -| Partially passing | 1 | 0.3% | +| Fully passing | 292 | 100.0% | +| Partially passing | 0 | 0.0% | | Fully failing | 0 | 0.0% | | Load errors | 0 | 0.0% | | No tests run | 0 | 0.0% | @@ -18,8 +18,8 @@ | Status | Count | % | | ----------- | ----- | ------ | | Total tests | 33090 | 100.0% | -| Passing | 32807 | 99.1% | -| Failing | 1 | 0.0% | +| Passing | 32808 | 99.1% | +| Failing | 0 | 0.0% | | Skipped | 282 | 0.9% | ## Fully Passing Rules @@ -137,6 +137,7 @@ - `no-empty-static-block` (10 tests) - `no-empty` (35 tests) - `no-eq-null` (5 tests) +- `no-eval` (101 tests) (1 skipped) - `no-ex-assign` (8 tests) - `no-extend-native` (40 tests) - `no-extra-bind` (43 tests) @@ -318,44 +319,4 @@ ## Rules with Failures -- `no-eval` - 100 / 101 (99.0%) - -## Rules with Failures Detail - -### `no-eval` - -Pass: 99 / 101 (98.0%) -Fail: 1 / 101 (1.0%) -Skip: 1 / 101 (1.0%) - -#### no-eval > invalid - -```js -function foo() { ('use strict'); this.eval; } -``` - -```json -{ - "languageOptions": { - "ecmaVersion": 5, - "sourceType": "script" - }, - "errors": [ - { - "messageId": "unexpected", - "column": 39, - "endColumn": 43 - } - ] -} -``` - -AssertionError [ERR_ASSERTION]: Should have 1 error but had 0: [] - -0 !== 1 - - at assertErrorCountIsCorrect (apps/oxlint/dist/index.js) - at assertInvalidTestCasePasses (apps/oxlint/dist/index.js) - at runInvalidTestCase (apps/oxlint/dist/index.js) - at apps/oxlint/dist/index.js - +No rules with failures diff --git a/patches/@typescript-eslint__scope-manager.patch b/patches/@typescript-eslint__scope-manager.patch new file mode 100644 index 0000000000000..882995cc1f405 --- /dev/null +++ b/patches/@typescript-eslint__scope-manager.patch @@ -0,0 +1,31 @@ +diff --git a/dist/scope/ScopeBase.js b/dist/scope/ScopeBase.js +index 5e07a7c3fb4670b2ce4fa405798d2f27c0084fef..b90f28311dc4a464243a017a51aeffc0e7409e21 100644 +--- a/dist/scope/ScopeBase.js ++++ b/dist/scope/ScopeBase.js +@@ -59,23 +59,15 @@ function isStrictScope(scope, block, isMethodDefinition) { + return false; + } + // Search 'use strict' directive. ++ // This check has been modified from @typescript-eslint/scope-manager's original code. ++ // See: https://github.com/typescript-eslint/typescript-eslint/issues/11993 + for (const stmt of body.body) { +- if (stmt.type !== types_1.AST_NODE_TYPES.ExpressionStatement) { ++ if (stmt.type !== types_1.AST_NODE_TYPES.ExpressionStatement || stmt.directive == null) { + break; + } + if (stmt.directive === 'use strict') { + return true; + } +- const expr = stmt.expression; +- if (expr.type !== types_1.AST_NODE_TYPES.Literal) { +- break; +- } +- if (expr.raw === '"use strict"' || expr.raw === "'use strict'") { +- return true; +- } +- if (expr.value === 'use strict') { +- return true; +- } + } + return false; + } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd5e4bef67b79..564a3df6eda9c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -41,6 +41,9 @@ catalogs: version: 4.0.15 patchedDependencies: + '@typescript-eslint/scope-manager': + hash: 15e9da78cb0de614fd78a94fbaca0b199efb09049db999b533c420a2125ab6a3 + path: patches/@typescript-eslint__scope-manager.patch prettier-plugin-tailwindcss@0.7.2: hash: 85d2396832ac55f5f0187f4ba0a7b8bf22d7d117e33f75c1290670eb9a8c55af path: patches/prettier-plugin-tailwindcss@0.7.2.patch @@ -127,7 +130,7 @@ importers: version: 24.1.0 '@typescript-eslint/scope-manager': specifier: 8.53.1 - version: 8.53.1 + version: 8.53.1(patch_hash=15e9da78cb0de614fd78a94fbaca0b199efb09049db999b533c420a2125ab6a3) ajv: specifier: ^6.12.6 version: 6.12.6 @@ -7921,7 +7924,7 @@ snapshots: '@types/whatwg-mimetype@3.0.2': {} - '@typescript-eslint/scope-manager@8.53.1': + '@typescript-eslint/scope-manager@8.53.1(patch_hash=15e9da78cb0de614fd78a94fbaca0b199efb09049db999b533c420a2125ab6a3)': dependencies: '@typescript-eslint/types': 8.53.1 '@typescript-eslint/visitor-keys': 8.53.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index be533221ddbe1..4dc5fa89489ad 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -28,6 +28,7 @@ onlyBuiltDependencies: - esbuild@0.25.11 patchedDependencies: + "@typescript-eslint/scope-manager": patches/@typescript-eslint__scope-manager.patch prettier-plugin-tailwindcss@0.7.2: patches/prettier-plugin-tailwindcss@0.7.2.patch verifyDepsBeforeRun: install