fix(tui): prevent memory growth during repeated selector searches (#109451)

* fix(tui): bound searchable select regex cache

* fix(tui): discard stale selector regexes

Co-authored-by: wahaha1223 <0668001153@xydigit.com>

---------

Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
wahaha1223
2026-07-21 10:06:58 +08:00
committed by GitHub
parent 9db4b991b0
commit 80c16ecc80
2 changed files with 20 additions and 0 deletions
@@ -289,6 +289,24 @@ describe("SearchableSelectList", () => {
expect(output).toContain("*gpt*");
});
it("discards compiled regexes from previous searches", () => {
const queryLength = 300;
const list = new SearchableSelectList(
[{ value: "match", label: "a".repeat(queryLength) }],
5,
mockTheme,
);
for (let index = 0; index < queryLength; index += 1) {
list.handleInput("a");
list.render(queryLength + 10);
}
const regexCache = (list as unknown as { regexCache: Map<string, RegExp> }).regexCache;
expect(regexCache.size).toBe(1);
expect(list.render(queryLength + 10).join("\n")).toContain(`*${"a".repeat(queryLength)}*`);
});
it("shows no match message when filter yields no results", () => {
const list = new SearchableSelectList(testItems, 5, mockTheme);
@@ -365,6 +365,8 @@ export class SearchableSelectList implements Component {
const newValue = this.searchInput.getValue();
if (prevValue !== newValue) {
// Only current-query patterns are reusable; retaining older edits grows without bound.
this.regexCache.clear();
this.updateFilter();
}
}