Skip to content

perf(linter/plugins): replace ESLint step classes with plain objects#18527

Merged
overlookmotel merged 10 commits intooxc-project:mainfrom
re-taro:refactor/cfg-step1-plain-objects
Jan 26, 2026
Merged

perf(linter/plugins): replace ESLint step classes with plain objects#18527
overlookmotel merged 10 commits intooxc-project:mainfrom
re-taro:refactor/cfg-step1-plain-objects

Conversation

@re-taro
Copy link
Contributor

@re-taro re-taro commented Jan 25, 2026

Part 1 of #17232 - CFG walker optimization.

  • Remove @eslint/plugin-kit dependency (no longer needed)
  • Replace VisitNodeStep and CallMethodStep classes with plain objects
  • Merge kind and phase into a single type property:
    • 0 = enter visit
    • 1 = exit visit
    • 2 = call method (CFG event)

This reduces object creation overhead and improves memory efficiency by using simpler data structures.

Copilot AI review requested due to automatic review settings January 25, 2026 16:11
@github-actions github-actions bot added A-linter Area - Linter A-cli Area - CLI A-linter-plugins Area - Linter JS plugins C-performance Category - Solution not expected to change functional behavior, only performance labels Jan 25, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR optimizes the CFG (Control Flow Graph) walker by replacing ESLint's class-based step system with plain JavaScript objects, reducing memory overhead and object creation costs.

Changes:

  • Removed @eslint/plugin-kit dependency
  • Replaced VisitNodeStep and CallMethodStep classes with plain object types
  • Merged kind and phase properties into a single type property using numeric constants (0=enter, 1=exit, 2=call)

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.

File Description
apps/oxlint/src-js/plugins/cfg.ts Replaced class-based step objects with plain objects, consolidated step type constants, and updated all step creation/consumption logic
apps/oxlint/package.json Removed unused @eslint/plugin-kit dependency
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Member

@overlookmotel overlookmotel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for working on this. Looking good!

re-taro and others added 10 commits January 26, 2026 12:35
This is Part 1 of CFG walker optimization series addressing TODO comments
in cfg.ts.

Changes:
- Remove `@eslint/plugin-kit` dependency (no longer needed)
- Replace `VisitNodeStep` and `CallMethodStep` classes with plain objects
- Merge `kind` and `phase` into a single `type` property:
  - 0 = enter visit
  - 1 = exit visit
  - 2 = call method (CFG event)

This reduces object creation overhead and improves memory efficiency
by using simpler data structures.

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Helps TS infer `step.type` in if/else below, so can remove an `as` type assertion.
@overlookmotel overlookmotel force-pushed the refactor/cfg-step1-plain-objects branch from d53d046 to bfb1277 Compare January 26, 2026 12:47
@overlookmotel
Copy link
Member

I'm keen to get this merged ASAP as it turns out that CFG is buggy - #18555. We're going to need to alter this code to fix the bugs, and I don't want to cause merge conflicts with your PRs (especially as you've waited a long time for me to review).

So I've taken the liberty of pushing some commits to resolve my comments above, and am going to merge as soon as CI passes.

@overlookmotel overlookmotel changed the title perf(js-plugins): replace ESLint step classes with plain objects perf(linter/plugins): replace ESLint step classes with plain objects Jan 26, 2026
@overlookmotel overlookmotel merged commit 2ac7c96 into oxc-project:main Jan 26, 2026
21 checks passed
overlookmotel added a commit that referenced this pull request Jan 26, 2026
…8528)

Part 2 of #17232, continuing after #18527 - CFG walker optimization.

- Replace single `steps` array with 2 SoA (Struct of Arrays):
  - `stepTypeIds`: encoded type IDs
  - `stepData`: node or args array
- Encode step types using type ID offset:
  - Enter visits: typeId directly (0-164 for node types)
  - CFG events: typeId directly (165-171 for event types)
  - Exit visits: typeId + 256 (offset to distinguish from enter)
- Pre-compute type IDs during step preparation phase

Benefits:

- Reduces object creation overhead (no step objects needed).
- Halves the number of `NODE_TYPE_IDS_MAP` hash map lookups to convert
node types (strings) to type IDs.

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
Co-authored-by: overlookmotel <[email protected]>
@re-taro re-taro deleted the refactor/cfg-step1-plain-objects branch January 26, 2026 15:06
overlookmotel added a commit that referenced this pull request Jan 26, 2026
…rseNode (#18529)

Part 3 of #17232, continuing after #18527 and #18528 - CFG walker
optimization.

- Remove ESLint's `Traverser`
- Add lightweight `traverseNode` function that walks AST using visitor
keys
- Simplify traversal by only calling enter/leave callbacks without extra
overhead

Benefits:

- Eliminates ESLint Traverser overhead (ancestors tracking, etc.)
- Uses pre-generated visitor keys for child property lookup
- Reduces bundle size by removing unused ESLint internal module (~1.7KB
smaller)

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
Co-authored-by: overlookmotel <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area - CLI A-linter Area - Linter A-linter-plugins Area - Linter JS plugins C-performance Category - Solution not expected to change functional behavior, only performance

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments