From 013e53881b2006a04188c8b3da53b44438a0a447 Mon Sep 17 00:00:00 2001 From: Mohamed Boudra Date: Tue, 28 Apr 2026 19:16:04 +0700 Subject: [PATCH] fix(app): prevent infinite loop in @-mention scan when @ is at index 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `findActiveFileMention` walked back through `@` candidates with `lastIndexOf("@", atIndex - 1)`, but per spec a negative `position` clamps to 0 — so once `atIndex` hit 0 with an invalid query (e.g. a trailing space), the loop stepped from 0 back to 0 forever, freezing the JS thread on every keystroke and forcing a quit. Refs #596, #425 --- packages/app/src/utils/file-mention-autocomplete.test.ts | 8 ++++++++ packages/app/src/utils/file-mention-autocomplete.ts | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/app/src/utils/file-mention-autocomplete.test.ts b/packages/app/src/utils/file-mention-autocomplete.test.ts index db975a760..e5e2ec506 100644 --- a/packages/app/src/utils/file-mention-autocomplete.test.ts +++ b/packages/app/src/utils/file-mention-autocomplete.test.ts @@ -36,6 +36,14 @@ describe("findActiveFileMention", () => { }); expect(mention).toBeNull(); }); + + it("returns null when @ at start is followed by a delimiter", () => { + const mention = findActiveFileMention({ + text: "@ ", + cursorIndex: 2, + }); + expect(mention).toBeNull(); + }); }); describe("applyFileMentionReplacement", () => { diff --git a/packages/app/src/utils/file-mention-autocomplete.ts b/packages/app/src/utils/file-mention-autocomplete.ts index 21c99a9c5..748a13458 100644 --- a/packages/app/src/utils/file-mention-autocomplete.ts +++ b/packages/app/src/utils/file-mention-autocomplete.ts @@ -24,7 +24,7 @@ export function findActiveFileMention(input: FindActiveFileMentionInput): FileMe for ( let atIndex = beforeCursor.lastIndexOf("@"); atIndex >= 0; - atIndex = beforeCursor.lastIndexOf("@", atIndex - 1) + atIndex = atIndex === 0 ? -1 : beforeCursor.lastIndexOf("@", atIndex - 1) ) { const query = beforeCursor.slice(atIndex + 1); if (INVALID_MENTION_QUERY_CHARS.test(query)) {