2020-05-06 06:08:21 -04:00
|
|
|
/*
|
|
|
|
* decaffeinate suggestions:
|
|
|
|
* DS101: Remove unnecessary use of Array.from
|
|
|
|
* DS102: Remove unnecessary code created because of implicit returns
|
|
|
|
* DS207: Consider shorter variations of null checks
|
|
|
|
* Full docs: https://github.com/decaffeinate/decaffeinate/blob/master/docs/suggestions.md
|
|
|
|
*/
|
|
|
|
// These methods let you build a transform function from a transformComponent function
|
|
|
|
// for OT types like text and JSON in which operations are lists of components
|
|
|
|
// and transforming them requires N^2 work.
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
// Add transform and transformX functions for an OT type which has transformComponent defined.
|
|
|
|
// transformComponent(destination array, component, other component, side)
|
|
|
|
let bootstrapTransform;
|
|
|
|
exports['_bt'] = (bootstrapTransform = function(type, transformComponent, checkValidOp, append) {
|
|
|
|
let transformX;
|
|
|
|
const transformComponentX = function(left, right, destLeft, destRight) {
|
|
|
|
transformComponent(destLeft, left, right, 'left');
|
|
|
|
return transformComponent(destRight, right, left, 'right');
|
|
|
|
};
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
// Transforms rightOp by leftOp. Returns ['rightOp', clientOp']
|
|
|
|
type.transformX = (type['transformX'] = (transformX = function(leftOp, rightOp) {
|
|
|
|
checkValidOp(leftOp);
|
|
|
|
checkValidOp(rightOp);
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
const newRightOp = [];
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
for (let rightComponent of Array.from(rightOp)) {
|
|
|
|
// Generate newLeftOp by composing leftOp by rightComponent
|
|
|
|
const newLeftOp = [];
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
let k = 0;
|
|
|
|
while (k < leftOp.length) {
|
|
|
|
var l;
|
|
|
|
const nextC = [];
|
|
|
|
transformComponentX(leftOp[k], rightComponent, newLeftOp, nextC);
|
|
|
|
k++;
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
if (nextC.length === 1) {
|
|
|
|
rightComponent = nextC[0];
|
|
|
|
} else if (nextC.length === 0) {
|
|
|
|
for (l of Array.from(leftOp.slice(k))) { append(newLeftOp, l); }
|
|
|
|
rightComponent = null;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
// Recurse.
|
|
|
|
const [l_, r_] = Array.from(transformX(leftOp.slice(k), nextC));
|
|
|
|
for (l of Array.from(l_)) { append(newLeftOp, l); }
|
|
|
|
for (let r of Array.from(r_)) { append(newRightOp, r); }
|
|
|
|
rightComponent = null;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
if (rightComponent != null) { append(newRightOp, rightComponent); }
|
|
|
|
leftOp = newLeftOp;
|
|
|
|
}
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
return [leftOp, newRightOp];
|
|
|
|
}));
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
// Transforms op with specified type ('left' or 'right') by otherOp.
|
|
|
|
return type.transform = (type['transform'] = function(op, otherOp, type) {
|
|
|
|
let _;
|
|
|
|
if ((type !== 'left') && (type !== 'right')) { throw new Error("type must be 'left' or 'right'"); }
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
if (otherOp.length === 0) { return op; }
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
// TODO: Benchmark with and without this line. I _think_ it'll make a big difference...?
|
|
|
|
if ((op.length === 1) && (otherOp.length === 1)) { return transformComponent([], op[0], otherOp[0], type); }
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
if (type === 'left') {
|
|
|
|
let left;
|
|
|
|
[left, _] = Array.from(transformX(op, otherOp));
|
|
|
|
return left;
|
|
|
|
} else {
|
|
|
|
let right;
|
|
|
|
[_, right] = Array.from(transformX(otherOp, op));
|
|
|
|
return right;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2014-02-12 05:40:42 -05:00
|
|
|
|
2020-05-06 06:08:21 -04:00
|
|
|
if (typeof WEB === 'undefined') {
|
|
|
|
exports.bootstrapTransform = bootstrapTransform;
|
|
|
|
}
|