Skip to content

Commit eed12f0

Browse files
committed
Changeset: Avoid unnecessary StringAssembler class
1 parent 0d95036 commit eed12f0

File tree

6 files changed

+54
-83
lines changed

6 files changed

+54
-83
lines changed

src/node/utils/ExportHtml.js

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ const getHTMLFromAtext = async (pad, atext, authorColors) => {
125125
// becomes
126126
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
127127
const taker = Changeset.stringIterator(text);
128-
const assem = Changeset.stringAssembler();
128+
let assem = '';
129129
const openTags = [];
130130

131131
const getSpanClassFor = (i) => {
@@ -161,31 +161,15 @@ const getHTMLFromAtext = async (pad, atext, authorColors) => {
161161
const emitOpenTag = (i) => {
162162
openTags.unshift(i);
163163
const spanClass = getSpanClassFor(i);
164-
165-
if (spanClass) {
166-
assem.append('<span class="');
167-
assem.append(spanClass);
168-
assem.append('">');
169-
} else {
170-
assem.append('<');
171-
assem.append(tags[i]);
172-
assem.append('>');
173-
}
164+
assem += spanClass ? `<span class="${spanClass}">` : `<${tags[i]}>`;
174165
};
175166

176167
// this closes an open tag and removes its reference from openTags
177168
const emitCloseTag = (i) => {
178169
openTags.shift();
179170
const spanClass = getSpanClassFor(i);
180171
const spanWithData = isSpanWithData(i);
181-
182-
if (spanClass || spanWithData) {
183-
assem.append('</span>');
184-
} else {
185-
assem.append('</');
186-
assem.append(tags[i]);
187-
assem.append('>');
188-
}
172+
assem += spanClass || spanWithData ? '</span>' : `</${tags[i]}>`;
189173
};
190174

191175
const urls = padutils.findURLs(text);
@@ -246,7 +230,7 @@ const getHTMLFromAtext = async (pad, atext, authorColors) => {
246230
// from but they break the abiword parser and are completly useless
247231
s = s.replace(String.fromCharCode(12), '');
248232

249-
assem.append(_encodeWhitespace(Security.escapeHTML(s)));
233+
assem += _encodeWhitespace(Security.escapeHTML(s));
250234
} // end iteration over spans in line
251235

252236
// close all the tags that are open after the last op
@@ -269,14 +253,14 @@ const getHTMLFromAtext = async (pad, atext, authorColors) => {
269253
// https://html.spec.whatwg.org/multipage/links.html#link-type-noopener
270254
// https://mathiasbynens.github.io/rel-noopener/
271255
// https://github.com/ether/etherpad-lite/pull/3636
272-
assem.append(`<a href="${Security.escapeHTMLAttribute(url)}" rel="noreferrer noopener">`);
256+
assem += `<a href="${Security.escapeHTMLAttribute(url)}" rel="noreferrer noopener">`;
273257
processNextChars(urlLength);
274-
assem.append('</a>');
258+
assem += '</a>';
275259
});
276260
}
277261
processNextChars(text.length - idx);
278262

279-
return _processSpaces(assem.toString());
263+
return _processSpaces(assem);
280264
};
281265
// end getLineHTML
282266
const pieces = [css];

