Port oxc react rules to TS and replace builtin usage#268
Closed
aidenybai wants to merge 3 commits into
Closed
Conversation
…sage Ports 11 of the 12 rules in BUILTIN_REACT_RULES from oxc's bundled `react` plugin (Rust) into our oxlint JS plugin (TypeScript), replacing the upstream rules with our own local versions: - react-no-children-prop (correctness) - react-jsx-no-duplicate-props (correctness) - react-no-danger (security) - react-jsx-no-script-url (security) - react-no-render-return-value (correctness) - react-no-is-mounted (correctness) - react-no-string-refs (correctness) - react-no-direct-mutation-state (correctness) - react-require-render-return (correctness) - react-jsx-key (correctness) - react-no-unknown-property (correctness) - react-rules-of-hooks (correctness; structural / lexical port) Each rule comes with an e2e test suite under `packages/react-doctor/tests/regressions/react-rules/` that mirrors the pass / fail vectors from the corresponding oxc Rust unit test. react/rules-of-hooks is kept active in BUILTIN_REACT_RULES (it lives in oxc's separate `react-hooks` plugin and depends on full CFG analysis we don't reproduce here). Our react-rules-of-hooks port supplements it for the common lexical violations (hooks called from helpers, in conditionals, or in loops). Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
|
🔴 React Review — 0/100 (unchanged) · No new issues Reviewed by react-review for commit 81f6897. Configure here. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports the rules from oxc's bundled
reactplugin (Rust) into our oxlint JS plugin (TypeScript), and replaces our usage of the upstream defaults with these new local rules.The 11 simpler rules in
BUILTIN_REACT_RULESare now sourced fromoxlint-plugin-react-doctor.react/rules-of-hooksstays as the upstream rule because it relies on full CFG analysis that we don't reproduce here — but a lexical / structural port (react-rules-of-hooks) is added alongside to catch the common violations.Ported rules
Each rule lands under
packages/oxlint-plugin-react-doctor/src/plugin/rules/<bucket>/react-*.tsand has an e2e test underpackages/react-doctor/tests/regressions/react-rules/whose pass / fail vectors mirror the corresponding oxc Rust unit test inoxc/crates/oxc_linter/src/rules/react/.Correctness (
correctness/):react-no-children-prop— flags thechildren=...prop and the equivalentReact.createElementshape.react-jsx-no-duplicate-props— flags identically-named props on the same JSX element (case-sensitive, matching oxc).react-no-render-return-value— flagsvar x = ReactDOM.render(...)/return ReactDOM.render(...)/ arrow-expression body.react-no-is-mounted— flagsthis.isMounted()inside a class method orcreateReactClassproperty.react-no-string-refs— flags<div ref="..." />,ref={'...'}, andthis.refs.xreads inside a component body.react-no-direct-mutation-state— flagsthis.state.foo = .../this.state.foo++outside the constructor of a React class component.react-require-render-return— flags an emptyrender()body on an ES6 class component orcreateReactClassobject property (structural approximation of oxc's CFG-based check).react-jsx-key— flags missingkeyon JSX in.map/.flatMap/Array.from/ array literals, pluskey-after-{...spread}and duplicate sibling keys. ExemptsReact.Children.toArray(...)/Children.toArray(...).react-no-unknown-property— flagsclass/for/ kebab-cased SVG attributes / etc., plus invalid prop-on-tag combinations (crossOriginon<div>). Ports the three lookup tables (ATTRIBUTE_TAGS_MAP,DOM_PROPERTIES_NAMES,DOM_ATTRIBUTES_TO_CAMEL) verbatim from oxc's Rust source.react-rules-of-hooks— structural port that catches the common lexical violations (hooks called from non-component / non-hook functions, hooks called inside conditionals / loops / try-catch, hooks called in async functions). Misses CFG-only patterns (early-return after hook, deep callback nesting);react/rules-of-hooksfromreact-hooksstays enabled to cover those.Security (
security/):react-no-danger— flagsdangerouslySetInnerHTMLon JSX orReact.createElementprops (XSS-shaped).react-jsx-no-script-url— flags<a href="javascript:..." />(case-insensitive, with whitespace tolerance to match oxc's regex). The optionalcomponentsconfig is omitted; bare<a>covers the vast majority of attack surface.Replacing the builtin usage
packages/core/src/runners/oxlint/external-plugin-rules.ts:BUILTIN_REACT_RULESshrinks from 12 entries to 1 (react/rules-of-hooksonly).rules-of-hooksstays.packages/core/src/runners/oxlint/config.ts:["react", "jsx-a11y"]plugin list and theBUILTIN_REACT_RULESspread stay so thatreact/rules-of-hookskeeps activating. Our 11 ported rules pick themselves up via the existing registry-driven loop (each new file lives in a bucket already wired intogenerate-rule-registry.mjs).Notes / known gaps
requireDataLowercase, thecomponentslist onjsx-no-script-url, etc.) that the JS plugin layer here doesn't thread through. The defaults match oxc's "no options" behavior.aria-*validation inreact-no-unknown-propertyuses a permissivearia-<word>regex instead of oxc's curated globals list (avoids duplicating ~120 attribute names with marginal value).react-rules-of-hooksis intentionally a subset of upstream behavior; pairs with the existingreact-hooks-js/*(React Compiler frontend) andreact/rules-of-hooksfor full coverage.Verification
pnpm typecheck— all 10 tasks pass.pnpm test— 95 test files / 946 tests pass. The 12 new test files (one per ported rule) are included.pnpm lint— 0 warnings, 0 errors.pnpm format:check— clean.