From 4fb4e3db048e9dee36bd343bf1fcbe4c71eb53f1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 08:34:51 +0000 Subject: [PATCH] perf: optimize CodeMirror decoration fields to avoid unnecessary rebuilds Co-authored-by: Horizontal42 <75383519+Horizontal42@users.noreply.github.com> --- .jules/bolt.md | 3 +++ src/ui/editor.ts | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..7bccb76 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-11-20 - [Avoid unnecessary CodeMirror rebuilds] +**Learning:** Highlight and Sparkline decorators in CodeMirror trigger `buildDecorations` on every transaction by default, which gets slow as document size increases (e.g. 50+ lines). It re-runs the lexer across the whole document on every keystroke if we do not check `tr.docChanged`/etc. +**Action:** Use `tr.docChanged` to selectively run `buildDecorations` or just use `value.map(tr.changes)` when only the text changed and results haven't been processed yet. \ No newline at end of file diff --git a/src/ui/editor.ts b/src/ui/editor.ts index 247a544..72b3166 100644 --- a/src/ui/editor.ts +++ b/src/ui/editor.ts @@ -65,8 +65,11 @@ function buildDecorations(state: EditorState): DecorationSet { const highlightField = StateField.define({ create: buildDecorations, - update(_value, tr) { - return buildDecorations(tr.state); + update(value, tr) { + const hasResults = tr.effects.some((e) => e.is(setResults)); + if (hasResults) return buildDecorations(tr.state); + if (tr.docChanged) return value.map(tr.changes); + return value; }, provide: (f) => EditorView.decorations.from(f), }); @@ -98,8 +101,9 @@ function buildVarHighlight(state: EditorState): DecorationSet { const varHighlightField = StateField.define({ create: buildVarHighlight, - update(_value, tr) { - return buildVarHighlight(tr.state); + update(value, tr) { + if (tr.docChanged || tr.selection) return buildVarHighlight(tr.state); + return value; }, provide: (f) => EditorView.decorations.from(f), });