From 5b64017b2e2ddd4d2462ce9a90e1db577ef789bd Mon Sep 17 00:00:00 2001 From: ionfwsrijan Date: Sun, 21 Jun 2026 12:53:59 +0530 Subject: [PATCH] fix(core): cap ChordMatcher buffer to prevent unbounded growth The buffer grew on each partial chord match with no upper limit. If a user typed keys matching a chord prefix indefinitely, the buffer would grow unbounded. Added maxBufferSize (default 10) that resets the buffer when exceeded. --- packages/core/src/input/ChordMatcher.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/core/src/input/ChordMatcher.ts b/packages/core/src/input/ChordMatcher.ts index 0e026879..a35dacdb 100644 --- a/packages/core/src/input/ChordMatcher.ts +++ b/packages/core/src/input/ChordMatcher.ts @@ -11,6 +11,7 @@ export interface Chord { export interface ChordMatcherOptions { timeoutMs?: number; + maxBufferSize?: number; } function getKeyEventToken(event: KeyEvent): string { @@ -27,10 +28,12 @@ export class ChordMatcher { private _nextId = 0; private _buffer: string[] = []; private _timeoutMs: number; + private _maxBufferSize: number; private _timer: ReturnType | null = null; constructor(opts?: ChordMatcherOptions) { this._timeoutMs = opts?.timeoutMs ?? 800; + this._maxBufferSize = opts?.maxBufferSize ?? 10; } bind(keys: string[], handler: () => void): () => void { @@ -49,6 +52,12 @@ export class ChordMatcher { const token = getKeyEventToken(event); let candidate = [...this._buffer, token]; + + if (candidate.length > this._maxBufferSize) { + this._buffer = []; + candidate = [token]; + } + let matchingBindings = this._getMatchingBindings(candidate); if (matchingBindings.length === 0) {