Skip to content

Port oxc react rules to TS and replace builtin usage#268

Closed
aidenybai wants to merge 3 commits into
mainfrom
cursor/port-oxc-react-rules-c329
Closed

Port oxc react rules to TS and replace builtin usage#268
aidenybai wants to merge 3 commits into
mainfrom
cursor/port-oxc-react-rules-c329

Conversation

@aidenybai
Copy link
Copy Markdown
Member

Summary

Ports the rules from oxc's bundled react plugin (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_RULES are now sourced from oxlint-plugin-react-doctor. react/rules-of-hooks stays 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-*.ts and has an e2e test under packages/react-doctor/tests/regressions/react-rules/ whose pass / fail vectors mirror the corresponding oxc Rust unit test in oxc/crates/oxc_linter/src/rules/react/.

Correctness (correctness/):

  • react-no-children-prop — flags the children=... prop and the equivalent React.createElement shape.
  • react-jsx-no-duplicate-props — flags identically-named props on the same JSX element (case-sensitive, matching oxc).
  • react-no-render-return-value — flags var x = ReactDOM.render(...) / return ReactDOM.render(...) / arrow-expression body.
  • react-no-is-mounted — flags this.isMounted() inside a class method or createReactClass property.
  • react-no-string-refs — flags <div ref="..." />, ref={'...'}, and this.refs.x reads inside a component body.
  • react-no-direct-mutation-state — flags this.state.foo = ... / this.state.foo++ outside the constructor of a React class component.
  • react-require-render-return — flags an empty render() body on an ES6 class component or createReactClass object property (structural approximation of oxc's CFG-based check).
  • react-jsx-key — flags missing key on JSX in .map / .flatMap / Array.from / array literals, plus key-after-{...spread} and duplicate sibling keys. Exempts React.Children.toArray(...) / Children.toArray(...).
  • react-no-unknown-property — flags class / for / kebab-cased SVG attributes / etc., plus invalid prop-on-tag combinations (crossOrigin on <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-hooks from react-hooks stays enabled to cover those.

Security (security/):

  • react-no-danger — flags dangerouslySetInnerHTML on JSX or React.createElement props (XSS-shaped).
  • react-jsx-no-script-url — flags <a href="javascript:..." /> (case-insensitive, with whitespace tolerance to match oxc's regex). The optional components config 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_RULES shrinks from 12 entries to 1 (react/rules-of-hooks only).
  • Inline note explains where the other 11 went and why rules-of-hooks stays.

packages/core/src/runners/oxlint/config.ts:

  • No structural changes — the ["react", "jsx-a11y"] plugin list and the BUILTIN_REACT_RULES spread stay so that react/rules-of-hooks keeps activating. Our 11 ported rules pick themselves up via the existing registry-driven loop (each new file lives in a bucket already wired into generate-rule-registry.mjs).

Notes / known gaps

  • oxc supports a few options on these rules (requireDataLowercase, the components list on jsx-no-script-url, etc.) that the JS plugin layer here doesn't thread through. The defaults match oxc's "no options" behavior.
  • The aria-* validation in react-no-unknown-property uses a permissive aria-<word> regex instead of oxc's curated globals list (avoids duplicating ~120 attribute names with marginal value).
  • react-rules-of-hooks is intentionally a subset of upstream behavior; pairs with the existing react-hooks-js/* (React Compiler frontend) and react/rules-of-hooks for 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.
Open in Web Open in Cursor 

…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>
@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 16, 2026

🔴 React Review0/100 (unchanged) · No new issues

Reviewed by react-review for commit 81f6897. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-doctor-website Ready Ready Preview, Comment May 16, 2026 8:03am

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants