Tiny optimization to CFG visitor. Bitwise OR is slightly cheaper than subtraction, and also gives V8 a guaranteed type (`i32` aka SMI) for the value being put into the array.
Fix a mistake in our (internal) types: `walkProgramWithCfg` was missing that elements can be `CfgVisitFn`.
Also refactor the types for `walkProgram`, importing the original `VisitFn` and `EnterExit` types from where they're defined.
Pure refactor. Replace `typeAssertIs` with debug assertions. Both perform the same type assertion, but difference is that the debug assertion actually checks that the type is correct at runtime in debug build.
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 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
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.
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
Implement CFG (or "code path analysis" as ESLint calls it).
This is the was the last remaining gap in our API.
The implementation is pretty slow, I imagine. I've pulled in ESLint's code for the actual control flow graph construction, and copied ESLint's code for the rest.
Fitting with how we combine enter and exit nodes for leaf nodes (`Identifier`s etc) required skipping creating "steps" for exiting leaf nodes, which should also be a perf gain, as they're so common. But that apart, I've made no effort to optimize it. There's plenty of scope for improving it. I've added comments with some starting points for doing that, and will open an issue in the hope someone would like to pick up on that.
I also cannot for the life of me figure out how to add the CFG event handlers (`onCodePathStart` etc) to `VisitorObject` type, without breaking everything. Me and Claude went at it for about an hour, and got nowhere. So I'm just leaving that for now.