perf(linter/plugins): replace ESLint step classes with plain objects#18527
Conversation
There was a problem hiding this comment.
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-kitdependency - Replaced
VisitNodeStepandCallMethodStepclasses with plain object types - Merged
kindandphaseproperties into a singletypeproperty 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.
2fca5ec to
d53d046
Compare
overlookmotel
left a comment
There was a problem hiding this comment.
Thanks for working on this. Looking good!
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.
d53d046 to
bfb1277
Compare
|
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. |
…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]>
…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]>
Part 1 of #17232 - CFG walker optimization.
@eslint/plugin-kitdependency (no longer needed)VisitNodeStepandCallMethodStepclasses with plain objectskindandphaseinto a singletypeproperty:This reduces object creation overhead and improves memory efficiency by using simpler data structures.