mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-25 18:06:15 -04:00
Merge branch 'master' into develop
This commit is contained in:
commit
f00b1ae89b
14 changed files with 606 additions and 348 deletions
|
@ -205,6 +205,35 @@ class AttributePool {
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the data in the pool is consistent. Throws if inconsistent.
|
||||
*/
|
||||
check() {
|
||||
if (!Number.isInteger(this.nextNum)) throw new Error('nextNum property is not an integer');
|
||||
if (this.nextNum < 0) throw new Error('nextNum property is negative');
|
||||
for (const prop of ['numToAttrib', 'attribToNum']) {
|
||||
const obj = this[prop];
|
||||
if (obj == null) throw new Error(`${prop} property is null`);
|
||||
if (typeof obj !== 'object') throw new TypeError(`${prop} property is not an object`);
|
||||
const keys = Object.keys(obj);
|
||||
if (keys.length !== this.nextNum) {
|
||||
throw new Error(`${prop} size mismatch (want ${this.nextNum}, got ${keys.length})`);
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < this.nextNum; ++i) {
|
||||
const attr = this.numToAttrib[`${i}`];
|
||||
if (!Array.isArray(attr)) throw new TypeError(`attrib ${i} is not an array`);
|
||||
if (attr.length !== 2) throw new Error(`attrib ${i} is not an array of length 2`);
|
||||
const [k, v] = attr;
|
||||
if (k == null) throw new TypeError(`attrib ${i} key is null`);
|
||||
if (typeof k !== 'string') throw new TypeError(`attrib ${i} key is not a string`);
|
||||
if (v == null) throw new TypeError(`attrib ${i} value is null`);
|
||||
if (typeof v !== 'string') throw new TypeError(`attrib ${i} value is not a string`);
|
||||
const attrStr = String(attr);
|
||||
if (this.attribToNum[attrStr] !== i) throw new Error(`attribToNum for ${attrStr} !== ${i}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AttributePool;
|
||||
|
|
|
@ -380,7 +380,6 @@ exports.checkRep = (cs) => {
|
|||
const assem = exports.smartOpAssembler();
|
||||
let oldPos = 0;
|
||||
let calcNewLen = 0;
|
||||
let numInserted = 0;
|
||||
for (const o of exports.deserializeOps(ops)) {
|
||||
switch (o.opcode) {
|
||||
case '=':
|
||||
|
@ -393,25 +392,29 @@ exports.checkRep = (cs) => {
|
|||
break;
|
||||
case '+':
|
||||
{
|
||||
assert(charBank.length >= o.chars, 'Invalid changeset: not enough chars in charBank');
|
||||
const chars = charBank.slice(0, o.chars);
|
||||
const nlines = (chars.match(/\n/g) || []).length;
|
||||
assert(nlines === o.lines,
|
||||
'Invalid changeset: number of newlines in insert op does not match the charBank');
|
||||
assert(o.lines === 0 || chars.endsWith('\n'),
|
||||
'Invalid changeset: multiline insert op does not end with a newline');
|
||||
charBank = charBank.slice(o.chars);
|
||||
calcNewLen += o.chars;
|
||||
numInserted += o.chars;
|
||||
assert(calcNewLen <= newLen, `${calcNewLen} > ${newLen} in ${cs}`);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false, `Invalid changeset: Unknown opcode: ${JSON.stringify(o.opcode)}`);
|
||||
}
|
||||
assem.append(o);
|
||||
}
|
||||
|
||||
calcNewLen += oldLen - oldPos;
|
||||
charBank = charBank.substring(0, numInserted);
|
||||
while (charBank.length < numInserted) {
|
||||
charBank += '?';
|
||||
}
|
||||
|
||||
assert(calcNewLen === newLen, 'Invalid changeset: claimed length does not match actual length');
|
||||
assert(charBank === '', 'Invalid changeset: excess characters in the charBank');
|
||||
assem.endDocument();
|
||||
const normalized = exports.pack(oldLen, calcNewLen, assem.toString(), charBank);
|
||||
assert(normalized === cs, 'Invalid changeset (checkRep failed)');
|
||||
|
||||
const normalized = exports.pack(oldLen, calcNewLen, assem.toString(), unpacked.charBank);
|
||||
assert(normalized === cs, 'Invalid changeset: not in canonical form');
|
||||
return cs;
|
||||
};
|
||||
|
||||
|
@ -1059,9 +1062,7 @@ const applyZip = (in1, in2, func) => {
|
|||
exports.unpack = (cs) => {
|
||||
const headerRegex = /Z:([0-9a-z]+)([><])([0-9a-z]+)|/;
|
||||
const headerMatch = headerRegex.exec(cs);
|
||||
if ((!headerMatch) || (!headerMatch[0])) {
|
||||
error(`Not a exports: ${cs}`);
|
||||
}
|
||||
if ((!headerMatch) || (!headerMatch[0])) error(`Not a changeset: ${cs}`);
|
||||
const oldLen = exports.parseNum(headerMatch[1]);
|
||||
const changeSign = (headerMatch[2] === '>') ? 1 : -1;
|
||||
const changeMag = exports.parseNum(headerMatch[3]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue