@fluidframework/merge-tree 0.57.0 → 0.58.0-55983

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.
Files changed (123) hide show
  1. package/dist/base.d.ts +0 -1
  2. package/dist/base.d.ts.map +1 -1
  3. package/dist/base.js.map +1 -1
  4. package/dist/client.d.ts +3 -5
  5. package/dist/client.d.ts.map +1 -1
  6. package/dist/client.js +14 -36
  7. package/dist/client.js.map +1 -1
  8. package/dist/collections.d.ts +1 -4
  9. package/dist/collections.d.ts.map +1 -1
  10. package/dist/collections.js +8 -24
  11. package/dist/collections.js.map +1 -1
  12. package/dist/index.d.ts +0 -1
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +0 -3
  15. package/dist/index.js.map +1 -1
  16. package/dist/mergeTree.d.ts +8 -30
  17. package/dist/mergeTree.d.ts.map +1 -1
  18. package/dist/mergeTree.js +17 -326
  19. package/dist/mergeTree.js.map +1 -1
  20. package/dist/mergeTreeDeltaCallback.d.ts.map +1 -1
  21. package/dist/mergeTreeDeltaCallback.js.map +1 -1
  22. package/dist/ops.d.ts +0 -6
  23. package/dist/ops.d.ts.map +1 -1
  24. package/dist/ops.js +1 -8
  25. package/dist/ops.js.map +1 -1
  26. package/dist/partialLengths.d.ts.map +1 -1
  27. package/dist/partialLengths.js +14 -26
  28. package/dist/partialLengths.js.map +1 -1
  29. package/dist/properties.d.ts.map +1 -1
  30. package/dist/properties.js +2 -15
  31. package/dist/properties.js.map +1 -1
  32. package/dist/segmentPropertiesManager.js +1 -5
  33. package/dist/segmentPropertiesManager.js.map +1 -1
  34. package/dist/snapshotChunks.js +3 -3
  35. package/dist/snapshotChunks.js.map +1 -1
  36. package/dist/snapshotV1.d.ts +2 -1
  37. package/dist/snapshotV1.d.ts.map +1 -1
  38. package/dist/snapshotV1.js +4 -4
  39. package/dist/snapshotV1.js.map +1 -1
  40. package/dist/snapshotlegacy.d.ts.map +1 -1
  41. package/dist/snapshotlegacy.js +3 -6
  42. package/dist/snapshotlegacy.js.map +1 -1
  43. package/dist/sortedSegmentSet.d.ts +3 -3
  44. package/dist/sortedSegmentSet.d.ts.map +1 -1
  45. package/dist/sortedSegmentSet.js +12 -12
  46. package/dist/sortedSegmentSet.js.map +1 -1
  47. package/dist/textSegment.d.ts.map +1 -1
  48. package/dist/textSegment.js +3 -17
  49. package/dist/textSegment.js.map +1 -1
  50. package/lib/base.d.ts +0 -1
  51. package/lib/base.d.ts.map +1 -1
  52. package/lib/base.js.map +1 -1
  53. package/lib/client.d.ts +3 -5
  54. package/lib/client.d.ts.map +1 -1
  55. package/lib/client.js +11 -33
  56. package/lib/client.js.map +1 -1
  57. package/lib/collections.d.ts +1 -4
  58. package/lib/collections.d.ts.map +1 -1
  59. package/lib/collections.js +8 -24
  60. package/lib/collections.js.map +1 -1
  61. package/lib/index.d.ts +0 -1
  62. package/lib/index.d.ts.map +1 -1
  63. package/lib/index.js +0 -1
  64. package/lib/index.js.map +1 -1
  65. package/lib/mergeTree.d.ts +8 -30
  66. package/lib/mergeTree.d.ts.map +1 -1
  67. package/lib/mergeTree.js +16 -322
  68. package/lib/mergeTree.js.map +1 -1
  69. package/lib/mergeTreeDeltaCallback.d.ts.map +1 -1
  70. package/lib/mergeTreeDeltaCallback.js.map +1 -1
  71. package/lib/ops.d.ts +0 -6
  72. package/lib/ops.d.ts.map +1 -1
  73. package/lib/ops.js +0 -7
  74. package/lib/ops.js.map +1 -1
  75. package/lib/partialLengths.d.ts.map +1 -1
  76. package/lib/partialLengths.js +14 -26
  77. package/lib/partialLengths.js.map +1 -1
  78. package/lib/properties.d.ts.map +1 -1
  79. package/lib/properties.js +2 -15
  80. package/lib/properties.js.map +1 -1
  81. package/lib/segmentPropertiesManager.js +1 -5
  82. package/lib/segmentPropertiesManager.js.map +1 -1
  83. package/lib/snapshotChunks.js +3 -3
  84. package/lib/snapshotChunks.js.map +1 -1
  85. package/lib/snapshotV1.d.ts +2 -1
  86. package/lib/snapshotV1.d.ts.map +1 -1
  87. package/lib/snapshotV1.js +4 -4
  88. package/lib/snapshotV1.js.map +1 -1
  89. package/lib/snapshotlegacy.d.ts.map +1 -1
  90. package/lib/snapshotlegacy.js +3 -6
  91. package/lib/snapshotlegacy.js.map +1 -1
  92. package/lib/sortedSegmentSet.d.ts +3 -3
  93. package/lib/sortedSegmentSet.d.ts.map +1 -1
  94. package/lib/sortedSegmentSet.js +12 -12
  95. package/lib/sortedSegmentSet.js.map +1 -1
  96. package/lib/textSegment.d.ts.map +1 -1
  97. package/lib/textSegment.js +4 -18
  98. package/lib/textSegment.js.map +1 -1
  99. package/package.json +11 -11
  100. package/src/base.ts +2 -3
  101. package/src/client.ts +11 -36
  102. package/src/collections.ts +9 -26
  103. package/src/index.ts +0 -1
  104. package/src/mergeTree.ts +32 -357
  105. package/src/mergeTreeDeltaCallback.ts +0 -1
  106. package/src/ops.ts +0 -7
  107. package/src/partialLengths.ts +17 -27
  108. package/src/properties.ts +7 -15
  109. package/src/segmentPropertiesManager.ts +5 -5
  110. package/src/snapshotChunks.ts +3 -3
  111. package/src/snapshotV1.ts +3 -3
  112. package/src/snapshotlegacy.ts +4 -6
  113. package/src/sortedSegmentSet.ts +12 -12
  114. package/src/textSegment.ts +5 -20
  115. package/dist/text.d.ts +0 -8
  116. package/dist/text.d.ts.map +0 -1
  117. package/dist/text.js +0 -78
  118. package/dist/text.js.map +0 -1
  119. package/lib/text.d.ts +0 -8
  120. package/lib/text.d.ts.map +0 -1
  121. package/lib/text.js +0 -73
  122. package/lib/text.js.map +0 -1
  123. 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
