perf(grep): up to 14.5× speedup via preFilter extensions and matcher reuse (#248)
* perf(grep): extract preFilter needles from anchored alternation (^lit1|^lit2)
* perf(grep): reuse re2 matcher and add file-level preFilter fast-path
Switch all UserRegex methods to acquireMatcher(input) to avoid
per-call allocations, and propagate preFilter into searchContentMultiline
so files with no needle are skipped without scanning every line.
* fix(grep): address PR review — matchAll generator + full output assertions
- matchAll(): revert to fresh `_re2.matcher(input)`. As a generator that
suspends at yield, sharing the cached `_matcher` risks corruption if a
caller interleaves any other UserRegex method (test/exec/search/replace)
between two next() calls — acquireMatcher would reset/repoint the shared
matcher, breaking the in-progress iteration. All other synchronous
methods continue to use acquireMatcher.
- matcher.test.ts: replace two toContain assertions in the multiline
preFilter tests with full output equality (per AGENTS.md guidance), so
regressions in line numbering or group separators surface.
- grep.ts: add file-level preFilter check right after readFile — skips
searchContent (and the content.split("\n")) entirely when no needle
exists in the file. Handles countOnly correctly (emits "0\n" or
"filename:0\n" without entering the line loop).
- matcher.ts searchContentMultiline: fix preFilter early return to emit
"0\n"/"filename:0\n" in count-only mode instead of empty string.
- user-regex.ts replace() callback path: capture matcher.start(0) and
matcher.end(0) before invoking the callback — acquireMatcher mutates
charSequence in-place, so a re-entrant call would corrupt those reads.
* chore: bump patch ver with changeset
* fix(regex): use fresh matcher in replace() callback path
The callback may re-enter the same UserRegex instance, which would route
through acquireMatcher and repoint the shared matcher's charSequence,
causing the next matcher.find(pos) to advance through the wrong input.
Mirrors the matchAll() fix. H
Harry Nguyen committed
d64009aef6bc1556e7c84b22ed455863275ea953
Parent: 25262af
Committed by GitHub <noreply@github.com>
on 5/26/2026, 1:35:10 AM