[compiler] Handle empty list of eslint suppression rules (#34323)

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/34323).
* #34276
* __->__ #34323
This commit is contained in:
Joseph Savona 2025-09-08 10:33:10 -07:00 committed by GitHub
parent 294c33f34d
commit 3f2a42a5de
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 92 additions and 8 deletions

View File

@ -135,7 +135,12 @@ export type PluginOptions = {
*/
eslintSuppressionRules: Array<string> | null | undefined;
/**
* Whether to report "suppression" errors for Flow suppressions. If false, suppression errors
* are only emitted for ESLint suppressions
*/
flowSuppressions: boolean;
/*
* Ignore 'use no forget' annotations. Helpful during testing but should not be used in production.
*/

View File

@ -86,12 +86,18 @@ export function findProgramSuppressions(
let enableComment: t.Comment | null = null;
let source: SuppressionSource | null = null;
const rulePattern = `(${ruleNames.join('|')})`;
const disableNextLinePattern = new RegExp(
`eslint-disable-next-line ${rulePattern}`,
);
const disablePattern = new RegExp(`eslint-disable ${rulePattern}`);
const enablePattern = new RegExp(`eslint-enable ${rulePattern}`);
let disableNextLinePattern: RegExp | null = null;
let disablePattern: RegExp | null = null;
let enablePattern: RegExp | null = null;
if (ruleNames.length !== 0) {
const rulePattern = `(${ruleNames.join('|')})`;
disableNextLinePattern = new RegExp(
`eslint-disable-next-line ${rulePattern}`,
);
disablePattern = new RegExp(`eslint-disable ${rulePattern}`);
enablePattern = new RegExp(`eslint-enable ${rulePattern}`);
}
const flowSuppressionPattern = new RegExp(
'\\$(FlowFixMe\\w*|FlowExpectedError|FlowIssue)\\[react\\-rule',
);
@ -107,6 +113,7 @@ export function findProgramSuppressions(
* CommentLine within the block.
*/
disableComment == null &&
disableNextLinePattern != null &&
disableNextLinePattern.test(comment.value)
) {
disableComment = comment;
@ -124,12 +131,16 @@ export function findProgramSuppressions(
source = 'Flow';
}
if (disablePattern.test(comment.value)) {
if (disablePattern != null && disablePattern.test(comment.value)) {
disableComment = comment;
source = 'Eslint';
}
if (enablePattern.test(comment.value) && source === 'Eslint') {
if (
enablePattern != null &&
enablePattern.test(comment.value) &&
source === 'Eslint'
) {
enableComment = comment;
}

View File

@ -0,0 +1,53 @@
## Input
```javascript
// @eslintSuppressionRules:[]
// The suppression here shouldn't cause compilation to get skipped
// Previously we had a bug where an empty list of suppressions would
// create a regexp that matched any suppression
function Component(props) {
'use forget';
// eslint-disable-next-line foo/not-react-related
return <div>{props.text}</div>;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{text: 'Hello'}],
};
```
## Code
```javascript
import { c as _c } from "react/compiler-runtime"; // @eslintSuppressionRules:[]
// The suppression here shouldn't cause compilation to get skipped
// Previously we had a bug where an empty list of suppressions would
// create a regexp that matched any suppression
function Component(props) {
"use forget";
const $ = _c(2);
let t0;
if ($[0] !== props.text) {
t0 = <div>{props.text}</div>;
$[0] = props.text;
$[1] = t0;
} else {
t0 = $[1];
}
return t0;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{ text: "Hello" }],
};
```
### Eval output
(kind: ok) <div>Hello</div>

View File

@ -0,0 +1,15 @@
// @eslintSuppressionRules:[]
// The suppression here shouldn't cause compilation to get skipped
// Previously we had a bug where an empty list of suppressions would
// create a regexp that matched any suppression
function Component(props) {
'use forget';
// eslint-disable-next-line foo/not-react-related
return <div>{props.text}</div>;
}
export const FIXTURE_ENTRYPOINT = {
fn: Component,
params: [{text: 'Hello'}],
};