- scripts/performance/corpus.json + performance:corpus (fetch-corpus.ts) pin the benchmark
repos into .performance/corpus; pnpm performance --corpus <names> selects them
- REACT_DOCTOR_OXLINT_SPAWN_LOG (off by default) makes spawn-oxlint.ts append one JSON line
per oxlint child plus parent CPU at exit; the harness turns it into a scan timeline
(procs, failed waves, sum of child durations, avg/peak concurrency, head, tail)
- --rule-timings aggregates REACT_DOCTOR_RULE_TIMINGS_DIR output into ranked rule and
selector tables; --profile merges child .cpuprofile files into top-40 function and
source-URL tables with a plugin/oxlint/gc/node split
- --compare reports a speedup ratio per target and flags diagnostics-hash mismatches;
--strict exits non-zero on a mismatch
- bash time -p fallback when GNU /usr/bin/time is missing so user/sys CPU is always recorded
Co-Authored-By: aiden@million.dev <aiden.bai05@gmail.com>
* perf: reduce cold scan startup and add V8 profiling
Add repeatable CPU and heap profiling so cold-run bottlenecks can be measured, then remove profile-proven startup, traversal, and security-scan overhead.
* perf: add deterministic stress benchmark
Exercise cold scans with reproducible diagnostics and remove redundant visitor-map allocations so regressions are measurable and behavior stays hash-verifiable.
* fix(tests): normalize benchmark paths cross-platform
Resolve the absolute fixture path through Node so the harness expectation matches Windows path semantics.
* perf: avoid effect analysis parent traversal
Reuse Oxc visitor keys with a parent-safe fallback so effect scope analysis no longer strips and restores every AST parent reference.
* perf: reduce repeated semantic traversal
Reuse host visitors and shared analysis caches to avoid redundant cold-scan AST passes while preserving diagnostic parity.
* fix: harden performance regression coverage
* fix(perf): support profiling on Node 20
* fix(plugin): skip CFGs for bodyless functions
* fix: harden profiling and semantic compatibility
Prevent benchmark artifacts and host differences from corrupting comparisons, while preserving host AST and React Compiler compatibility across optimized scan paths.
* fix(plugin): preserve rule correctness in fast scan paths
Keep security prefilters comment-tolerant and resolve React HOC wrappers by binding provenance so scan optimizations cannot hide valid diagnostics.
* fix: address review findings and consolidate duplicated code
- wrapWithSemanticContext copies the rule's visitors instead of mutating
a possibly shared object; walkAst regains its null-root guard
- no-multi-comp HOC identity accepts React-compat runtimes via
REACT_RUNTIME_MODULE_SOURCES (now incl. @wordpress/element) across
ESM, require(), and TS import-equals, with regression coverage in
both directions
- shared traversal core (forEachChildNode) replaces the walkChildren and
containsJsx copies; isImportedFromReact deduped into is-react-api-call
- performance harness consolidated (27 -> 22 files): shared commander
options, shared profile-frame accumulation, record shape guards, dead
BenchmarkSample.profileDirectory removed
- CLI-spawning harness tests skip without a built dist; dead and
tautological test assertions removed
Net -282 LOC against the branch head.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(plugin): capture the Program root for every rule
Rules can reach context.scopes through shared helpers and factories
(createDeprecatedReactImportRule resolves namespace aliases via
resolveConstIdentifierAlias), so the codegen'd requiresSemanticContext
flag — a regex over the rule's own file — silently left factory-based
rules on stub scope analyses: no-react-dom-deprecated-apis and
no-react19-deprecated-apis stopped reporting namespace usages through
the host wrapper.
Delete the flag and its regex detector entirely and install the
root-capture Program visitor on every rule. The analyses stay lazy and
memoized per Program, so rules that never read them still pay only one
call per rule per file, and no future helper-routed consumer can be
missed. Regression test runs the real host-wrapped rule and fails
against the gated wrapper.
Fixes cursor bugbot review finding on PR #1114.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix(scripts): reject cyclic heap-profile node graphs during collection
collectNodes flattened the parsed tree with no visited guard, so a
cyclic or shared-node object graph would loop before reaching the
duplicate-ID check. Unreachable through analyzeHeapProfiles (JSON.parse
output is always a strict tree), but guard and throw like the CPU
analyzer so a synthetic graph fails deterministically.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>