Stop the clipboard picker freezing on huge pastes (#6568)

Every keystroke in the search box scanned, lowercased, and split the
full text of every history entry, and the preview pane laid out the
entire selection with WrapAnywhere. A single 1.6MB paste (or a large
file selection) turned that into hundreds of megabytes of work on the
shell thread and stalled the render thread — freezing the whole
desktop.

Cap each entry once as it enters the display, so searching, previewing,
and rendering all work on a bounded prefix. Pasting reads the full entry
back from history by index, so nothing is actually lost. The cut lands
on a line break, keeping a file:// URI from truncating into a bogus path.

Co-authored-by: markbusking <marcosbustos.dev@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
markbus-ai
2026-08-09 14:01:37 +02:00
committed by GitHub
co-authored by markbusking Claude Opus 5
parent dd61d4a75b
commit c4dda58ba2
2 changed files with 41 additions and 1 deletions
+26
View File
@@ -179,6 +179,32 @@ assertEqual(
2,
'clipboard respawns both watchers when they die'
)
assertDeepEqual(
clipboard.displayRows([{ type: 'text', text: 'a'.repeat(8192) + 'needle' }], 'needle', 50),
[],
'clipboard display rows do not search text past the cap'
)
assertDeepEqual(
clipboard.displayRows([{ type: 'text', text: 'needle' + 'a'.repeat(100000) }], 'needle', 50).map(row => row.index),
[0],
'clipboard display rows search text up to the cap'
)
const hugeTextRow = clipboard.displayRows([{ type: 'text', text: 'z'.repeat(100000) }], '', 50)[0]
assert(
hugeTextRow.fullText.length === 8192 && hugeTextRow.previewText.length === 8192,
'clipboard display rows cap what a huge text entry renders'
)
const hugeFileList = []
for (let i = 0; i < 5000; i++) hugeFileList.push('file:///home/dhh/clip-' + i + '.mp4')
const hugeFileRow = clipboard.displayRows([{ type: 'text', text: hugeFileList.join('\n') + '\n' }], '', 50)[0]
assert(
hugeFileRow.entryType === 'file' && hugeFileRow.fullText.split('\n').every(path => path.endsWith('.mp4')),
'clipboard display rows cap a huge file list without truncating a path'
)
JS
TMPDIR=$(mktemp -d)