Skip to content

Commit 21bab9f

Browse files
Merge pull request #74 from mProjectsCode/copilot/fix-vim-mode-highlighting
Fix RangeError when document changes during async decoration rebuild
2 parents f245777 + c57d76a commit 21bab9f

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

src/codemirror/Cm6_ViewPlugin.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,14 @@ export function createCm6Plugin(plugin: ShikiPlugin) {
5555
* @param update
5656
*/
5757
update(update: ViewUpdate): void {
58-
this.decorations = this.decorations.map(update.changes);
58+
try {
59+
this.decorations = this.decorations.map(update.changes);
60+
} catch (e) {
61+
// Decorations may have stale positions if the document changed while an async
62+
// updateWidgets call was in flight. Reset them so the next update can rebuild.
63+
this.decorations = Decoration.none;
64+
console.warn('Resetting decorations due to error:', e);
65+
}
5966

6067
// we handle doc changes and selection changes here
6168
if (update.docChanged || update.selectionSet) {
@@ -79,6 +86,9 @@ export function createCm6Plugin(plugin: ShikiPlugin) {
7986
let lang = '';
8087
let state: SyntaxNode[] = [];
8188
const decorationUpdates: DecorationUpdate[] = [];
89+
// Capture the state at the time of the syntax tree traversal so we can
90+
// detect if the document changed while async decoration building was in flight.
91+
const capturedState = view.state;
8292

8393
// const t1 = performance.now();
8494

@@ -172,6 +182,11 @@ export function createCm6Plugin(plugin: ShikiPlugin) {
172182
this.removeDecoration(node.from, node.to);
173183
} else if (node.type === DecorationUpdateType.Insert) {
174184
const decorations = await this.buildDecorations(node.hideTo ?? node.from, node.to, node.lang, node.content);
185+
// If the document changed while we were awaiting, the positions we captured
186+
// from the syntax tree are stale. Abort to avoid applying out-of-range decorations.
187+
if (this.view.state !== capturedState) {
188+
return;
189+
}
175190
this.removeDecoration(node.from, node.to);
176191
if (node.hideLang) {
177192
// add the decoration that hides the language tag

0 commit comments

Comments
 (0)