src/node/utils/ExportTxt.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ const getTXTFromAtext = (pad, atext, authorColors) => {
6767
// becomes
6868
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
6969
const taker = Changeset.stringIterator(text);
70-
const assem = Changeset.stringAssembler();
70+
let assem = '';
7171

7272
let idx = 0;
7373

@@ -161,7 +161,7 @@ const getTXTFromAtext = (pad, atext, authorColors) => {
161161
// plugins from being able to display * at the beginning of a line
162162
// s = s.replace("*", ""); // Then remove it
163163

164-
assem.append(s);
164+
assem += s;
165165
} // end iteration over spans in line
166166

167167
const tags2close = [];
@@ -175,7 +175,7 @@ const getTXTFromAtext = (pad, atext, authorColors) => {
175175
// end processNextChars
176176

177177
processNextChars(text.length - idx);
178-
return (assem.toString());
178+
return assem;
179179
};
180180
// end getLineHTML
181181

src/node/utils/padDiff.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,21 +328,21 @@ PadDiff.prototype._createDeletionChangeset = function (cs, startAText, apool) {
328328

329329
const nextText = (numChars) => {
330330
let len = 0;
331-
const assem = Changeset.stringAssembler();
331+
let assem = '';
332332
const firstString = linesGet(curLine).substring(curChar);
333333
len += firstString.length;
334-
assem.append(firstString);
334+
assem += firstString;
335335

336336
let lineNum = curLine + 1;
337337

338338
while (len < numChars) {
339339
const nextString = linesGet(lineNum);
340340
len += nextString.length;
341-
assem.append(nextString);
341+
assem += nextString;
342342
lineNum++;
343343
}
344344

345-
return assem.toString().substring(0, numChars);
345+
return assem.substring(0, numChars);
346346
};
347347

348348
const cachedStrFunc = (func) => {

src/static/js/Changeset.js

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -727,7 +727,11 @@ class StringAssembler {
727727
/**
728728
* @returns {StringAssembler}
729729
*/
730-
exports.stringAssembler = () => new StringAssembler();
730+
exports.stringAssembler = () => {
731+
padutils.warnWithStack(
732+
'Changeset.stringAssembler() is deprecated; build a string manually instead');
733+
return new StringAssembler();
734+
};
731735

732736
/**
733737
* @typedef {object} StringArrayLike
@@ -1156,7 +1160,7 @@ exports.applyToText = (cs, str) => {
11561160
assert(str.length === unpacked.oldLen, `mismatched apply: ${str.length} / ${unpacked.oldLen}`);
11571161
const bankIter = exports.stringIterator(unpacked.charBank);
11581162
const strIter = exports.stringIterator(str);
1159-
const assem = new StringAssembler();
1163+
let assem = '';
11601164
for (const op of exports.deserializeOps(unpacked.ops)) {
11611165
switch (op.opcode) {
11621166
case '+':
@@ -1165,7 +1169,7 @@ exports.applyToText = (cs, str) => {
11651169
if (op.lines !== bankIter.peek(op.chars).split('\n').length - 1) {
11661170
throw new Error(`newline count is wrong in op +; cs:${cs} and text:${str}`);
11671171
}
1168-
assem.append(bankIter.take(op.chars));
1172+
assem += bankIter.take(op.chars);
11691173
break;
11701174
case '-':
11711175
// op is - and op.lines 0: no newlines must be in the deleted string
@@ -1181,12 +1185,12 @@ exports.applyToText = (cs, str) => {
11811185
if (op.lines !== strIter.peek(op.chars).split('\n').length - 1) {
11821186
throw new Error(`newline count is wrong in op =; cs:${cs} and text:${str}`);
11831187
}
1184-
assem.append(strIter.take(op.chars));
1188+
assem += strIter.take(op.chars);
11851189
break;
11861190
}
11871191
}
1188-
assem.append(strIter.take(strIter.remaining()));
1189-
return assem.toString();
1192+
assem += strIter.take(strIter.remaining());
1193+
return assem;
11901194
};
11911195

11921196
/**
@@ -1475,7 +1479,7 @@ exports.compose = (cs1, cs2, pool) => {
14751479
const len3 = unpacked2.newLen;
14761480
const bankIter1 = exports.stringIterator(unpacked1.charBank);
14771481
const bankIter2 = exports.stringIterator(unpacked2.charBank);
1478-
const bankAssem = new StringAssembler();
1482+
let bankAssem = '';
14791483

14801484
const newOps = applyZip(unpacked1.ops, unpacked2.ops, (op1, op2) => {
14811485
const op1code = op1.opcode;
@@ -1485,16 +1489,12 @@ exports.compose = (cs1, cs2, pool) => {
14851489
}
14861490
const opOut = slicerZipperFunc(op1, op2, pool);
14871491
if (opOut.opcode === '+') {
1488-
if (op2code === '+') {
1489-
bankAssem.append(bankIter2.take(opOut.chars));
1490-
} else {
1491-
bankAssem.append(bankIter1.take(opOut.chars));
1492-
}
1492+
bankAssem += (op2code === '+' ? bankIter2 : bankIter1).take(opOut.chars);
14931493
}
14941494
return opOut;
14951495
});
14961496

1497-
return exports.pack(len1, len3, newOps, bankAssem.toString());
1497+
return exports.pack(len1, len3, newOps, bankAssem);
14981498
};
14991499

15001500
/**
@@ -1923,7 +1923,7 @@ class Builder {
19231923
constructor(oldLen) {
19241924
this._oldLen = oldLen;
19251925
this._ops = [];
1926-
this._charBank = new StringAssembler();
1926+
this._charBank = '';
19271927
}
19281928

19291929
/**
@@ -1969,7 +1969,7 @@ class Builder {
19691969
*/
19701970
insert(text, attribs = '', pool = null) {
19711971
this._ops.push(...opsFromText('+', text, attribs, pool));
1972-
this._charBank.append(text);
1972+
this._charBank += text;
19731973
return this;
19741974
}
19751975

@@ -2001,7 +2001,7 @@ class Builder {
20012001
oldLen: this._oldLen,
20022002
newLen: this._oldLen + lengthChange,
20032003
ops: serializedOps,
2004-
charBank: this._charBank.toString(),
2004+
charBank: this._charBank,
20052005
};
20062006
}
20072007

@@ -2184,20 +2184,20 @@ exports.inverse = (cs, lines, alines, pool) => {
21842184

21852185
const nextText = (numChars) => {
21862186
let len = 0;
2187-
const assem = new StringAssembler();
2187+
let assem = '';
21882188
const firstString = linesGet(curLine).substring(curChar);
21892189
len += firstString.length;
2190-
assem.append(firstString);
2190+
assem += firstString;
21912191

21922192
let lineNum = curLine + 1;
21932193
while (len < numChars) {
21942194
const nextString = linesGet(lineNum);
21952195
len += nextString.length;
2196-
assem.append(nextString);
2196+
assem += nextString;
21972197
lineNum++;
21982198
}
21992199

2200-
return assem.toString().substring(0, numChars);
2200+
return assem.substring(0, numChars);
22012201
};
22022202

22032203
const cachedStrFunc = (func) => {
@@ -2410,12 +2410,9 @@ const followAttributes = (att1, att2, pool) => {
24102410
return '';
24112411
});
24122412
// we've only removed attributes, so they're already sorted
2413-
const buf = new StringAssembler();
2414-
for (const att of atts) {
2415-
buf.append('*');
2416-
buf.append(exports.numToString(pool.putAttrib(att)));
2417-
}
2418-
return buf.toString();
2413+
let buf = '';
2414+
for (const att of atts) buf += `*${exports.numToString(pool.putAttrib(att))}`;
2415+
return buf;
24192416
};
24202417

24212418
exports.exportedForTestingOnly = {

src/tests/frontend/easysync-helper.js

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,29 +20,19 @@ const poolOrArray = (attribs) => {
2020
exports.poolOrArray = poolOrArray;
2121

2222
const randomInlineString = (len) => {
23-
const assem = Changeset.stringAssembler();
24-
for (let i = 0; i < len; i++) {
25-
assem.append(String.fromCharCode(randInt(26) + 97));
26-
}
27-
return assem.toString();
23+
let assem = '';
24+
for (let i = 0; i < len; i++) assem += String.fromCharCode(randInt(26) + 97);
25+
return assem;
2826
};
2927

3028
const randomMultiline = (approxMaxLines, approxMaxCols) => {
3129
const numParts = randInt(approxMaxLines * 2) + 1;
32-
const txt = Changeset.stringAssembler();
33-
txt.append(randInt(2) ? '\n' : '');
30+
let txt = '';
31+
txt += randInt(2) ? '\n' : '';
3432
for (let i = 0; i < numParts; i++) {
35-
if ((i % 2) === 0) {
36-
if (randInt(10)) {
37-
txt.append(randomInlineString(randInt(approxMaxCols) + 1));
38-
} else {
39-
txt.append('\n');
40-
}
41-
} else {
42-
txt.append('\n');
43-
}
33+
txt += i % 2 === 0 && randInt(10) ? randomInlineString(randInt(approxMaxCols) + 1) : '\n';
4434
}
45-
return txt.toString();
35+
return txt;
4636
};
4737
exports.randomMultiline = randomMultiline;
4838

@@ -165,9 +155,9 @@ const randomTwoPropAttribs = (opcode) => {
165155
};
166156

167157
const randomTestChangeset = (origText, withAttribs) => {
168-
const charBank = Changeset.stringAssembler();
158+
let charBank = '';
169159
let textLeft = origText; // always keep final newline
170-
const outTextAssem = Changeset.stringAssembler();
160+
let outTextAssem = '';
171161
const ops = [];
172162
const oldLen = origText.length;
173163

@@ -192,13 +182,13 @@ const randomTestChangeset = (origText, withAttribs) => {
192182
const o = randomStringOperation(textLeft.length);
193183
if (o.insert) {
194184
const txt = o.insert;
195-
charBank.append(txt);
196-
outTextAssem.append(txt);
185+
charBank += txt;
186+
outTextAssem += txt;
197187
appendMultilineOp('+', txt);
198188
} else if (o.skip) {
199189
const txt = textLeft.substring(0, o.skip);
200190
textLeft = textLeft.substring(o.skip);
201-
outTextAssem.append(txt);
191+
outTextAssem += txt;
202192
appendMultilineOp('=', txt);
203193
} else if (o.remove) {
204194
const txt = textLeft.substring(0, o.remove);
@@ -209,9 +199,9 @@ const randomTestChangeset = (origText, withAttribs) => {
209199

210200
while (textLeft.length > 1) doOp();
211201
for (let i = 0; i < 5; i++) doOp(); // do some more (only insertions will happen)
212-
const outText = `${outTextAssem.toString()}\n`;
202+
const outText = `${outTextAssem}\n`;
213203
const serializedOps = Changeset.serializeOps(Changeset.canonicalizeOps(ops, true));
214-
const cs = Changeset.pack(oldLen, outText.length, serializedOps, charBank.toString());
204+
const cs = Changeset.pack(oldLen, outText.length, serializedOps, charBank);
215205
Changeset.checkRep(cs);
216206
return [cs, outText];
217207
};

src/tests/frontend/specs/easysync-mutations.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('easysync-mutations', function () {
1515
};
1616

1717
const mutationsToChangeset = (oldLen, arrayOfArrays) => {
18-
const bank = Changeset.stringAssembler();
18+
let bank = '';
1919
let oldPos = 0;
2020
let newLen = 0;
2121
const ops = (function* () {
@@ -34,7 +34,7 @@ describe('easysync-mutations', function () {
3434
oldPos += op.chars;
3535
} else if (a[0] === 'insert') {
3636
op.opcode = '+';
37-
bank.append(a[1]);
37+
bank += a[1];
3838
op.chars = a[1].length;
3939
op.lines = (a[2] || 0);
4040
newLen += op.chars;
@@ -44,7 +44,7 @@ describe('easysync-mutations', function () {
4444
})();
4545
const serializedOps = Changeset.serializeOps(Changeset.canonicalizeOps(ops, true));
4646
newLen += oldLen - oldPos;
47-
return Changeset.pack(oldLen, newLen, serializedOps, bank.toString());
47+
return Changeset.pack(oldLen, newLen, serializedOps, bank);
4848
};
4949

5050
const runMutationTest = (testId, origLines, muts, correct) => {

0 commit comments

Comments
 (0)