Skip to content

Commit 51331cb

Browse files
committed
optimization: lazily-generate run text
1 parent 9b315ed commit 51331cb

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

code.js

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -718,12 +718,20 @@
718718
c.font = monospaceFont;
719719
const spaceWidth = c.measureText(' ').width;
720720
const spacesPerTab = 2;
721-
const lines = text.split(/\r\n|\r|\n/g);
721+
const parts = text.split(/(\r\n|\r|\n)/g);
722722
const unicodeWidthCache = new Map();
723+
const lines = [];
723724
let longestLineInColumns = 0;
725+
let lineStartOffset = 0;
726+
727+
for (let part = 0; part < parts.length; part++) {
728+
let raw = parts[part];
729+
if (part & 1) {
730+
// Accumulate the length of the newline (CRLF uses two code units)
731+
lineStartOffset += raw.length;
732+
continue;
733+
}
724734

725-
for (let line = 0; line < lines.length; line++) {
726-
let raw = lines[line];
727735
let runs = [];
728736
let i = 0;
729737
let n = raw.length + 1; // Add 1 for the extra character at the end
@@ -841,16 +849,13 @@
841849
startIndex, endIndex: i,
842850
startColumn, endColumn: column,
843851
isSingleChunk,
844-
text:
845-
!whitespace ? raw.slice(startIndex, i) :
846-
whitespace === 0x20 /* space */ ? '·'.repeat(i - startIndex) :
847-
whitespace === 0x0A /* newline */ ? line + 1 === lines.length ? '∅' : '↵' :
848-
'→' /* tab */,
852+
text: lineStartOffset, // The string for this run will be lazily-generated using this offset
849853
});
850854
}
851855

852-
lines[line] = { raw, runs, endIndex: i, endColumn: column };
856+
lines.push({ raw, runs, endIndex: i, endColumn: column });
853857
longestLineInColumns = Math.max(longestLineInColumns, column);
858+
lineStartOffset += raw.length;
854859
}
855860

856861
return { lines, longestLineInColumns };
@@ -1275,23 +1280,35 @@
12751280

12761281
// Draw the runs
12771282
let currentColumn = firstColumn;
1278-
for (let run = firstRun; run <= lastRun; run++) {
1279-
let { whitespace, text, startColumn, endColumn, isSingleChunk } = runs[run];
1283+
for (let i = firstRun; i <= lastRun; i++) {
1284+
const run = runs[i];
1285+
let { whitespace, text: runText, startColumn, endColumn } = run;
1286+
1287+
// Lazily-generate text for runs to improve performance. When
1288+
// this happens, the run text is the code unit offset of the
1289+
// start of the line containing this run.
1290+
if (typeof runText === 'number') {
1291+
runText = run.text =
1292+
!whitespace ? text.slice(runText + run.startIndex, runText + run.endIndex) :
1293+
whitespace === 0x20 /* space */ ? '·'.repeat(run.endIndex - run.startIndex) :
1294+
whitespace === 0x0A /* newline */ ? runText + run.startIndex === text.length ? '∅' : '↵' :
1295+
'→' /* tab */;
1296+
}
12801297

12811298
// Limit the run to the visible columns (but only for ASCII runs)
1282-
if (!isSingleChunk) {
1299+
if (!run.isSingleChunk) {
12831300
if (startColumn < currentColumn) {
1284-
text = text.slice(currentColumn - startColumn);
1301+
runText = runText.slice(currentColumn - startColumn);
12851302
startColumn = currentColumn;
12861303
}
12871304
if (endColumn > lastColumn) {
1288-
text = text.slice(0, lastColumn - startColumn);
1305+
runText = runText.slice(0, lastColumn - startColumn);
12891306
endColumn = lastColumn;
12901307
}
12911308
}
12921309

12931310
// Draw whitespace in a separate batch
1294-
(whitespace ? whitespaceBatch : textBatch).push(text, dx + startColumn * columnWidth, dy);
1311+
(whitespace ? whitespaceBatch : textBatch).push(runText, dx + startColumn * columnWidth, dy);
12951312
currentColumn = endColumn;
12961313
}
12971314
}

0 commit comments

Comments
 (0)