Skip to content

Commit 72579dd

Browse files
committed
Remove quadratic complexity of adding lots of marks to a single line
(As long as this is done in an operation.) Closes #6682
1 parent 687b6dd commit 72579dd

File tree

4 files changed

+15
-5
lines changed

4 files changed

+15
-5
lines changed

src/display/operations.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ export function startOperation(cm) {
3636
scrollLeft: null, scrollTop: null, // Intermediate scroll position, not pushed to DOM yet
3737
scrollToPos: null, // Used to scroll to a specific position
3838
focus: false,
39-
id: ++nextOpId // Unique ID
39+
id: ++nextOpId, // Unique ID
40+
markArrays: null // Used by addMarkedSpan
4041
}
4142
pushOperation(cm.curOp)
4243
}

src/line/spans.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export function getMarkedSpanFor(spans, marker) {
1818
if (span.marker == marker) return span
1919
}
2020
}
21+
2122
// Remove a span from an array, returning undefined if no spans are
2223
// left (we don't store arrays for lines without spans).
2324
export function removeMarkedSpan(spans, span) {
@@ -26,9 +27,16 @@ export function removeMarkedSpan(spans, span) {
2627
if (spans[i] != span) (r || (r = [])).push(spans[i])
2728
return r
2829
}
30+
2931
// Add a span to a line.
30-
export function addMarkedSpan(line, span) {
31-
line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]
32+
export function addMarkedSpan(line, span, op) {
33+
let inThisOp = op && window.WeakSet && (op.markedSpans || (op.markedSpans = new WeakSet))
34+
if (inThisOp && inThisOp.has(line.markedSpans)) {
35+
line.markedSpans.push(span)
36+
} else {
37+
line.markedSpans = line.markedSpans ? line.markedSpans.concat([span]) : [span]
38+
if (inThisOp) inThisOp.add(line.markedSpans)
39+
}
3240
span.marker.attachLine(line)
3341
}
3442

src/model/mark_text.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ export function markText(doc, from, to, options, type) {
187187
if (marker.collapsed && curLine != from.line) updateLineHeight(line, 0)
188188
addMarkedSpan(line, new MarkedSpan(marker,
189189
curLine == from.line ? from.ch : null,
190-
curLine == to.line ? to.ch : null))
190+
curLine == to.line ? to.ch : null), doc.cm && doc.cm.curOp)
191191
++curLine
192192
})
193193
// lineIsHidden depends on the presence of the spans, so needs a second pass

test/lint.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ var blint = require("blint");
33
["mode", "lib", "addon", "keymap"].forEach(function(dir) {
44
blint.checkDir(dir, {
55
browser: true,
6-
allowedGlobals: ["CodeMirror", "define", "test", "requirejs", "globalThis"],
6+
allowedGlobals: ["CodeMirror", "define", "test", "requirejs", "globalThis", "WeakSet"],
77
ecmaVersion: 5,
88
tabs: dir == "lib"
99
});
@@ -12,6 +12,7 @@ var blint = require("blint");
1212
["src"].forEach(function(dir) {
1313
blint.checkDir(dir, {
1414
browser: true,
15+
allowedGlobals: ["WeakSet"],
1516
ecmaVersion: 6,
1617
semicolons: false
1718
});

0 commit comments

Comments
 (0)