Skip to content

Commit db9fc99

Browse files
committed
Changeset: Avoid unnecessary StringAssembler class
1 parent aef79e7 commit db9fc99

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
@@ -731,7 +731,11 @@ class StringAssembler {
731731
/**
732732
* @returns {StringAssembler}
733733
*/
734-
exports.stringAssembler = () => new StringAssembler();
734+
exports.stringAssembler = () => {
735+
padutils.warnDeprecated(
736+
'Changeset.stringAssembler() is deprecated; build a string manually instead');
737+
return new StringAssembler();
738+
};
735739

736740
/**
737741
* @typedef {object} StringArrayLike
@@ -1158,7 +1162,7 @@ exports.applyToText = (cs, str) => {
11581162
assert(str.length === unpacked.oldLen, `mismatched apply: ${str.length} / ${unpacked.oldLen}`);
11591163
const bankIter = exports.stringIterator(unpacked.charBank);
11601164
const strIter = exports.stringIterator(str);
1161-
const assem = new StringAssembler();
1165+
let assem = '';
11621166
for (const op of exports.deserializeOps(unpacked.ops)) {
11631167
switch (op.opcode) {
11641168
case '+':
@@ -1167,7 +1171,7 @@ exports.applyToText = (cs, str) => {
11671171
if (op.lines !== bankIter.peek(op.chars).split('\n').length - 1) {
11681172
throw new Error(`newline count is wrong in op +; cs:${cs} and text:${str}`);
11691173
}
1170-
assem.append(bankIter.take(op.chars));
1174+
assem += bankIter.take(op.chars);
11711175
break;
11721176
case '-':
11731177
// op is - and op.lines 0: no newlines must be in the deleted string
@@ -1183,12 +1187,12 @@ exports.applyToText = (cs, str) => {
11831187
if (op.lines !== strIter.peek(op.chars).split('\n').length - 1) {
11841188
throw new Error(`newline count is wrong in op =; cs:${cs} and text:${str}`);
11851189
}
1186-
assem.append(strIter.take(op.chars));
1190+
assem += strIter.take(op.chars);
11871191
break;
11881192
}
11891193
}
1190-
assem.append(strIter.take(strIter.remaining()));
1191-
return assem.toString();
1194+
assem += strIter.take(strIter.remaining());
1195+
return assem;
11921196
};
11931197

11941198
/**
@@ -1477,7 +1481,7 @@ exports.compose = (cs1, cs2, pool) => {
14771481
const len3 = unpacked2.newLen;
14781482
const bankIter1 = exports.stringIterator(unpacked1.charBank);
14791483
const bankIter2 = exports.stringIterator(unpacked2.charBank);
1480-
const bankAssem = new StringAssembler();
1484+
let bankAssem = '';
14811485

14821486
const newOps = applyZip(unpacked1.ops, unpacked2.ops, (op1, op2) => {
14831487
const op1code = op1.opcode;
@@ -1487,16 +1491,12 @@ exports.compose = (cs1, cs2, pool) => {
14871491
}
14881492
const opOut = slicerZipperFunc(op1, op2, pool);
14891493
if (opOut.opcode === '+') {
1490-
if (op2code === '+') {
1491-
bankAssem.append(bankIter2.take(opOut.chars));
1492-
} else {
1493-
bankAssem.append(bankIter1.take(opOut.chars));
1494-
}
1494+
bankAssem += (op2code === '+' ? bankIter2 : bankIter1).take(opOut.chars);
14951495
}
14961496
return opOut;
14971497
});
14981498

1499-
return exports.pack(len1, len3, newOps, bankAssem.toString());
1499+
return exports.pack(len1, len3, newOps, bankAssem);
15001500
};
15011501

15021502
/**
@@ -1920,7 +1920,7 @@ class Builder {
19201920
constructor(oldLen) {
19211921
this._oldLen = oldLen;
19221922
this._ops = [];
1923-
this._charBank = new StringAssembler();
1923+
this._charBank = '';
19241924
}
19251925

19261926
/**
@@ -1966,7 +1966,7 @@ class Builder {
19661966
*/
19671967
insert(text, attribs = '', pool = null) {
19681968
this._ops.push(...opsFromText('+', text, attribs, pool));
1969-
this._charBank.append(text);
1969+
this._charBank += text;
19701970
return this;
19711971
}
19721972

@@ -1998,7 +1998,7 @@ class Builder {
19981998
oldLen: this._oldLen,
19991999
newLen: this._oldLen + lengthChange,
20002000
ops: serializedOps,
2001-
charBank: this._charBank.toString(),
2001+
charBank: this._charBank,
20022002
};
20032003
}
20042004

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

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

21892189
let lineNum = curLine + 1;
21902190
while (len < numChars) {
21912191
const nextString = linesGet(lineNum);
21922192
len += nextString.length;
2193-
assem.append(nextString);
2193+
assem += nextString;
21942194
lineNum++;
21952195
}
21962196

2197-
return assem.toString().substring(0, numChars);
2197+
return assem.substring(0, numChars);
21982198
};
21992199

22002200
const cachedStrFunc = (func) => {
@@ -2407,12 +2407,9 @@ const followAttributes = (att1, att2, pool) => {
24072407
return '';
24082408
});
24092409
// we've only removed attributes, so they're already sorted
2410-
const buf = new StringAssembler();
2411-
for (const att of atts) {
2412-
buf.append('*');
2413-
buf.append(exports.numToString(pool.putAttrib(att)));
2414-
}
2415-
return buf.toString();
2410+
let buf = '';
2411+
for (const att of atts) buf += `*${exports.numToString(pool.putAttrib(att))}`;
2412+
return buf;
24162413
};
24172414

24182415
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)