@fluidframework/merge-tree 0.57.1 → 0.58.0-55561
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base.d.ts +0 -1
- package/dist/base.d.ts.map +1 -1
- package/dist/base.js.map +1 -1
- package/dist/client.d.ts +0 -2
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +8 -29
- package/dist/client.js.map +1 -1
- package/dist/collections.d.ts +0 -3
- package/dist/collections.d.ts.map +1 -1
- package/dist/collections.js +6 -22
- package/dist/collections.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -3
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +8 -26
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +16 -277
- package/dist/mergeTree.js.map +1 -1
- package/dist/ops.d.ts +0 -6
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +1 -8
- package/dist/ops.js.map +1 -1
- package/dist/partialLengths.d.ts.map +1 -1
- package/dist/partialLengths.js +0 -9
- package/dist/partialLengths.js.map +1 -1
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +2 -15
- package/dist/properties.js.map +1 -1
- package/dist/snapshotlegacy.d.ts.map +1 -1
- package/dist/snapshotlegacy.js +3 -6
- package/dist/snapshotlegacy.js.map +1 -1
- package/dist/textSegment.d.ts.map +1 -1
- package/dist/textSegment.js +0 -14
- package/dist/textSegment.js.map +1 -1
- package/lib/base.d.ts +0 -1
- package/lib/base.d.ts.map +1 -1
- package/lib/base.js.map +1 -1
- package/lib/client.d.ts +0 -2
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +5 -26
- package/lib/client.js.map +1 -1
- package/lib/collections.d.ts +0 -3
- package/lib/collections.d.ts.map +1 -1
- package/lib/collections.js +6 -22
- package/lib/collections.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/mergeTree.d.ts +8 -26
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +15 -274
- package/lib/mergeTree.js.map +1 -1
- package/lib/ops.d.ts +0 -6
- package/lib/ops.d.ts.map +1 -1
- package/lib/ops.js +0 -7
- package/lib/ops.js.map +1 -1
- package/lib/partialLengths.d.ts.map +1 -1
- package/lib/partialLengths.js +0 -9
- package/lib/partialLengths.js.map +1 -1
- package/lib/properties.d.ts.map +1 -1
- package/lib/properties.js +2 -15
- package/lib/properties.js.map +1 -1
- package/lib/snapshotlegacy.d.ts.map +1 -1
- package/lib/snapshotlegacy.js +3 -6
- package/lib/snapshotlegacy.js.map +1 -1
- package/lib/textSegment.d.ts.map +1 -1
- package/lib/textSegment.js +1 -15
- package/lib/textSegment.js.map +1 -1
- package/package.json +10 -10
- package/src/base.ts +0 -1
- package/src/client.ts +5 -29
- package/src/collections.ts +7 -24
- package/src/index.ts +0 -1
- package/src/mergeTree.ts +31 -306
- package/src/ops.ts +0 -7
- package/src/partialLengths.ts +0 -10
- package/src/properties.ts +7 -15
- package/src/snapshotlegacy.ts +4 -6
- package/src/textSegment.ts +2 -17
- package/dist/text.d.ts +0 -8
- package/dist/text.d.ts.map +0 -1
- package/dist/text.js +0 -78
- package/dist/text.js.map +0 -1
- package/lib/text.d.ts +0 -8
- package/lib/text.d.ts.map +0 -1
- package/lib/text.js +0 -73
- package/lib/text.js.map +0 -1
- package/src/text.ts +0 -83
package/src/mergeTree.ts
CHANGED
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
|
|
5
|
+
/* eslint-disable max-lines */
|
|
6
6
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
|
7
7
|
/* eslint-disable @typescript-eslint/consistent-type-assertions */
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
/* eslint-disable no-bitwise */
|
|
10
10
|
|
|
11
|
-
import { assert
|
|
12
|
-
import { IIntegerRange } from "./base";
|
|
11
|
+
import { assert } from "@fluidframework/common-utils";
|
|
13
12
|
import {
|
|
14
13
|
Comparer,
|
|
15
14
|
Heap,
|
|
@@ -150,12 +149,12 @@ export interface ISegment extends IMergeNodeCommon, IRemovalInfo {
|
|
|
150
149
|
}
|
|
151
150
|
|
|
152
151
|
export interface IMarkerModifiedAction {
|
|
153
|
-
|
|
152
|
+
|
|
154
153
|
(marker: Marker): void;
|
|
155
154
|
}
|
|
156
155
|
|
|
157
156
|
export interface ISegmentAction<TClientData> {
|
|
158
|
-
|
|
157
|
+
|
|
159
158
|
(segment: ISegment, pos: number, refSeq: number, clientId: number, start: number,
|
|
160
159
|
end: number, accum: TClientData): boolean;
|
|
161
160
|
}
|
|
@@ -166,7 +165,7 @@ export interface ISegmentChanges {
|
|
|
166
165
|
}
|
|
167
166
|
|
|
168
167
|
export interface BlockAction<TClientData> {
|
|
169
|
-
|
|
168
|
+
|
|
170
169
|
(
|
|
171
170
|
block: IMergeBlock,
|
|
172
171
|
pos: number,
|
|
@@ -179,7 +178,7 @@ export interface BlockAction<TClientData> {
|
|
|
179
178
|
}
|
|
180
179
|
|
|
181
180
|
export interface NodeAction<TClientData> {
|
|
182
|
-
|
|
181
|
+
|
|
183
182
|
(
|
|
184
183
|
node: IMergeNode,
|
|
185
184
|
pos: number,
|
|
@@ -259,7 +258,7 @@ export class MergeNode implements IMergeNodeCommon {
|
|
|
259
258
|
}
|
|
260
259
|
}
|
|
261
260
|
|
|
262
|
-
|
|
261
|
+
|
|
263
262
|
function addTile(tile: ReferencePosition, tiles: object) {
|
|
264
263
|
const tileLabels = tile.getTileLabels();
|
|
265
264
|
if (tileLabels) {
|
|
@@ -269,7 +268,7 @@ function addTile(tile: ReferencePosition, tiles: object) {
|
|
|
269
268
|
}
|
|
270
269
|
}
|
|
271
270
|
|
|
272
|
-
|
|
271
|
+
|
|
273
272
|
function addTileIfNotPresent(tile: ReferencePosition, tiles: object) {
|
|
274
273
|
const tileLabels = tile.getTileLabels();
|
|
275
274
|
if (tileLabels) {
|
|
@@ -282,7 +281,7 @@ function addTileIfNotPresent(tile: ReferencePosition, tiles: object) {
|
|
|
282
281
|
}
|
|
283
282
|
|
|
284
283
|
function applyStackDelta(currentStackMap: RangeStackMap, deltaStackMap: RangeStackMap) {
|
|
285
|
-
// eslint-disable-next-line guard-for-in
|
|
284
|
+
// eslint-disable-next-line guard-for-in
|
|
286
285
|
for (const label in deltaStackMap) {
|
|
287
286
|
const deltaStack = deltaStackMap[label];
|
|
288
287
|
if (!deltaStack.empty()) {
|
|
@@ -390,7 +389,6 @@ export function ordinalToArray(ord: string) {
|
|
|
390
389
|
// `MaxNodesInBlock`. (i.e., `MaxNodesInBlock` contains 1 extra slot for temporary storage to
|
|
391
390
|
// facilitate splits.)
|
|
392
391
|
export const MaxNodesInBlock = 8;
|
|
393
|
-
const traceOrdinals = false;
|
|
394
392
|
|
|
395
393
|
export class MergeBlock extends MergeNode implements IMergeBlock {
|
|
396
394
|
public children: IMergeNode[];
|
|
@@ -419,19 +417,12 @@ export class MergeBlock extends MergeNode implements IMergeBlock {
|
|
|
419
417
|
localOrdinal = prevOrdCode + ordinalWidth;
|
|
420
418
|
}
|
|
421
419
|
child.ordinal = this.ordinal + String.fromCharCode(localOrdinal);
|
|
422
|
-
if (traceOrdinals) {
|
|
423
|
-
// eslint-disable-next-line max-len
|
|
424
|
-
console.log(`so: prnt chld prev ${ordinalToArray(this.ordinal)} ${ordinalToArray(child.ordinal)} ${(index > 0) ? ordinalToArray(this.children[index - 1].ordinal) : "NA"}`);
|
|
425
|
-
}
|
|
426
420
|
assert(child.ordinal.length === (this.ordinal.length + 1), 0x041 /* "Unexpected child ordinal length!" */);
|
|
427
421
|
if (index > 0) {
|
|
428
422
|
assert(
|
|
429
423
|
child.ordinal > this.children[index - 1].ordinal,
|
|
430
424
|
0x042, /* "Child ordinal <= previous sibling ordinal!" */
|
|
431
425
|
);
|
|
432
|
-
// eslint-disable-next-line max-len
|
|
433
|
-
// console.log(`${ordinalToArray(this.ordinal)} ${ordinalToArray(child.ordinal)} ${ordinalToArray(this.children[index - 1].ordinal)}`);
|
|
434
|
-
// console.log(`ord width ${ordinalWidth}`);
|
|
435
426
|
}
|
|
436
427
|
}
|
|
437
428
|
|
|
@@ -468,7 +459,7 @@ class HierMergeBlock extends MergeBlock implements IMergeBlock {
|
|
|
468
459
|
|
|
469
460
|
public hierToString(indentCount: number) {
|
|
470
461
|
let strbuf = "";
|
|
471
|
-
// eslint-disable-next-line guard-for-in
|
|
462
|
+
// eslint-disable-next-line guard-for-in
|
|
472
463
|
for (const key in this.rangeStacks) {
|
|
473
464
|
const stack = this.rangeStacks[key];
|
|
474
465
|
strbuf += internedSpaces(indentCount);
|
|
@@ -566,7 +557,7 @@ export abstract class BaseSegment extends MergeNode implements ISegment {
|
|
|
566
557
|
return true;
|
|
567
558
|
|
|
568
559
|
case MergeTreeDeltaType.REMOVE:
|
|
569
|
-
|
|
560
|
+
|
|
570
561
|
const removalInfo: IRemovalInfo = this;
|
|
571
562
|
assert(!!removalInfo, 0x046 /* "On remove ack, missing removal info!" */);
|
|
572
563
|
assert(!!removalInfo.removedSeq, 0x047 /* "On remove ack, missing removed sequence number!" */);
|
|
@@ -575,11 +566,7 @@ export abstract class BaseSegment extends MergeNode implements ISegment {
|
|
|
575
566
|
removalInfo.removedSeq = opArgs.sequencedMessage!.sequenceNumber;
|
|
576
567
|
return true;
|
|
577
568
|
}
|
|
578
|
-
|
|
579
|
-
console.log(`grump @seq ${opArgs.sequencedMessage!.sequenceNumber} ` +
|
|
580
|
-
`cli ${glc(mergeTree, mergeTree.collabWindow.clientId)} ` +
|
|
581
|
-
`from ${removalInfo.removedSeq} text ${mergeTree.toString()}`);
|
|
582
|
-
}
|
|
569
|
+
|
|
583
570
|
return false;
|
|
584
571
|
|
|
585
572
|
default:
|
|
@@ -824,7 +811,7 @@ export class Marker extends BaseSegment implements ReferencePosition {
|
|
|
824
811
|
// Avoid circular reference when stringifying makers containing handles.
|
|
825
812
|
// (Substitute a debug string instead.)
|
|
826
813
|
const handle = !!value && value.IFluidHandle;
|
|
827
|
-
|
|
814
|
+
|
|
828
815
|
return handle
|
|
829
816
|
? `#Handle(${handle.routeContext.path}/${handle.path})`
|
|
830
817
|
: value;
|
|
@@ -889,14 +876,6 @@ export const compareNumbers = (a: number, b: number) => a - b;
|
|
|
889
876
|
|
|
890
877
|
export const compareStrings = (a: string, b: string) => a.localeCompare(b);
|
|
891
878
|
|
|
892
|
-
export function clock() {
|
|
893
|
-
return Trace.start();
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
export function elapsedMicroseconds(trace: Trace) {
|
|
897
|
-
return trace.trace().duration * 1000;
|
|
898
|
-
}
|
|
899
|
-
|
|
900
879
|
const indentStrings = ["", " ", " "];
|
|
901
880
|
export function internedSpaces(n: number) {
|
|
902
881
|
if (indentStrings[n] === undefined) {
|
|
@@ -1060,18 +1039,9 @@ export class MergeTree {
|
|
|
1060
1039
|
public static readonly options = {
|
|
1061
1040
|
incrementalUpdate: true,
|
|
1062
1041
|
insertAfterRemovedSegs: true,
|
|
1063
|
-
measureOrdinalTime: true,
|
|
1064
|
-
measureWindowTime: true,
|
|
1065
1042
|
zamboniSegments: true,
|
|
1066
1043
|
};
|
|
1067
|
-
|
|
1068
|
-
private static readonly traceZRemove = false;
|
|
1069
|
-
private static readonly traceOrdinals = false;
|
|
1070
|
-
public static readonly traceGatherText = false;
|
|
1071
|
-
private static readonly diagInsertTie = false;
|
|
1072
|
-
public static readonly diagOverlappingRemove = false;
|
|
1073
|
-
private static readonly traceTraversal = false;
|
|
1074
|
-
private static readonly traceIncrTraversal = false;
|
|
1044
|
+
|
|
1075
1045
|
private static readonly initBlockUpdateActions: BlockUpdateActions;
|
|
1076
1046
|
private static readonly theUnfinishedNode = <IMergeBlock>{ childCount: -1 };
|
|
1077
1047
|
// WARNING:
|
|
@@ -1079,11 +1049,6 @@ export class MergeTree {
|
|
|
1079
1049
|
// for property updates on markers when loading from snapshots
|
|
1080
1050
|
private static readonly blockUpdateMarkers = true;
|
|
1081
1051
|
|
|
1082
|
-
private windowTime = 0;
|
|
1083
|
-
private packTime = 0;
|
|
1084
|
-
private ordTime = 0;
|
|
1085
|
-
private maxOrdTime = 0;
|
|
1086
|
-
|
|
1087
1052
|
root: IMergeBlock;
|
|
1088
1053
|
private readonly blockUpdateActions: BlockUpdateActions = MergeTree.initBlockUpdateActions;
|
|
1089
1054
|
public readonly collabWindow = new CollaborationWindow();
|
|
@@ -1171,7 +1136,6 @@ export class MergeTree {
|
|
|
1171
1136
|
assert(!this.collabWindow.collaborating, 0x049 /* "Trying to reload from segments while collaborating!" */);
|
|
1172
1137
|
|
|
1173
1138
|
const maxChildren = MaxNodesInBlock - 1;
|
|
1174
|
-
const measureReloadTime = false;
|
|
1175
1139
|
|
|
1176
1140
|
// Starting with the leaf segments, recursively builds the B-Tree layer by layer from the bottom up.
|
|
1177
1141
|
const buildMergeBlock = (nodes: IMergeNode[]) => {
|
|
@@ -1201,26 +1165,16 @@ export class MergeTree {
|
|
|
1201
1165
|
this.blockUpdate(block);
|
|
1202
1166
|
}
|
|
1203
1167
|
|
|
1204
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
1205
1168
|
return blocks.length === 1 // If there is only one block at this layer...
|
|
1206
1169
|
? blocks[0] // ...then we're done. Return the root.
|
|
1207
1170
|
: buildMergeBlock(blocks); // ...otherwise recursively build the next layer above blocks.
|
|
1208
1171
|
};
|
|
1209
|
-
|
|
1210
|
-
let clockStart: Trace | undefined;
|
|
1211
|
-
if (measureReloadTime) {
|
|
1212
|
-
clockStart = clock();
|
|
1213
|
-
}
|
|
1214
1172
|
if (segments.length > 0) {
|
|
1215
1173
|
this.root = buildMergeBlock(segments);
|
|
1216
1174
|
this.nodeUpdateOrdinals(this.root);
|
|
1217
1175
|
} else {
|
|
1218
1176
|
this.root = this.makeBlock(0);
|
|
1219
1177
|
}
|
|
1220
|
-
|
|
1221
|
-
if (clockStart) {
|
|
1222
|
-
console.log(`reload time ${elapsedMicroseconds(clockStart)}`);
|
|
1223
|
-
}
|
|
1224
1178
|
}
|
|
1225
1179
|
/* eslint-enable max-len */
|
|
1226
1180
|
|
|
@@ -1232,15 +1186,7 @@ export class MergeTree {
|
|
|
1232
1186
|
this.collabWindow.currentSeq = currentSeq;
|
|
1233
1187
|
this.segmentsToScour = new Heap<LRUSegment>([], LRUSegmentComparer);
|
|
1234
1188
|
this.pendingSegments = ListMakeHead<SegmentGroup>();
|
|
1235
|
-
const measureFullCollab = false;
|
|
1236
|
-
let clockStart: Trace | undefined;
|
|
1237
|
-
if (measureFullCollab) {
|
|
1238
|
-
clockStart = clock();
|
|
1239
|
-
}
|
|
1240
1189
|
this.nodeUpdateLengthNewStructure(this.root, true);
|
|
1241
|
-
if (clockStart) {
|
|
1242
|
-
console.log(`update partial lengths at start ${elapsedMicroseconds(clockStart)}`);
|
|
1243
|
-
}
|
|
1244
1190
|
}
|
|
1245
1191
|
|
|
1246
1192
|
private addToLRUSet(segment: ISegment, seq: number) {
|
|
@@ -1272,11 +1218,6 @@ export class MergeTree {
|
|
|
1272
1218
|
} else if (!segment.trackingCollection.empty) {
|
|
1273
1219
|
holdNodes.push(segment);
|
|
1274
1220
|
} else {
|
|
1275
|
-
if (MergeTree.traceZRemove) {
|
|
1276
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation, max-len
|
|
1277
|
-
console.log(`${this.getLongClientId!(this.collabWindow.clientId)}: Zremove ${segment["text"]}; cli ${this.getLongClientId!(segment.clientId)}`);
|
|
1278
|
-
}
|
|
1279
|
-
|
|
1280
1221
|
// Notify maintenance event observers that the segment is being unlinked from the MergeTree
|
|
1281
1222
|
if (this.mergeTreeMaintenanceCallback) {
|
|
1282
1223
|
this.mergeTreeMaintenanceCallback({
|
|
@@ -1298,10 +1239,6 @@ export class MergeTree {
|
|
|
1298
1239
|
&& this.localNetLength(segment) > 0;
|
|
1299
1240
|
|
|
1300
1241
|
if (canAppend) {
|
|
1301
|
-
if (MergeTree.traceAppend) {
|
|
1302
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation, max-len
|
|
1303
|
-
console.log(`${this.getLongClientId!(this.collabWindow.clientId)}: append ${prevSegment!["text"]} + ${segment["text"]}; cli ${this.getLongClientId!(prevSegment!.clientId)} + cli ${this.getLongClientId!(segment.clientId)}`);
|
|
1304
|
-
}
|
|
1305
1242
|
prevSegment!.append(segment);
|
|
1306
1243
|
if (this.mergeTreeMaintenanceCallback) {
|
|
1307
1244
|
this.mergeTreeMaintenanceCallback({
|
|
@@ -1374,9 +1311,6 @@ export class MergeTree {
|
|
|
1374
1311
|
packedBlocks[nodeIndex] = packedBlock;
|
|
1375
1312
|
this.nodeUpdateLengthNewStructure(packedBlock);
|
|
1376
1313
|
}
|
|
1377
|
-
if (readCount !== totalNodeCount) {
|
|
1378
|
-
console.log(`total count ${totalNodeCount} readCount ${readCount}`);
|
|
1379
|
-
}
|
|
1380
1314
|
parent.children = packedBlocks;
|
|
1381
1315
|
for (let j = 0; j < childCount; j++) {
|
|
1382
1316
|
parent.assignChild(packedBlocks[j], j, false);
|
|
@@ -1394,10 +1328,6 @@ export class MergeTree {
|
|
|
1394
1328
|
if (!this.collabWindow.collaborating) {
|
|
1395
1329
|
return;
|
|
1396
1330
|
}
|
|
1397
|
-
let clockStart;
|
|
1398
|
-
if (MergeTree.options.measureWindowTime) {
|
|
1399
|
-
clockStart = clock();
|
|
1400
|
-
}
|
|
1401
1331
|
|
|
1402
1332
|
for (let i = 0; i < zamboniSegmentsMaxCount; i++) {
|
|
1403
1333
|
let segmentToScour = this.segmentsToScour!.peek();
|
|
@@ -1409,7 +1339,6 @@ export class MergeTree {
|
|
|
1409
1339
|
if (segmentToScour.segment!.parent && segmentToScour.segment!.parent.needsScour !== false) {
|
|
1410
1340
|
const block = segmentToScour.segment!.parent;
|
|
1411
1341
|
const childrenCopy: IMergeNode[] = [];
|
|
1412
|
-
// console.log(`scouring from ${segmentToScour.segment.seq}`);
|
|
1413
1342
|
this.scourNode(block, childrenCopy);
|
|
1414
1343
|
// This will avoid the cost of re-scouring nodes
|
|
1415
1344
|
// that have recently been scoured
|
|
@@ -1425,16 +1354,9 @@ export class MergeTree {
|
|
|
1425
1354
|
}
|
|
1426
1355
|
|
|
1427
1356
|
if (this.underflow(block) && block.parent) {
|
|
1428
|
-
|
|
1429
|
-
let packClockStart;
|
|
1430
|
-
if (MergeTree.options.measureWindowTime) {
|
|
1431
|
-
packClockStart = clock();
|
|
1432
|
-
}
|
|
1357
|
+
|
|
1433
1358
|
this.packParent(block.parent);
|
|
1434
1359
|
|
|
1435
|
-
if (MergeTree.options.measureWindowTime) {
|
|
1436
|
-
this.packTime += elapsedMicroseconds(packClockStart);
|
|
1437
|
-
}
|
|
1438
1360
|
} else {
|
|
1439
1361
|
this.nodeUpdateOrdinals(block);
|
|
1440
1362
|
this.blockUpdatePathLengths(block, UnassignedSequenceNumber, -1, true);
|
|
@@ -1442,10 +1364,6 @@ export class MergeTree {
|
|
|
1442
1364
|
}
|
|
1443
1365
|
}
|
|
1444
1366
|
}
|
|
1445
|
-
|
|
1446
|
-
if (MergeTree.options.measureWindowTime) {
|
|
1447
|
-
this.windowTime += elapsedMicroseconds(clockStart);
|
|
1448
|
-
}
|
|
1449
1367
|
}
|
|
1450
1368
|
|
|
1451
1369
|
public getCollabWindow() {
|
|
@@ -1495,74 +1413,9 @@ export class MergeTree {
|
|
|
1495
1413
|
return stats;
|
|
1496
1414
|
};
|
|
1497
1415
|
const rootStats = nodeGetStats(this.root);
|
|
1498
|
-
if (MergeTree.options.measureWindowTime) {
|
|
1499
|
-
rootStats.windowTime = this.windowTime;
|
|
1500
|
-
rootStats.packTime = this.packTime;
|
|
1501
|
-
rootStats.ordTime = this.ordTime;
|
|
1502
|
-
rootStats.maxOrdTime = this.maxOrdTime;
|
|
1503
|
-
}
|
|
1504
1416
|
return rootStats;
|
|
1505
1417
|
}
|
|
1506
1418
|
|
|
1507
|
-
public findHistorialPosition(pos: number, fromSeq: number, toSeq: number, clientId: number) {
|
|
1508
|
-
return this.findHistorialPositionFromClient(pos, fromSeq, toSeq, clientId);
|
|
1509
|
-
}
|
|
1510
|
-
|
|
1511
|
-
private findHistorialPositionFromClient(pos: number, fromSeq: number, toSeq: number, clientId: number) {
|
|
1512
|
-
assert(fromSeq < toSeq, 0x04a /* "Invalid range for historical position search!" */);
|
|
1513
|
-
if (pos < this.getLength(fromSeq, clientId)) {
|
|
1514
|
-
assert(toSeq <= this.collabWindow.currentSeq,
|
|
1515
|
-
0x04b /* "Out-of-bounds end sequence number for historical position search!" */);
|
|
1516
|
-
const segoff = this.getContainingSegment(pos, fromSeq, clientId);
|
|
1517
|
-
assert(segoff.segment !== undefined,
|
|
1518
|
-
0x04c /* "Containing segment for historical position search is undefined!" */);
|
|
1519
|
-
const toPos = this.getPosition(segoff.segment, toSeq, clientId);
|
|
1520
|
-
const ret = toPos + segoff.offset!;
|
|
1521
|
-
assert(ret !== undefined,
|
|
1522
|
-
0x04d /* "Return value for historical position search is undefined!" */);
|
|
1523
|
-
return ret;
|
|
1524
|
-
} else {
|
|
1525
|
-
return pos;
|
|
1526
|
-
}
|
|
1527
|
-
}
|
|
1528
|
-
|
|
1529
|
-
public findHistorialRangeFromClient(
|
|
1530
|
-
rangeStart: number,
|
|
1531
|
-
rangeEnd: number,
|
|
1532
|
-
fromSeq: number,
|
|
1533
|
-
toSeq: number,
|
|
1534
|
-
clientId: number,
|
|
1535
|
-
) {
|
|
1536
|
-
const ranges: IIntegerRange[] = [];
|
|
1537
|
-
const recordRange = (
|
|
1538
|
-
segment: ISegment,
|
|
1539
|
-
pos: number,
|
|
1540
|
-
refSeq: number,
|
|
1541
|
-
clientId: number,
|
|
1542
|
-
segStart: number,
|
|
1543
|
-
segEnd: number) => {
|
|
1544
|
-
let _segStart = segStart;
|
|
1545
|
-
let _segEnd = segEnd;
|
|
1546
|
-
if ((this.nodeLength(segment, toSeq, clientId) ?? 0) > 0) {
|
|
1547
|
-
const position = this.getPosition(segment, toSeq, clientId);
|
|
1548
|
-
if (_segStart < 0) {
|
|
1549
|
-
_segStart = 0;
|
|
1550
|
-
}
|
|
1551
|
-
if (_segEnd > segment.cachedLength) {
|
|
1552
|
-
_segEnd = segment.cachedLength;
|
|
1553
|
-
}
|
|
1554
|
-
ranges.push({ start: position + _segStart, end: position + _segEnd });
|
|
1555
|
-
}
|
|
1556
|
-
return true;
|
|
1557
|
-
};
|
|
1558
|
-
this.mapRange({ leaf: recordRange }, fromSeq, clientId, undefined, rangeStart, rangeEnd);
|
|
1559
|
-
return ranges;
|
|
1560
|
-
}
|
|
1561
|
-
|
|
1562
|
-
public findHistorialRange(rangeStart: number, rangeEnd: number, fromSeq: number, toSeq: number, clientId: number) {
|
|
1563
|
-
return this.findHistorialRangeFromClient(rangeStart, rangeEnd, fromSeq, toSeq, clientId);
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
1419
|
public getLength(refSeq: number, clientId: number) {
|
|
1567
1420
|
return this.blockLength(this.root, refSeq, clientId);
|
|
1568
1421
|
}
|
|
@@ -1862,16 +1715,12 @@ export class MergeTree {
|
|
|
1862
1715
|
* Assign sequence number to existing segment; update partial lengths to reflect the change
|
|
1863
1716
|
* @param seq - sequence number given by server to pending segment
|
|
1864
1717
|
*/
|
|
1865
|
-
public ackPendingSegment(opArgs: IMergeTreeDeltaOpArgs
|
|
1718
|
+
public ackPendingSegment(opArgs: IMergeTreeDeltaOpArgs) {
|
|
1866
1719
|
const seq = opArgs.sequencedMessage!.sequenceNumber;
|
|
1867
1720
|
const pendingSegmentGroup = this.pendingSegments!.dequeue();
|
|
1868
1721
|
const nodesToUpdate: IMergeBlock[] = [];
|
|
1869
1722
|
let overwrite = false;
|
|
1870
1723
|
if (pendingSegmentGroup !== undefined) {
|
|
1871
|
-
if (verboseOps) {
|
|
1872
|
-
console.log(`segment group has ${pendingSegmentGroup.segments.length} segments`);
|
|
1873
|
-
}
|
|
1874
|
-
|
|
1875
1724
|
const deltaSegments: IMergeTreeSegmentDelta[] = [];
|
|
1876
1725
|
pendingSegmentGroup.segments.map((pendingSegment) => {
|
|
1877
1726
|
overwrite = !pendingSegment.ack(pendingSegmentGroup, opArgs, this) || overwrite;
|
|
@@ -1961,13 +1810,8 @@ export class MergeTree {
|
|
|
1961
1810
|
seq: number,
|
|
1962
1811
|
opArgs: IMergeTreeDeltaOpArgs | undefined,
|
|
1963
1812
|
) {
|
|
1964
|
-
// const tt = MergeTree.traceTraversal;
|
|
1965
|
-
// MergeTree.traceTraversal = true;
|
|
1966
1813
|
this.ensureIntervalBoundary(pos, refSeq, clientId);
|
|
1967
1814
|
|
|
1968
|
-
if (MergeTree.traceOrdinals) {
|
|
1969
|
-
this.ordinalIntegrity();
|
|
1970
|
-
}
|
|
1971
1815
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1972
1816
|
|
|
1973
1817
|
this.blockInsert(pos, refSeq, clientId, seq, localSeq, segments);
|
|
@@ -1982,10 +1826,6 @@ export class MergeTree {
|
|
|
1982
1826
|
});
|
|
1983
1827
|
}
|
|
1984
1828
|
|
|
1985
|
-
// MergeTree.traceTraversal = tt;
|
|
1986
|
-
if (MergeTree.traceOrdinals) {
|
|
1987
|
-
this.ordinalIntegrity();
|
|
1988
|
-
}
|
|
1989
1829
|
if (this.collabWindow.collaborating && MergeTree.options.zamboniSegments &&
|
|
1990
1830
|
(seq !== UnassignedSequenceNumber)) {
|
|
1991
1831
|
this.zamboniSegments();
|
|
@@ -2109,7 +1949,13 @@ export class MergeTree {
|
|
|
2109
1949
|
/**
|
|
2110
1950
|
* Resolves a remote client's position against the local sequence
|
|
2111
1951
|
* and returns the remote client's position relative to the local
|
|
2112
|
-
* sequence
|
|
1952
|
+
* sequence. The client ref seq must be above the minimum sequence number
|
|
1953
|
+
* or the return value will be undefined.
|
|
1954
|
+
* Generally this method is used in conjunction with signals which provide
|
|
1955
|
+
* point in time values for the below parameters, and is useful for things
|
|
1956
|
+
* like displaying user position. It should not be used with persisted values
|
|
1957
|
+
* as persisted values will quickly become invalid as the remoteClientRefSeq
|
|
1958
|
+
* moves below the minimum sequence number
|
|
2113
1959
|
* @param remoteClientPosition - The remote client's position to resolve
|
|
2114
1960
|
* @param remoteClientRefSeq - The reference sequence number of the remote client
|
|
2115
1961
|
* @param remoteClientId - The client id of the remote client
|
|
@@ -2118,6 +1964,11 @@ export class MergeTree {
|
|
|
2118
1964
|
remoteClientPosition: number,
|
|
2119
1965
|
remoteClientRefSeq: number,
|
|
2120
1966
|
remoteClientId: number): number | undefined {
|
|
1967
|
+
|
|
1968
|
+
if(remoteClientRefSeq < this.collabWindow.minSeq){
|
|
1969
|
+
return undefined;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
2121
1972
|
const segmentInfo = this.getContainingSegment(
|
|
2122
1973
|
remoteClientPosition,
|
|
2123
1974
|
remoteClientRefSeq,
|
|
@@ -2159,10 +2010,6 @@ export class MergeTree {
|
|
|
2159
2010
|
let segIsLocal = false;
|
|
2160
2011
|
const checkSegmentIsLocal = (segment: ISegment, pos: number, refSeq: number, clientId: number) => {
|
|
2161
2012
|
if (segment.seq === UnassignedSequenceNumber) {
|
|
2162
|
-
if (MergeTree.diagInsertTie) {
|
|
2163
|
-
// eslint-disable-next-line max-len
|
|
2164
|
-
console.log(`@cli ${glc(this, this.collabWindow.clientId)}: promoting continue due to seq ${segment.seq} text ${segment.toString()} ref ${refSeq}`);
|
|
2165
|
-
}
|
|
2166
2013
|
segIsLocal = true;
|
|
2167
2014
|
}
|
|
2168
2015
|
// Only need to look at first segment that follows finished node
|
|
@@ -2172,10 +2019,6 @@ export class MergeTree {
|
|
|
2172
2019
|
const continueFrom = (node: IMergeBlock) => {
|
|
2173
2020
|
segIsLocal = false;
|
|
2174
2021
|
this.rightExcursion(node, checkSegmentIsLocal);
|
|
2175
|
-
if (MergeTree.diagInsertTie && segIsLocal) {
|
|
2176
|
-
// eslint-disable-next-line max-len
|
|
2177
|
-
console.log(`@cli ${glc(this, this.collabWindow.clientId)}: attempting continue with seq ${seq} ref ${refSeq} `);
|
|
2178
|
-
}
|
|
2179
2022
|
return segIsLocal;
|
|
2180
2023
|
};
|
|
2181
2024
|
|
|
@@ -2357,7 +2200,6 @@ export class MergeTree {
|
|
|
2357
2200
|
let child: IMergeNode;
|
|
2358
2201
|
let newNode: IMergeNode | undefined;
|
|
2359
2202
|
let fromSplit: IMergeBlock | undefined;
|
|
2360
|
-
let found = false;
|
|
2361
2203
|
for (childIndex = 0; childIndex < block.childCount; childIndex++) {
|
|
2362
2204
|
child = children[childIndex];
|
|
2363
2205
|
const len = this.nodeLength(child, refSeq, clientId);
|
|
@@ -2366,23 +2208,9 @@ export class MergeTree {
|
|
|
2366
2208
|
// will be removed, so should just be skipped for now
|
|
2367
2209
|
continue;
|
|
2368
2210
|
}
|
|
2369
|
-
if (MergeTree.traceTraversal) {
|
|
2370
|
-
let segInfo: string;
|
|
2371
|
-
if ((!child.isLeaf()) && this.collabWindow.collaborating) {
|
|
2372
|
-
segInfo = `minLength: ${child.partialLengths!.minLength}`;
|
|
2373
|
-
} else {
|
|
2374
|
-
const segment = <ISegment>child;
|
|
2375
|
-
segInfo = `cli: ${glc(this, segment.clientId)} seq: ${segment.seq} text: ${segment.toString()}`;
|
|
2376
|
-
if (segment.removedSeq !== undefined) {
|
|
2377
|
-
segInfo += ` rcli: ${glc(this, segment.removedClientId!)} rseq: ${segment.removedSeq}`;
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
console.log(`@tcli: ${glc(this, this.collabWindow.clientId)} len: ${len} pos: ${_pos} ${segInfo}`);
|
|
2381
|
-
}
|
|
2382
2211
|
|
|
2383
2212
|
if ((_pos < len) || ((_pos === len) && this.breakTie(_pos, child, seq))) {
|
|
2384
2213
|
// Found entry containing pos
|
|
2385
|
-
found = true;
|
|
2386
2214
|
if (!child.isLeaf()) {
|
|
2387
2215
|
const childBlock = child;
|
|
2388
2216
|
// Internal node
|
|
@@ -2396,10 +2224,6 @@ export class MergeTree {
|
|
|
2396
2224
|
}
|
|
2397
2225
|
return undefined;
|
|
2398
2226
|
} else if (splitNode === MergeTree.theUnfinishedNode) {
|
|
2399
|
-
if (MergeTree.traceTraversal) {
|
|
2400
|
-
// eslint-disable-next-line max-len
|
|
2401
|
-
console.log(`@cli ${glc(this, this.collabWindow.clientId)} unfinished bus pos ${_pos} len ${len}`);
|
|
2402
|
-
}
|
|
2403
2227
|
_pos -= len; // Act as if shifted segment
|
|
2404
2228
|
continue;
|
|
2405
2229
|
} else {
|
|
@@ -2408,15 +2232,9 @@ export class MergeTree {
|
|
|
2408
2232
|
childIndex++; // Insert after
|
|
2409
2233
|
}
|
|
2410
2234
|
} else {
|
|
2411
|
-
if (MergeTree.traceTraversal) {
|
|
2412
|
-
console.log(`@tcli: ${glc(this, this.collabWindow.clientId)}: leaf action`);
|
|
2413
|
-
}
|
|
2414
2235
|
const segment = child;
|
|
2415
2236
|
const segmentChanges = context.leaf(segment, _pos, context);
|
|
2416
2237
|
if (segmentChanges.replaceCurrent) {
|
|
2417
|
-
if (MergeTree.traceOrdinals) {
|
|
2418
|
-
console.log(`assign from leaf with block ord ${ordinalToArray(block.ordinal)}`);
|
|
2419
|
-
}
|
|
2420
2238
|
block.assignChild(segmentChanges.replaceCurrent, childIndex, false);
|
|
2421
2239
|
segmentChanges.replaceCurrent.ordinal = child.ordinal;
|
|
2422
2240
|
}
|
|
@@ -2436,21 +2254,12 @@ export class MergeTree {
|
|
|
2436
2254
|
_pos -= len;
|
|
2437
2255
|
}
|
|
2438
2256
|
}
|
|
2439
|
-
if (MergeTree.traceTraversal) {
|
|
2440
|
-
if ((!found) && (_pos > 0)) {
|
|
2441
|
-
// eslint-disable-next-line max-len
|
|
2442
|
-
console.log(`inserting walk fell through pos ${_pos} len: ${this.blockLength(this.root, refSeq, clientId)}`);
|
|
2443
|
-
}
|
|
2444
|
-
}
|
|
2445
2257
|
if (!newNode) {
|
|
2446
2258
|
if (_pos === 0) {
|
|
2447
2259
|
if ((seq !== UnassignedSequenceNumber) && context.continuePredicate &&
|
|
2448
2260
|
context.continuePredicate(block)) {
|
|
2449
2261
|
return MergeTree.theUnfinishedNode;
|
|
2450
2262
|
} else {
|
|
2451
|
-
if (MergeTree.traceTraversal) {
|
|
2452
|
-
console.log(`@tcli: ${glc(this, this.collabWindow.clientId)}: leaf action pos 0`);
|
|
2453
|
-
}
|
|
2454
2263
|
const segmentChanges = context.leaf(undefined, _pos, context);
|
|
2455
2264
|
newNode = segmentChanges.next;
|
|
2456
2265
|
// Assert segmentChanges.replaceCurrent === undefined
|
|
@@ -2467,9 +2276,6 @@ export class MergeTree {
|
|
|
2467
2276
|
block.setOrdinal(newNode, childIndex);
|
|
2468
2277
|
if (block.childCount < MaxNodesInBlock) {
|
|
2469
2278
|
if (fromSplit) {
|
|
2470
|
-
if (MergeTree.traceOrdinals) {
|
|
2471
|
-
console.log(`split ord ${ordinalToArray(fromSplit.ordinal)}`);
|
|
2472
|
-
}
|
|
2473
2279
|
this.nodeUpdateOrdinals(fromSplit);
|
|
2474
2280
|
}
|
|
2475
2281
|
if (context.structureChange) {
|
|
@@ -2502,44 +2308,7 @@ export class MergeTree {
|
|
|
2502
2308
|
return newNode;
|
|
2503
2309
|
}
|
|
2504
2310
|
|
|
2505
|
-
private ordinalIntegrity() {
|
|
2506
|
-
console.log("chk ordnls");
|
|
2507
|
-
this.nodeOrdinalIntegrity(this.root);
|
|
2508
|
-
}
|
|
2509
|
-
|
|
2510
|
-
private nodeOrdinalIntegrity(block: IMergeBlock) {
|
|
2511
|
-
const olen = block.ordinal.length;
|
|
2512
|
-
for (let i = 0; i < block.childCount; i++) {
|
|
2513
|
-
const child = block.children[i];
|
|
2514
|
-
if (child.ordinal) {
|
|
2515
|
-
if (olen !== (child.ordinal.length - 1)) {
|
|
2516
|
-
console.log("node integrity issue");
|
|
2517
|
-
}
|
|
2518
|
-
if (i > 0) {
|
|
2519
|
-
if (child.ordinal <= block.children[i - 1].ordinal) {
|
|
2520
|
-
console.log("node sib integrity issue");
|
|
2521
|
-
// eslint-disable-next-line max-len
|
|
2522
|
-
console.log(`??: prnt chld prev ${ordinalToArray(block.ordinal)} ${ordinalToArray(child.ordinal)} ${(i > 0) ? ordinalToArray(block.children[i - 1].ordinal) : "NA"}`);
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
if (!child.isLeaf()) {
|
|
2526
|
-
this.nodeOrdinalIntegrity(child);
|
|
2527
|
-
}
|
|
2528
|
-
} else {
|
|
2529
|
-
console.log(`node child ordinal not set ${i}`);
|
|
2530
|
-
console.log(`??: prnt ${ordinalToArray(block.ordinal)}`);
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
}
|
|
2534
|
-
|
|
2535
2311
|
private nodeUpdateOrdinals(block: IMergeBlock) {
|
|
2536
|
-
if (MergeTree.traceOrdinals) {
|
|
2537
|
-
console.log(`update ordinals for children of node with ordinal ${ordinalToArray(block.ordinal)}`);
|
|
2538
|
-
}
|
|
2539
|
-
let clockStart: Trace | undefined;
|
|
2540
|
-
if (MergeTree.options.measureOrdinalTime) {
|
|
2541
|
-
clockStart = clock();
|
|
2542
|
-
}
|
|
2543
2312
|
for (let i = 0; i < block.childCount; i++) {
|
|
2544
2313
|
const child = block.children[i];
|
|
2545
2314
|
block.setOrdinal(child, i);
|
|
@@ -2547,22 +2316,12 @@ export class MergeTree {
|
|
|
2547
2316
|
this.nodeUpdateOrdinals(child);
|
|
2548
2317
|
}
|
|
2549
2318
|
}
|
|
2550
|
-
if (clockStart) {
|
|
2551
|
-
const elapsed = elapsedMicroseconds(clockStart);
|
|
2552
|
-
if (elapsed > this.maxOrdTime) {
|
|
2553
|
-
this.maxOrdTime = elapsed;
|
|
2554
|
-
}
|
|
2555
|
-
this.ordTime += elapsed;
|
|
2556
|
-
}
|
|
2557
2319
|
}
|
|
2558
2320
|
|
|
2559
2321
|
private addOverlappingClient(removalInfo: IRemovalInfo, clientId: number) {
|
|
2560
2322
|
if (!removalInfo.removedClientOverlap) {
|
|
2561
2323
|
removalInfo.removedClientOverlap = <number[]>[];
|
|
2562
2324
|
}
|
|
2563
|
-
if (MergeTree.diagOverlappingRemove) {
|
|
2564
|
-
console.log(`added cli ${glc(this, clientId)} to rseq: ${removalInfo.removedSeq}`);
|
|
2565
|
-
}
|
|
2566
2325
|
removalInfo.removedClientOverlap.push(clientId);
|
|
2567
2326
|
}
|
|
2568
2327
|
|
|
@@ -2638,10 +2397,6 @@ export class MergeTree {
|
|
|
2638
2397
|
const markRemoved = (segment: ISegment, pos: number, start: number, end: number) => {
|
|
2639
2398
|
const removalInfo: IRemovalInfo = segment;
|
|
2640
2399
|
if (removalInfo.removedSeq !== undefined) {
|
|
2641
|
-
if (MergeTree.diagOverlappingRemove) {
|
|
2642
|
-
// eslint-disable-next-line max-len
|
|
2643
|
-
console.log(`yump @seq ${seq} cli ${glc(this, this.collabWindow.clientId)}: overlaps deleted segment ${removalInfo.removedSeq} text '${segment.toString()}'`);
|
|
2644
|
-
}
|
|
2645
2400
|
_overwrite = true;
|
|
2646
2401
|
if (removalInfo.removedSeq === UnassignedSequenceNumber) {
|
|
2647
2402
|
// replace because comes later
|
|
@@ -2675,7 +2430,6 @@ export class MergeTree {
|
|
|
2675
2430
|
this.addToLRUSet(segment, seq);
|
|
2676
2431
|
}
|
|
2677
2432
|
}
|
|
2678
|
-
// console.log(`saved local removed seg with text: ${textSegment.text}`);
|
|
2679
2433
|
}
|
|
2680
2434
|
return true;
|
|
2681
2435
|
};
|
|
@@ -2687,7 +2441,6 @@ export class MergeTree {
|
|
|
2687
2441
|
}
|
|
2688
2442
|
return true;
|
|
2689
2443
|
};
|
|
2690
|
-
// MergeTree.traceTraversal = true;
|
|
2691
2444
|
this.mapRange({ leaf: markRemoved, post: afterMarkRemoved }, refSeq, clientId, undefined, start, end);
|
|
2692
2445
|
if (savedLocalRefs.length > 0) {
|
|
2693
2446
|
const length = this.getLength(refSeq, clientId);
|
|
@@ -2736,7 +2489,6 @@ export class MergeTree {
|
|
|
2736
2489
|
this.zamboniSegments();
|
|
2737
2490
|
}
|
|
2738
2491
|
}
|
|
2739
|
-
// MergeTree.traceTraversal = false;
|
|
2740
2492
|
}
|
|
2741
2493
|
|
|
2742
2494
|
private nodeUpdateLengthNewStructure(node: IMergeBlock, recur = false) {
|
|
@@ -2917,22 +2669,12 @@ export class MergeTree {
|
|
|
2917
2669
|
if ((state.op === IncrementalExecOp.Go) && (state.childIndex < state.block.childCount)) {
|
|
2918
2670
|
const child = state.block.children[state.childIndex];
|
|
2919
2671
|
const len = this.nodeLength(child, state.refSeq, state.clientId) ?? 0;
|
|
2920
|
-
if (MergeTree.traceIncrTraversal) {
|
|
2921
|
-
if (child.isLeaf()) {
|
|
2922
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation, max-len
|
|
2923
|
-
console.log(`considering (r ${state.refSeq} c ${glc(this, state.clientId)}) seg with text ${child["text"]} len ${len} seq ${child.seq} rseq ${child.removedSeq} cli ${glc(this, child.clientId)}`);
|
|
2924
|
-
}
|
|
2925
|
-
}
|
|
2926
2672
|
if ((len > 0) && (state.start < len) && (state.end > 0)) {
|
|
2927
2673
|
if (!child.isLeaf()) {
|
|
2928
2674
|
const childState = new IncrementalMapState(child, state.actions, state.pos,
|
|
2929
2675
|
state.refSeq, state.clientId, state.context, state.start, state.end, 0);
|
|
2930
2676
|
stateStack.push(childState);
|
|
2931
2677
|
} else {
|
|
2932
|
-
if (MergeTree.traceIncrTraversal) {
|
|
2933
|
-
// eslint-disable-next-line @typescript-eslint/dot-notation
|
|
2934
|
-
console.log(`action on seg with text ${child["text"]}`);
|
|
2935
|
-
}
|
|
2936
2678
|
state.actions.leaf(child, state);
|
|
2937
2679
|
}
|
|
2938
2680
|
}
|
|
@@ -2975,20 +2717,6 @@ export class MergeTree {
|
|
|
2975
2717
|
for (let childIndex = 0; childIndex < node.childCount; childIndex++) {
|
|
2976
2718
|
const child = children[childIndex];
|
|
2977
2719
|
const len = this.nodeLength(child, refSeq, clientId) ?? 0;
|
|
2978
|
-
if (MergeTree.traceTraversal) {
|
|
2979
|
-
let segInfo: string;
|
|
2980
|
-
if ((!child.isLeaf()) && this.collabWindow.collaborating) {
|
|
2981
|
-
segInfo = `minLength: ${child.partialLengths!.minLength}`;
|
|
2982
|
-
} else {
|
|
2983
|
-
const segment = <ISegment>child;
|
|
2984
|
-
segInfo = `cli: ${glc(this, segment.clientId)} seq: ${segment.seq} text: '${segment.toString()}'`;
|
|
2985
|
-
if (segment.removedSeq !== undefined) {
|
|
2986
|
-
segInfo += ` rcli: ${glc(this, segment.removedClientId!)} rseq: ${segment.removedSeq}`;
|
|
2987
|
-
}
|
|
2988
|
-
}
|
|
2989
|
-
// eslint-disable-next-line max-len
|
|
2990
|
-
console.log(`@tcli ${glc(this, this.collabWindow.clientId)}: map len: ${len} start: ${_start} end: ${_end} ${segInfo}`);
|
|
2991
|
-
}
|
|
2992
2720
|
if (go && (_end > 0) && (len > 0) && (_start < len)) {
|
|
2993
2721
|
// Found entry containing pos
|
|
2994
2722
|
if (!child.isLeaf()) {
|
|
@@ -2996,14 +2724,11 @@ export class MergeTree {
|
|
|
2996
2724
|
go = this.nodeMap(child, actions, _pos, refSeq, clientId, accum, _start, _end);
|
|
2997
2725
|
}
|
|
2998
2726
|
} else {
|
|
2999
|
-
if (MergeTree.traceTraversal) {
|
|
3000
|
-
console.log(`@tcli ${glc(this, this.collabWindow.clientId)}: map leaf action`);
|
|
3001
|
-
}
|
|
3002
2727
|
if (actions.leaf) {
|
|
3003
|
-
|
|
2728
|
+
go = actions.leaf(child, _pos, refSeq, clientId, _start, _end, accum);
|
|
2729
|
+
}
|
|
3004
2730
|
}
|
|
3005
2731
|
}
|
|
3006
|
-
}
|
|
3007
2732
|
if (!go) {
|
|
3008
2733
|
break;
|
|
3009
2734
|
}
|