- /* eslint-disable @typescript-eslint/no-shadow */
8
+
9
9
  /* eslint-disable no-bitwise */
10
10
 
11
- import { assert, Trace } from "@fluidframework/common-utils";
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
- // eslint-disable-next-line @typescript-eslint/prefer-function-type
152
+
154
153
  (marker: Marker): void;
155
154
  }
156
155
 
157
156
  export interface ISegmentAction<TClientData> {
158
- // eslint-disable-next-line @typescript-eslint/prefer-function-type
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
- // eslint-disable-next-line @typescript-eslint/prefer-function-type
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
- // eslint-disable-next-line @typescript-eslint/prefer-function-type
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
- // eslint-disable-next-line @typescript-eslint/ban-types
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
- // eslint-disable-next-line @typescript-eslint/ban-types
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, no-restricted-syntax
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, no-restricted-syntax
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
- // eslint-disable-next-line @typescript-eslint/no-this-alias
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
- if (MergeTree.diagOverlappingRemove) {
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
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
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) {
@@ -933,14 +912,6 @@ const LRUSegmentComparer: Comparer<LRUSegment> = {
933
912
  compare: (a, b) => a.maxSeq - b.maxSeq,
934
913
  };
935
914
 
936
- export function glc(mergeTree: MergeTree, id: number) {
937
- if (mergeTree.getLongClientId) {
938
- return mergeTree.getLongClientId(id);
939
- } else {
940
- return id.toString();
941
- }
942
- }
943
-
944
915
  export interface SegmentAccumulator {
945
916
  segments: ISegment[];
946
917
  }
@@ -1060,18 +1031,9 @@ export class MergeTree {
1060
1031
  public static readonly options = {
1061
1032
  incrementalUpdate: true,
1062
1033
  insertAfterRemovedSegs: true,
1063
- measureOrdinalTime: true,
1064
- measureWindowTime: true,
1065
1034
  zamboniSegments: true,
1066
1035
  };
1067
- private static readonly traceAppend = false;
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;
1036
+
1075
1037
  private static readonly initBlockUpdateActions: BlockUpdateActions;
1076
1038
  private static readonly theUnfinishedNode = <IMergeBlock>{ childCount: -1 };
1077
1039
  // WARNING:
@@ -1079,11 +1041,6 @@ export class MergeTree {
1079
1041
  // for property updates on markers when loading from snapshots
1080
1042
  private static readonly blockUpdateMarkers = true;
1081
1043
 
1082
- private windowTime = 0;
1083
- private packTime = 0;
1084
- private ordTime = 0;
1085
- private maxOrdTime = 0;
1086
-
1087
1044
  root: IMergeBlock;
1088
1045
  private readonly blockUpdateActions: BlockUpdateActions = MergeTree.initBlockUpdateActions;
1089
1046
  public readonly collabWindow = new CollaborationWindow();
@@ -1094,8 +1051,6 @@ export class MergeTree {
1094
1051
  // if we need to have pointers to non-markers, we can change to point at local refs
1095
1052
  private readonly idToSegment = new Map<string, ISegment>();
1096
1053
  private minSeqListeners: Heap<MinListener> | undefined;
1097
- // For diagnostics
1098
- public getLongClientId?: (id: number) => string;
1099
1054
  public mergeTreeDeltaCallback?: MergeTreeDeltaCallback;
1100
1055
  public mergeTreeMaintenanceCallback?: MergeTreeMaintenanceCallback;
1101
1056
 
@@ -1171,7 +1126,6 @@ export class MergeTree {
1171
1126
  assert(!this.collabWindow.collaborating, 0x049 /* "Trying to reload from segments while collaborating!" */);
1172
1127
 
1173
1128
  const maxChildren = MaxNodesInBlock - 1;
1174
- const measureReloadTime = false;
1175
1129
 
1176
1130
  // Starting with the leaf segments, recursively builds the B-Tree layer by layer from the bottom up.
1177
1131
  const buildMergeBlock = (nodes: IMergeNode[]) => {
@@ -1201,26 +1155,16 @@ export class MergeTree {
1201
1155
  this.blockUpdate(block);
1202
1156
  }
1203
1157
 
1204
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
1205
1158
  return blocks.length === 1 // If there is only one block at this layer...
1206
1159
  ? blocks[0] // ...then we're done. Return the root.
1207
1160
  : buildMergeBlock(blocks); // ...otherwise recursively build the next layer above blocks.
1208
1161
  };
1209
-
1210
- let clockStart: Trace | undefined;
1211
- if (measureReloadTime) {
1212
- clockStart = clock();
1213
- }
1214
1162
  if (segments.length > 0) {
1215
1163
  this.root = buildMergeBlock(segments);
1216
1164
  this.nodeUpdateOrdinals(this.root);
1217
1165
  } else {
1218
1166
  this.root = this.makeBlock(0);
1219
1167
  }
1220
-
1221
- if (clockStart) {
1222
- console.log(`reload time ${elapsedMicroseconds(clockStart)}`);
1223
- }
1224
1168
  }
1225
1169
  /* eslint-enable max-len */
1226
1170
 
@@ -1232,15 +1176,7 @@ export class MergeTree {
1232
1176
  this.collabWindow.currentSeq = currentSeq;
1233
1177
  this.segmentsToScour = new Heap<LRUSegment>([], LRUSegmentComparer);
1234
1178
  this.pendingSegments = ListMakeHead<SegmentGroup>();
1235
- const measureFullCollab = false;
1236
- let clockStart: Trace | undefined;
1237
- if (measureFullCollab) {
1238
- clockStart = clock();
1239
- }
1240
1179
  this.nodeUpdateLengthNewStructure(this.root, true);
1241
- if (clockStart) {
1242
- console.log(`update partial lengths at start ${elapsedMicroseconds(clockStart)}`);
1243
- }
1244
1180
  }
1245
1181
 
1246
1182
  private addToLRUSet(segment: ISegment, seq: number) {
@@ -1272,11 +1208,6 @@ export class MergeTree {
1272
1208
  } else if (!segment.trackingCollection.empty) {
1273
1209
  holdNodes.push(segment);
1274
1210
  } 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
1211
  // Notify maintenance event observers that the segment is being unlinked from the MergeTree
1281
1212
  if (this.mergeTreeMaintenanceCallback) {
1282
1213
  this.mergeTreeMaintenanceCallback({
@@ -1298,10 +1229,6 @@ export class MergeTree {
1298
1229
  && this.localNetLength(segment) > 0;
1299
1230
 
1300
1231
  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
1232
  prevSegment!.append(segment);
1306
1233
  if (this.mergeTreeMaintenanceCallback) {
1307
1234
  this.mergeTreeMaintenanceCallback({
@@ -1374,9 +1301,6 @@ export class MergeTree {
1374
1301
  packedBlocks[nodeIndex] = packedBlock;
1375
1302
  this.nodeUpdateLengthNewStructure(packedBlock);
1376
1303
  }
1377
- if (readCount !== totalNodeCount) {
1378
- console.log(`total count ${totalNodeCount} readCount ${readCount}`);
1379
- }
1380
1304
  parent.children = packedBlocks;
1381
1305
  for (let j = 0; j < childCount; j++) {
1382
1306
  parent.assignChild(packedBlocks[j], j, false);
@@ -1394,10 +1318,6 @@ export class MergeTree {
1394
1318
  if (!this.collabWindow.collaborating) {
1395
1319
  return;
1396
1320
  }
1397
- let clockStart;
1398
- if (MergeTree.options.measureWindowTime) {
1399
- clockStart = clock();
1400
- }
1401
1321
 
1402
1322
  for (let i = 0; i < zamboniSegmentsMaxCount; i++) {
1403
1323
  let segmentToScour = this.segmentsToScour!.peek();
@@ -1409,7 +1329,6 @@ export class MergeTree {
1409
1329
  if (segmentToScour.segment!.parent && segmentToScour.segment!.parent.needsScour !== false) {
1410
1330
  const block = segmentToScour.segment!.parent;
1411
1331
  const childrenCopy: IMergeNode[] = [];
1412
- // console.log(`scouring from ${segmentToScour.segment.seq}`);
1413
1332
  this.scourNode(block, childrenCopy);
1414
1333
  // This will avoid the cost of re-scouring nodes
1415
1334
  // that have recently been scoured
@@ -1425,16 +1344,9 @@ export class MergeTree {
1425
1344
  }
1426
1345
 
1427
1346
  if (this.underflow(block) && block.parent) {
1428
- // nodeUpdatePathLengths(node, UnassignedSequenceNumber, -1, true);
1429
- let packClockStart;
1430
- if (MergeTree.options.measureWindowTime) {
1431
- packClockStart = clock();
1432
- }
1347
+
1433
1348
  this.packParent(block.parent);
1434
1349
 
1435
- if (MergeTree.options.measureWindowTime) {
1436
- this.packTime += elapsedMicroseconds(packClockStart);
1437
- }
1438
1350
  } else {
1439
1351
  this.nodeUpdateOrdinals(block);
1440
1352
  this.blockUpdatePathLengths(block, UnassignedSequenceNumber, -1, true);
@@ -1442,10 +1354,6 @@ export class MergeTree {
1442
1354
  }
1443
1355
  }
1444
1356
  }
1445
-
1446
- if (MergeTree.options.measureWindowTime) {
1447
- this.windowTime += elapsedMicroseconds(clockStart);
1448
- }
1449
1357
  }
1450
1358
 
1451
1359
  public getCollabWindow() {
@@ -1495,74 +1403,9 @@ export class MergeTree {
1495
1403
  return stats;
1496
1404
  };
1497
1405
  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
1406
  return rootStats;
1505
1407
  }
1506
1408
 
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
1409
  public getLength(refSeq: number, clientId: number) {
1567
1410
  return this.blockLength(this.root, refSeq, clientId);
1568
1411
  }
@@ -1862,16 +1705,12 @@ export class MergeTree {
1862
1705
  * Assign sequence number to existing segment; update partial lengths to reflect the change
1863
1706
  * @param seq - sequence number given by server to pending segment
1864
1707
  */
1865
- public ackPendingSegment(opArgs: IMergeTreeDeltaOpArgs, verboseOps = false) {
1708
+ public ackPendingSegment(opArgs: IMergeTreeDeltaOpArgs) {
1866
1709
  const seq = opArgs.sequencedMessage!.sequenceNumber;
1867
1710
  const pendingSegmentGroup = this.pendingSegments!.dequeue();
1868
1711
  const nodesToUpdate: IMergeBlock[] = [];
1869
1712
  let overwrite = false;
1870
1713
  if (pendingSegmentGroup !== undefined) {
1871
- if (verboseOps) {
1872
- console.log(`segment group has ${pendingSegmentGroup.segments.length} segments`);
1873
- }
1874
-
1875
1714
  const deltaSegments: IMergeTreeSegmentDelta[] = [];
1876
1715
  pendingSegmentGroup.segments.map((pendingSegment) => {
1877
1716
  overwrite = !pendingSegment.ack(pendingSegmentGroup, opArgs, this) || overwrite;
@@ -1961,13 +1800,8 @@ export class MergeTree {
1961
1800
  seq: number,
1962
1801
  opArgs: IMergeTreeDeltaOpArgs | undefined,
1963
1802
  ) {
1964
- // const tt = MergeTree.traceTraversal;
1965
- // MergeTree.traceTraversal = true;
1966
1803
  this.ensureIntervalBoundary(pos, refSeq, clientId);
1967
1804
 
1968
- if (MergeTree.traceOrdinals) {
1969
- this.ordinalIntegrity();
1970
- }
1971
1805
  const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
1972
1806
 
1973
1807
  this.blockInsert(pos, refSeq, clientId, seq, localSeq, segments);
@@ -1982,10 +1816,6 @@ export class MergeTree {
1982
1816
  });
1983
1817
  }
1984
1818
 
1985
- // MergeTree.traceTraversal = tt;
1986
- if (MergeTree.traceOrdinals) {
1987
- this.ordinalIntegrity();
1988
- }
1989
1819
  if (this.collabWindow.collaborating && MergeTree.options.zamboniSegments &&
1990
1820
  (seq !== UnassignedSequenceNumber)) {
1991
1821
  this.zamboniSegments();
@@ -2109,7 +1939,13 @@ export class MergeTree {
2109
1939
  /**
2110
1940
  * Resolves a remote client's position against the local sequence
2111
1941
  * and returns the remote client's position relative to the local
2112
- * sequence
1942
+ * sequence. The client ref seq must be above the minimum sequence number
1943
+ * or the return value will be undefined.
1944
+ * Generally this method is used in conjunction with signals which provide
1945
+ * point in time values for the below parameters, and is useful for things
1946
+ * like displaying user position. It should not be used with persisted values
1947
+ * as persisted values will quickly become invalid as the remoteClientRefSeq
1948
+ * moves below the minimum sequence number
2113
1949
  * @param remoteClientPosition - The remote client's position to resolve
2114
1950
  * @param remoteClientRefSeq - The reference sequence number of the remote client
2115
1951
  * @param remoteClientId - The client id of the remote client
@@ -2118,6 +1954,11 @@ export class MergeTree {
2118
1954
  remoteClientPosition: number,
2119
1955
  remoteClientRefSeq: number,
2120
1956
  remoteClientId: number): number | undefined {
1957
+
1958
+ if(remoteClientRefSeq < this.collabWindow.minSeq){
1959
+ return undefined;
1960
+ }
1961
+
2121
1962
  const segmentInfo = this.getContainingSegment(
2122
1963
  remoteClientPosition,
2123
1964
  remoteClientRefSeq,
@@ -2159,10 +2000,6 @@ export class MergeTree {
2159
2000
  let segIsLocal = false;
2160
2001
  const checkSegmentIsLocal = (segment: ISegment, pos: number, refSeq: number, clientId: number) => {
2161
2002
  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
2003
  segIsLocal = true;
2167
2004
  }
2168
2005
  // Only need to look at first segment that follows finished node
@@ -2172,10 +2009,6 @@ export class MergeTree {
2172
2009
  const continueFrom = (node: IMergeBlock) => {
2173
2010
  segIsLocal = false;
2174
2011
  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
2012
  return segIsLocal;
2180
2013
  };
2181
2014
 
@@ -2270,7 +2103,7 @@ export class MergeTree {
2270
2103
  if (pos === 0) {
2271
2104
  // normalize the seq numbers
2272
2105
  // if the new seg is local (UnassignedSequenceNumber) give it the highest possible
2273
- // seq for comparision, as it will get a seq higher than any other seq once sequences
2106
+ // seq for comparison, as it will get a seq higher than any other seq once sequences
2274
2107
  // if the current seg is local (UnassignedSequenceNumber) give it the second highest
2275
2108
  // possible seq, as the highest is reserved for the previous.
2276
2109
  const newSeq = seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER : seq;
@@ -2357,7 +2190,6 @@ export class MergeTree {
2357
2190
  let child: IMergeNode;
2358
2191
  let newNode: IMergeNode | undefined;
2359
2192
  let fromSplit: IMergeBlock | undefined;
2360
- let found = false;
2361
2193
  for (childIndex = 0; childIndex < block.childCount; childIndex++) {
2362
2194
  child = children[childIndex];
2363
2195
  const len = this.nodeLength(child, refSeq, clientId);
@@ -2366,23 +2198,9 @@ export class MergeTree {
2366
2198
  // will be removed, so should just be skipped for now
2367
2199
  continue;
2368
2200
  }
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
2201
 
2383
2202
  if ((_pos < len) || ((_pos === len) && this.breakTie(_pos, child, seq))) {
2384
2203
  // Found entry containing pos
2385
- found = true;
2386
2204
  if (!child.isLeaf()) {
2387
2205
  const childBlock = child;
2388
2206
  // Internal node
@@ -2396,10 +2214,6 @@ export class MergeTree {
2396
2214
  }
2397
2215
  return undefined;
2398
2216
  } 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
2217
  _pos -= len; // Act as if shifted segment
2404
2218
  continue;
2405
2219
  } else {
@@ -2408,15 +2222,9 @@ export class MergeTree {
2408
2222
  childIndex++; // Insert after
2409
2223
  }
2410
2224
  } else {
2411
- if (MergeTree.traceTraversal) {
2412
- console.log(`@tcli: ${glc(this, this.collabWindow.clientId)}: leaf action`);
2413
- }
2414
2225
  const segment = child;
2415
2226
  const segmentChanges = context.leaf(segment, _pos, context);
2416
2227
  if (segmentChanges.replaceCurrent) {
2417
- if (MergeTree.traceOrdinals) {
2418
- console.log(`assign from leaf with block ord ${ordinalToArray(block.ordinal)}`);
2419
- }
2420
2228
  block.assignChild(segmentChanges.replaceCurrent, childIndex, false);
2421
2229
  segmentChanges.replaceCurrent.ordinal = child.ordinal;
2422
2230
  }
@@ -2436,21 +2244,12 @@ export class MergeTree {
2436
2244
  _pos -= len;
2437
2245
  }
2438
2246
  }
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
2247
  if (!newNode) {
2446
2248
  if (_pos === 0) {
2447
2249
  if ((seq !== UnassignedSequenceNumber) && context.continuePredicate &&
2448
2250
  context.continuePredicate(block)) {
2449
2251
  return MergeTree.theUnfinishedNode;
2450
2252
  } else {
2451
- if (MergeTree.traceTraversal) {
2452
- console.log(`@tcli: ${glc(this, this.collabWindow.clientId)}: leaf action pos 0`);
2453
- }
2454
2253
  const segmentChanges = context.leaf(undefined, _pos, context);
2455
2254
  newNode = segmentChanges.next;
2456
2255
  // Assert segmentChanges.replaceCurrent === undefined
@@ -2467,9 +2266,6 @@ export class MergeTree {
2467
2266
  block.setOrdinal(newNode, childIndex);
2468
2267
  if (block.childCount < MaxNodesInBlock) {
2469
2268
  if (fromSplit) {
2470
- if (MergeTree.traceOrdinals) {
2471
- console.log(`split ord ${ordinalToArray(fromSplit.ordinal)}`);
2472
- }
2473
2269
  this.nodeUpdateOrdinals(fromSplit);
2474
2270
  }
2475
2271
  if (context.structureChange) {
@@ -2502,44 +2298,7 @@ export class MergeTree {
2502
2298
  return newNode;
2503
2299
  }
2504
2300
 
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
2301
  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
2302
  for (let i = 0; i < block.childCount; i++) {
2544
2303
  const child = block.children[i];
2545
2304
  block.setOrdinal(child, i);
@@ -2547,22 +2306,12 @@ export class MergeTree {
2547
2306
  this.nodeUpdateOrdinals(child);
2548
2307
  }
2549
2308
  }
2550
- if (clockStart) {
2551
- const elapsed = elapsedMicroseconds(clockStart);
2552
- if (elapsed > this.maxOrdTime) {
2553
- this.maxOrdTime = elapsed;
2554
- }
2555
- this.ordTime += elapsed;
2556
- }
2557
2309
  }
2558
2310
 
2559
2311
  private addOverlappingClient(removalInfo: IRemovalInfo, clientId: number) {
2560
2312
  if (!removalInfo.removedClientOverlap) {
2561
2313
  removalInfo.removedClientOverlap = <number[]>[];
2562
2314
  }
2563
- if (MergeTree.diagOverlappingRemove) {
2564
- console.log(`added cli ${glc(this, clientId)} to rseq: ${removalInfo.removedSeq}`);
2565
- }
2566
2315
  removalInfo.removedClientOverlap.push(clientId);
2567
2316
  }
2568
2317
 
@@ -2638,10 +2387,6 @@ export class MergeTree {
2638
2387
  const markRemoved = (segment: ISegment, pos: number, start: number, end: number) => {
2639
2388
  const removalInfo: IRemovalInfo = segment;
2640
2389
  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
2390
  _overwrite = true;
2646
2391
  if (removalInfo.removedSeq === UnassignedSequenceNumber) {
2647
2392
  // replace because comes later
@@ -2675,7 +2420,6 @@ export class MergeTree {
2675
2420
  this.addToLRUSet(segment, seq);
2676
2421
  }
2677
2422
  }
2678
- // console.log(`saved local removed seg with text: ${textSegment.text}`);
2679
2423
  }
2680
2424
  return true;
2681
2425
  };
@@ -2687,7 +2431,6 @@ export class MergeTree {
2687
2431
  }
2688
2432
  return true;
2689
2433
  };
2690
- // MergeTree.traceTraversal = true;
2691
2434
  this.mapRange({ leaf: markRemoved, post: afterMarkRemoved }, refSeq, clientId, undefined, start, end);
2692
2435
  if (savedLocalRefs.length > 0) {
2693
2436
  const length = this.getLength(refSeq, clientId);
@@ -2736,7 +2479,6 @@ export class MergeTree {
2736
2479
  this.zamboniSegments();
2737
2480
  }
2738
2481
  }
2739
- // MergeTree.traceTraversal = false;
2740
2482
  }
2741
2483
 
2742
2484
  private nodeUpdateLengthNewStructure(node: IMergeBlock, recur = false) {
@@ -2855,46 +2597,6 @@ export class MergeTree {
2855
2597
  this.nodeMap(this.root, actions, 0, refSeq, clientId, accum, start, end);
2856
2598
  }
2857
2599
 
2858
- public nodeToString(block: IMergeBlock, strbuf: string, indentCount = 0) {
2859
- let _strbuf = strbuf;
2860
- _strbuf += internedSpaces(indentCount);
2861
- // eslint-disable-next-line max-len
2862
- _strbuf += `Node (len ${block.cachedLength}) p len (${block.parent ? block.parent.cachedLength : 0}) ord ${ordinalToArray(block.ordinal)} with ${block.childCount} segs:\n`;
2863
- if (MergeTree.blockUpdateMarkers) {
2864
- _strbuf += internedSpaces(indentCount);
2865
- _strbuf += (<IHierBlock>block).hierToString(indentCount);
2866
- }
2867
- if (this.collabWindow.collaborating) {
2868
- _strbuf += internedSpaces(indentCount);
2869
- _strbuf += `${block.partialLengths!.toString((id) => glc(this, id), indentCount)}\n`;
2870
- }
2871
- const children = block.children;
2872
- for (let childIndex = 0; childIndex < block.childCount; childIndex++) {
2873
- const child = children[childIndex];
2874
- if (!child.isLeaf()) {
2875
- _strbuf = this.nodeToString(child, _strbuf, indentCount + 4);
2876
- } else {
2877
- const segment = child;
2878
- _strbuf += internedSpaces(indentCount + 4);
2879
- // eslint-disable-next-line max-len
2880
- _strbuf += `cli: ${glc(this, segment.clientId)} seq: ${segment.seq} ord: ${ordinalToArray(segment.ordinal)}`;
2881
- const removalInfo: IRemovalInfo = segment;
2882
- if (removalInfo.removedSeq !== undefined) {
2883
- _strbuf += ` rcli: ${glc(this, removalInfo.removedClientId!)} rseq: ${removalInfo.removedSeq}`;
2884
- }
2885
- _strbuf += "\n";
2886
- _strbuf += internedSpaces(indentCount + 4);
2887
- _strbuf += segment.toString();
2888
- _strbuf += "\n";
2889
- }
2890
- }
2891
- return _strbuf;
2892
- }
2893
-
2894
- public toString() {
2895
- return this.nodeToString(this.root, "", 0);
2896
- }
2897
-
2898
2600
  public incrementalBlockMap<TContext>(stateStack: Stack<IncrementalMapState<TContext>>) {
2899
2601
  while (!stateStack.empty()) {
2900
2602
  // We already check the stack is not empty
@@ -2917,22 +2619,12 @@ export class MergeTree {
2917
2619
  if ((state.op === IncrementalExecOp.Go) && (state.childIndex < state.block.childCount)) {
2918
2620
  const child = state.block.children[state.childIndex];
2919
2621
  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
2622
  if ((len > 0) && (state.start < len) && (state.end > 0)) {
2927
2623
  if (!child.isLeaf()) {
2928
2624
  const childState = new IncrementalMapState(child, state.actions, state.pos,
2929
2625
  state.refSeq, state.clientId, state.context, state.start, state.end, 0);
2930
2626
  stateStack.push(childState);
2931
2627
  } 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
2628
  state.actions.leaf(child, state);
2937
2629
  }
2938
2630
  }
@@ -2975,20 +2667,6 @@ export class MergeTree {
2975
2667
  for (let childIndex = 0; childIndex < node.childCount; childIndex++) {
2976
2668
  const child = children[childIndex];
2977
2669
  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
2670
  if (go && (_end > 0) && (len > 0) && (_start < len)) {
2993
2671
  // Found entry containing pos
2994
2672
  if (!child.isLeaf()) {
@@ -2996,14 +2674,11 @@ export class MergeTree {
2996
2674
  go = this.nodeMap(child, actions, _pos, refSeq, clientId, accum, _start, _end);
2997
2675
  }
2998
2676
  } else {
2999
- if (MergeTree.traceTraversal) {
3000
- console.log(`@tcli ${glc(this, this.collabWindow.clientId)}: map leaf action`);
3001
- }
3002
2677
  if (actions.leaf) {
3003
- go = actions.leaf(child, _pos, refSeq, clientId, _start, _end, accum);
2678
+ go = actions.leaf(child, _pos, refSeq, clientId, _start, _end, accum);
2679
+ }
3004
2680
  }
3005
2681
  }
3006
- }
3007
2682
  if (!go) {
3008
2683
  break;
3009
2684
  }