@fluidframework/merge-tree 2.12.0 → 2.13.0
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/CHANGELOG.md +4 -0
- package/dist/MergeTreeTextHelper.d.ts.map +1 -1
- package/dist/MergeTreeTextHelper.js +0 -2
- package/dist/MergeTreeTextHelper.js.map +1 -1
- package/dist/attributionPolicy.d.ts.map +1 -1
- package/dist/attributionPolicy.js +6 -16
- package/dist/attributionPolicy.js.map +1 -1
- package/dist/client.d.ts +3 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +39 -28
- package/dist/client.js.map +1 -1
- package/dist/endOfTreeSegment.d.ts +2 -1
- package/dist/endOfTreeSegment.d.ts.map +1 -1
- package/dist/endOfTreeSegment.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +8 -7
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +190 -216
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeNodeWalk.d.ts.map +1 -1
- package/dist/mergeTreeNodeWalk.js +3 -2
- package/dist/mergeTreeNodeWalk.js.map +1 -1
- package/dist/mergeTreeNodes.d.ts +76 -162
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +100 -112
- package/dist/mergeTreeNodes.js.map +1 -1
- package/dist/mergeTreeTracking.d.ts.map +1 -1
- package/dist/mergeTreeTracking.js +0 -2
- package/dist/mergeTreeTracking.js.map +1 -1
- package/dist/partialLengths.d.ts +2 -2
- package/dist/partialLengths.d.ts.map +1 -1
- package/dist/partialLengths.js +28 -26
- package/dist/partialLengths.js.map +1 -1
- package/dist/perspective.d.ts +3 -2
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +11 -4
- package/dist/perspective.js.map +1 -1
- package/dist/referencePositions.d.ts.map +1 -1
- package/dist/referencePositions.js +4 -1
- package/dist/referencePositions.js.map +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +10 -11
- package/dist/revertibles.js.map +1 -1
- package/dist/segmentGroupCollection.d.ts +4 -4
- package/dist/segmentGroupCollection.d.ts.map +1 -1
- package/dist/segmentGroupCollection.js +0 -6
- package/dist/segmentGroupCollection.js.map +1 -1
- package/dist/segmentInfos.d.ts +257 -0
- package/dist/segmentInfos.d.ts.map +1 -0
- package/dist/segmentInfos.js +166 -0
- package/dist/segmentInfos.js.map +1 -0
- package/dist/snapshotLoader.d.ts.map +1 -1
- package/dist/snapshotLoader.js +38 -44
- package/dist/snapshotLoader.js.map +1 -1
- package/dist/snapshotV1.d.ts.map +1 -1
- package/dist/snapshotV1.js +9 -12
- package/dist/snapshotV1.js.map +1 -1
- package/dist/snapshotlegacy.d.ts +2 -2
- package/dist/snapshotlegacy.d.ts.map +1 -1
- package/dist/snapshotlegacy.js +5 -3
- package/dist/snapshotlegacy.js.map +1 -1
- package/dist/sortedSegmentSet.d.ts.map +1 -1
- package/dist/sortedSegmentSet.js +5 -8
- package/dist/sortedSegmentSet.js.map +1 -1
- package/dist/test/beastTest.spec.d.ts +0 -2
- package/dist/test/beastTest.spec.d.ts.map +1 -1
- package/dist/test/beastTest.spec.js +1 -5
- package/dist/test/beastTest.spec.js.map +1 -1
- package/dist/test/client.annotateMarker.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +15 -12
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.attributionFarm.spec.js.map +1 -1
- package/dist/test/client.getPosition.spec.js +3 -2
- package/dist/test/client.getPosition.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +6 -6
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.localReferenceFarm.spec.js.map +1 -1
- package/dist/test/client.rollback.spec.js.map +1 -1
- package/dist/test/dirname.cjs +0 -1
- package/dist/test/dirname.cjs.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +2 -4
- package/dist/test/index.js.map +1 -1
- package/dist/test/mergeTree.annotate.spec.js +3 -0
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/mergeTree.insertingWalk.spec.js +1 -1
- package/dist/test/mergeTree.insertingWalk.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js +2 -0
- package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/dist/test/mergeTree.walk.spec.js.map +1 -1
- package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
- package/dist/test/mergeTreeOperationRunner.js +2 -3
- package/dist/test/mergeTreeOperationRunner.js.map +1 -1
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/propertyManager.spec.js.map +1 -1
- package/dist/test/reconnectHelper.d.ts +2 -1
- package/dist/test/reconnectHelper.d.ts.map +1 -1
- package/dist/test/reconnectHelper.js.map +1 -1
- package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/dist/test/revertibleFarm.spec.js.map +1 -1
- package/dist/test/segmentGroupCollection.spec.js +15 -3
- package/dist/test/segmentGroupCollection.spec.js.map +1 -1
- package/dist/test/snapshot.utils.d.ts +2 -2
- package/dist/test/snapshot.utils.d.ts.map +1 -1
- package/dist/test/snapshot.utils.js.map +1 -1
- package/dist/test/sortedSegmentSet.spec.js +4 -3
- package/dist/test/sortedSegmentSet.spec.js.map +1 -1
- package/dist/test/testClient.d.ts +8 -6
- package/dist/test/testClient.d.ts.map +1 -1
- package/dist/test/testClient.js +29 -27
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/testClientLogger.d.ts.map +1 -1
- package/dist/test/testClientLogger.js +6 -4
- package/dist/test/testClientLogger.js.map +1 -1
- package/dist/test/testUtils.d.ts +2 -2
- package/dist/test/testUtils.d.ts.map +1 -1
- package/dist/test/testUtils.js +32 -8
- package/dist/test/testUtils.js.map +1 -1
- package/dist/test/text.d.ts +2 -2
- package/dist/test/text.d.ts.map +1 -1
- package/dist/test/text.js +12 -6
- package/dist/test/text.js.map +1 -1
- package/dist/test/tracking.spec.js.map +1 -1
- package/dist/test/wordUnitTests.spec.js +1 -1
- package/dist/test/wordUnitTests.spec.js.map +1 -1
- package/dist/zamboni.d.ts.map +1 -1
- package/dist/zamboni.js +8 -7
- package/dist/zamboni.js.map +1 -1
- package/lib/MergeTreeTextHelper.d.ts.map +1 -1
- package/lib/MergeTreeTextHelper.js +0 -2
- package/lib/MergeTreeTextHelper.js.map +1 -1
- package/lib/attributionPolicy.d.ts.map +1 -1
- package/lib/attributionPolicy.js +6 -16
- package/lib/attributionPolicy.js.map +1 -1
- package/lib/client.d.ts +3 -4
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +40 -29
- package/lib/client.js.map +1 -1
- package/lib/endOfTreeSegment.d.ts +2 -1
- package/lib/endOfTreeSegment.d.ts.map +1 -1
- package/lib/endOfTreeSegment.js.map +1 -1
- package/lib/index.d.ts +2 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +1 -1
- package/lib/index.js.map +1 -1
- package/lib/mergeTree.d.ts +8 -7
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +177 -205
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeNodeWalk.d.ts.map +1 -1
- package/lib/mergeTreeNodeWalk.js +3 -2
- package/lib/mergeTreeNodeWalk.js.map +1 -1
- package/lib/mergeTreeNodes.d.ts +76 -162
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +95 -108
- package/lib/mergeTreeNodes.js.map +1 -1
- package/lib/mergeTreeTracking.d.ts.map +1 -1
- package/lib/mergeTreeTracking.js +0 -2
- package/lib/mergeTreeTracking.js.map +1 -1
- package/lib/partialLengths.d.ts +2 -2
- package/lib/partialLengths.d.ts.map +1 -1
- package/lib/partialLengths.js +25 -23
- package/lib/partialLengths.js.map +1 -1
- package/lib/perspective.d.ts +3 -2
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +11 -4
- package/lib/perspective.js.map +1 -1
- package/lib/referencePositions.d.ts.map +1 -1
- package/lib/referencePositions.js +4 -1
- package/lib/referencePositions.js.map +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +8 -9
- package/lib/revertibles.js.map +1 -1
- package/lib/segmentGroupCollection.d.ts +4 -4
- package/lib/segmentGroupCollection.d.ts.map +1 -1
- package/lib/segmentGroupCollection.js +0 -6
- package/lib/segmentGroupCollection.js.map +1 -1
- package/lib/segmentInfos.d.ts +257 -0
- package/lib/segmentInfos.d.ts.map +1 -0
- package/lib/segmentInfos.js +145 -0
- package/lib/segmentInfos.js.map +1 -0
- package/lib/snapshotLoader.d.ts.map +1 -1
- package/lib/snapshotLoader.js +38 -44
- package/lib/snapshotLoader.js.map +1 -1
- package/lib/snapshotV1.d.ts.map +1 -1
- package/lib/snapshotV1.js +9 -12
- package/lib/snapshotV1.js.map +1 -1
- package/lib/snapshotlegacy.d.ts +2 -2
- package/lib/snapshotlegacy.d.ts.map +1 -1
- package/lib/snapshotlegacy.js +5 -3
- package/lib/snapshotlegacy.js.map +1 -1
- package/lib/sortedSegmentSet.d.ts.map +1 -1
- package/lib/sortedSegmentSet.js +5 -8
- package/lib/sortedSegmentSet.js.map +1 -1
- package/lib/test/beastTest.spec.d.ts +0 -2
- package/lib/test/beastTest.spec.d.ts.map +1 -1
- package/lib/test/beastTest.spec.js +0 -3
- package/lib/test/beastTest.spec.js.map +1 -1
- package/lib/test/client.annotateMarker.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +15 -12
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.attributionFarm.spec.js.map +1 -1
- package/lib/test/client.getPosition.spec.js +3 -2
- package/lib/test/client.getPosition.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +1 -1
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.localReferenceFarm.spec.js.map +1 -1
- package/lib/test/client.rollback.spec.js +1 -1
- package/lib/test/client.rollback.spec.js.map +1 -1
- package/lib/test/dirname.cjs +0 -1
- package/lib/test/dirname.cjs.map +1 -1
- package/lib/test/index.d.ts +1 -1
- package/lib/test/index.d.ts.map +1 -1
- package/lib/test/index.js +1 -1
- package/lib/test/index.js.map +1 -1
- package/lib/test/mergeTree.annotate.spec.js +3 -0
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/mergeTree.insertingWalk.spec.js +2 -2
- package/lib/test/mergeTree.insertingWalk.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js +2 -0
- package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/lib/test/mergeTree.walk.spec.js.map +1 -1
- package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
- package/lib/test/mergeTreeOperationRunner.js +1 -2
- package/lib/test/mergeTreeOperationRunner.js.map +1 -1
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/propertyManager.spec.js.map +1 -1
- package/lib/test/reconnectHelper.d.ts +2 -1
- package/lib/test/reconnectHelper.d.ts.map +1 -1
- package/lib/test/reconnectHelper.js.map +1 -1
- package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/lib/test/revertibleFarm.spec.js.map +1 -1
- package/lib/test/segmentGroupCollection.spec.js +15 -3
- package/lib/test/segmentGroupCollection.spec.js.map +1 -1
- package/lib/test/snapshot.utils.d.ts +2 -2
- package/lib/test/snapshot.utils.d.ts.map +1 -1
- package/lib/test/snapshot.utils.js.map +1 -1
- package/lib/test/sortedSegmentSet.spec.js +4 -3
- package/lib/test/sortedSegmentSet.spec.js.map +1 -1
- package/lib/test/testClient.d.ts +8 -6
- package/lib/test/testClient.d.ts.map +1 -1
- package/lib/test/testClient.js +30 -28
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/testClientLogger.d.ts.map +1 -1
- package/lib/test/testClientLogger.js +5 -3
- package/lib/test/testClientLogger.js.map +1 -1
- package/lib/test/testUtils.d.ts +2 -2
- package/lib/test/testUtils.d.ts.map +1 -1
- package/lib/test/testUtils.js +9 -8
- package/lib/test/testUtils.js.map +1 -1
- package/lib/test/text.d.ts +2 -2
- package/lib/test/text.d.ts.map +1 -1
- package/lib/test/text.js +12 -6
- package/lib/test/text.js.map +1 -1
- package/lib/test/tracking.spec.js.map +1 -1
- package/lib/test/wordUnitTests.spec.js +1 -1
- package/lib/test/wordUnitTests.spec.js.map +1 -1
- package/lib/zamboni.d.ts.map +1 -1
- package/lib/zamboni.js +7 -6
- package/lib/zamboni.js.map +1 -1
- package/package.json +17 -17
- package/src/MergeTreeTextHelper.ts +2 -4
- package/src/attributionPolicy.ts +5 -13
- package/src/client.ts +55 -44
- package/src/endOfTreeSegment.ts +3 -3
- package/src/index.ts +4 -6
- package/src/mergeTree.ts +245 -282
- package/src/mergeTreeNodeWalk.ts +3 -2
- package/src/mergeTreeNodes.ts +190 -322
- package/src/mergeTreeTracking.ts +0 -3
- package/src/partialLengths.ts +42 -27
- package/src/perspective.ts +27 -4
- package/src/referencePositions.ts +4 -1
- package/src/revertibles.ts +19 -13
- package/src/segmentGroupCollection.ts +7 -18
- package/src/segmentInfos.ts +377 -0
- package/src/snapshotLoader.ts +60 -57
- package/src/snapshotV1.ts +14 -16
- package/src/snapshotlegacy.ts +12 -17
- package/src/sortedSegmentSet.ts +6 -8
- package/src/zamboni.ts +10 -12
package/src/mergeTreeTracking.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
|
|
6
6
|
import { LocalReferencePosition } from "./localReference.js";
|
|
7
7
|
import { ISegment } from "./mergeTreeNodes.js";
|
|
8
|
-
// eslint-disable-next-line import/no-deprecated
|
|
9
8
|
import { SortedSegmentSet } from "./sortedSegmentSet.js";
|
|
10
9
|
|
|
11
10
|
/**
|
|
@@ -31,11 +30,9 @@ export interface ITrackingGroup {
|
|
|
31
30
|
* @alpha
|
|
32
31
|
*/
|
|
33
32
|
export class TrackingGroup implements ITrackingGroup {
|
|
34
|
-
// eslint-disable-next-line import/no-deprecated
|
|
35
33
|
private readonly trackedSet: SortedSegmentSet<Trackable>;
|
|
36
34
|
|
|
37
35
|
constructor() {
|
|
38
|
-
// eslint-disable-next-line import/no-deprecated
|
|
39
36
|
this.trackedSet = new SortedSegmentSet<Trackable>();
|
|
40
37
|
}
|
|
41
38
|
|
package/src/partialLengths.ts
CHANGED
|
@@ -9,24 +9,25 @@ import { Property, RedBlackTree } from "./collections/index.js";
|
|
|
9
9
|
import { UnassignedSequenceNumber } from "./constants.js";
|
|
10
10
|
import { MergeTree } from "./mergeTree.js";
|
|
11
11
|
import {
|
|
12
|
-
// eslint-disable-next-line import/no-deprecated
|
|
13
12
|
CollaborationWindow,
|
|
14
13
|
IMergeNode,
|
|
15
|
-
|
|
16
|
-
IMoveInfo,
|
|
17
|
-
// eslint-disable-next-line import/no-deprecated
|
|
18
|
-
IRemovalInfo,
|
|
19
|
-
ISegmentLeaf,
|
|
14
|
+
ISegmentPrivate,
|
|
20
15
|
compareNumbers,
|
|
21
16
|
seqLTE,
|
|
22
|
-
toMoveInfo,
|
|
23
|
-
toRemovalInfo,
|
|
24
17
|
type MergeBlock,
|
|
25
18
|
} from "./mergeTreeNodes.js";
|
|
26
|
-
|
|
19
|
+
import {
|
|
20
|
+
toRemovalInfo,
|
|
21
|
+
toMoveInfo,
|
|
22
|
+
// eslint-disable-next-line import/no-deprecated
|
|
23
|
+
IRemovalInfo,
|
|
24
|
+
// eslint-disable-next-line import/no-deprecated
|
|
25
|
+
IMoveInfo,
|
|
26
|
+
assertInserted,
|
|
27
|
+
isRemoved,
|
|
28
|
+
} from "./segmentInfos.js";
|
|
27
29
|
import { SortedSet } from "./sortedSet.js";
|
|
28
30
|
|
|
29
|
-
// eslint-disable-next-line import/no-deprecated
|
|
30
31
|
class PartialSequenceLengthsSet extends SortedSet<PartialSequenceLength, number> {
|
|
31
32
|
protected getKey(item: PartialSequenceLength): number {
|
|
32
33
|
return item.seq;
|
|
@@ -289,7 +290,7 @@ export class PartialSequenceLengths {
|
|
|
289
290
|
*/
|
|
290
291
|
public static combine(
|
|
291
292
|
block: MergeBlock,
|
|
292
|
-
|
|
293
|
+
|
|
293
294
|
collabWindow: CollaborationWindow,
|
|
294
295
|
recur = false,
|
|
295
296
|
computeLocalPartials = false,
|
|
@@ -378,7 +379,7 @@ export class PartialSequenceLengths {
|
|
|
378
379
|
*/
|
|
379
380
|
private static fromLeaves(
|
|
380
381
|
block: MergeBlock,
|
|
381
|
-
|
|
382
|
+
|
|
382
383
|
collabWindow: CollaborationWindow,
|
|
383
384
|
computeLocalPartials: boolean,
|
|
384
385
|
): PartialSequenceLengths {
|
|
@@ -506,10 +507,11 @@ export class PartialSequenceLengths {
|
|
|
506
507
|
*/
|
|
507
508
|
static accumulateMoveOverlapForExisting(
|
|
508
509
|
segmentLen: number,
|
|
509
|
-
segment:
|
|
510
|
+
segment: ISegmentPrivate,
|
|
510
511
|
firstGte: PartialSequenceLength,
|
|
511
512
|
clientIds: number[],
|
|
512
513
|
): void {
|
|
514
|
+
assertInserted(segment);
|
|
513
515
|
const nonInsertingClientIds = clientIds.filter((id) => id !== segment.clientId);
|
|
514
516
|
|
|
515
517
|
PartialSequenceLengths.accumulateMoveClientOverlap(
|
|
@@ -526,7 +528,7 @@ export class PartialSequenceLengths {
|
|
|
526
528
|
PartialSequenceLengths.accumulateMoveClientOverlap(
|
|
527
529
|
firstGte,
|
|
528
530
|
[segment.clientId],
|
|
529
|
-
segment
|
|
531
|
+
toMoveInfo(segment)?.wasMovedOnInsert ? -segment.cachedLength : segmentLen,
|
|
530
532
|
);
|
|
531
533
|
}
|
|
532
534
|
}
|
|
@@ -539,10 +541,11 @@ export class PartialSequenceLengths {
|
|
|
539
541
|
* segment
|
|
540
542
|
*/
|
|
541
543
|
private static getMoveOverlapForExisting(
|
|
542
|
-
segment:
|
|
544
|
+
segment: ISegmentPrivate,
|
|
543
545
|
obliterateOverlapLen: number,
|
|
544
546
|
clientIds: number[],
|
|
545
547
|
): RedBlackTree<number, IOverlapClient> {
|
|
548
|
+
assertInserted(segment);
|
|
546
549
|
const nonInsertingClientIds = clientIds.filter((id) => id !== segment.clientId);
|
|
547
550
|
const overlapObliterateClients = PartialSequenceLengths.getOverlapClients(
|
|
548
551
|
nonInsertingClientIds,
|
|
@@ -552,7 +555,9 @@ export class PartialSequenceLengths {
|
|
|
552
555
|
if (clientIds.length !== nonInsertingClientIds.length) {
|
|
553
556
|
overlapObliterateClients.put(segment.clientId, {
|
|
554
557
|
clientId: segment.clientId,
|
|
555
|
-
seglen: segment
|
|
558
|
+
seglen: toMoveInfo(segment)?.wasMovedOnInsert
|
|
559
|
+
? -segment.cachedLength
|
|
560
|
+
: obliterateOverlapLen,
|
|
556
561
|
});
|
|
557
562
|
}
|
|
558
563
|
|
|
@@ -560,7 +565,7 @@ export class PartialSequenceLengths {
|
|
|
560
565
|
}
|
|
561
566
|
|
|
562
567
|
private static updatePartialsAfterInsertion(
|
|
563
|
-
segment:
|
|
568
|
+
segment: ISegmentPrivate,
|
|
564
569
|
segmentLen: number,
|
|
565
570
|
remoteObliteratedLen: number | undefined,
|
|
566
571
|
obliterateOverlapLen: number = segmentLen,
|
|
@@ -640,12 +645,14 @@ export class PartialSequenceLengths {
|
|
|
640
645
|
*/
|
|
641
646
|
private static insertSegment(
|
|
642
647
|
combinedPartialLengths: PartialSequenceLengths,
|
|
643
|
-
segment:
|
|
648
|
+
segment: ISegmentPrivate,
|
|
644
649
|
// eslint-disable-next-line import/no-deprecated
|
|
645
650
|
removalInfo?: IRemovalInfo,
|
|
646
651
|
// eslint-disable-next-line import/no-deprecated
|
|
647
652
|
moveInfo?: IMoveInfo,
|
|
648
653
|
): void {
|
|
654
|
+
assertInserted(segment);
|
|
655
|
+
|
|
649
656
|
const removalIsLocal =
|
|
650
657
|
!!removalInfo && removalInfo.removedSeq === UnassignedSequenceNumber;
|
|
651
658
|
const moveIsLocal = !!moveInfo && moveInfo.movedSeq === UnassignedSequenceNumber;
|
|
@@ -654,7 +661,7 @@ export class PartialSequenceLengths {
|
|
|
654
661
|
(!!removalInfo && removalIsLocal && (!moveInfo || moveIsLocal)) ||
|
|
655
662
|
(!!moveInfo && moveIsLocal && (!removalInfo || removalIsLocal));
|
|
656
663
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
657
|
-
let seqOrLocalSeq = isLocal ? segment.localSeq! : segment.seq
|
|
664
|
+
let seqOrLocalSeq = isLocal ? segment.localSeq! : segment.seq;
|
|
658
665
|
let segmentLen = segment.cachedLength;
|
|
659
666
|
let clientId = segment.clientId;
|
|
660
667
|
let removeClientOverlap: number[] | undefined;
|
|
@@ -690,7 +697,7 @@ export class PartialSequenceLengths {
|
|
|
690
697
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
691
698
|
seqOrLocalSeq = moveIsLocal ? moveInfo.localMovedSeq! : moveInfo.movedSeq;
|
|
692
699
|
|
|
693
|
-
if (
|
|
700
|
+
if (moveInfo.wasMovedOnInsert) {
|
|
694
701
|
assert(
|
|
695
702
|
moveInfo.movedSeq !== -1,
|
|
696
703
|
0x871 /* wasMovedOnInsert should only be set on acked obliterates */,
|
|
@@ -702,7 +709,10 @@ export class PartialSequenceLengths {
|
|
|
702
709
|
|
|
703
710
|
const hasOverlap = moveInfo.movedClientIds.length > 1;
|
|
704
711
|
moveClientOverlap = hasOverlap ? moveInfo.movedClientIds : undefined;
|
|
705
|
-
}
|
|
712
|
+
} // BUG BUG: something fishy here around how/when move info is passed or not
|
|
713
|
+
// this condition only hits if it is not passed, so we can't rely on the passed move info
|
|
714
|
+
// and need to inspect the segment directly. maybe related to AB#15630.
|
|
715
|
+
else if (toMoveInfo(segment)?.wasMovedOnInsert) {
|
|
706
716
|
// if this segment was obliterated on insert, its length is only
|
|
707
717
|
// visible to the client that inserted it
|
|
708
718
|
segmentLen = 0;
|
|
@@ -775,7 +785,12 @@ export class PartialSequenceLengths {
|
|
|
775
785
|
// todo: the below block needs to be changed to handle obliterate, which
|
|
776
786
|
// doesn't have great support for reconnect at the moment. see ADO #3714
|
|
777
787
|
const { unsequencedRecords } = combinedPartialLengths;
|
|
778
|
-
if (
|
|
788
|
+
if (
|
|
789
|
+
unsequencedRecords &&
|
|
790
|
+
removeClientOverlap &&
|
|
791
|
+
isRemoved(segment) &&
|
|
792
|
+
segment.localRemovedSeq !== undefined
|
|
793
|
+
) {
|
|
779
794
|
const localSeq = segment.localRemovedSeq;
|
|
780
795
|
const localPartialLengthEntry: LocalPartialSequenceLength = {
|
|
781
796
|
seq: seqOrLocalSeq,
|
|
@@ -910,7 +925,7 @@ export class PartialSequenceLengths {
|
|
|
910
925
|
node: MergeBlock,
|
|
911
926
|
seq: number,
|
|
912
927
|
clientId: number,
|
|
913
|
-
|
|
928
|
+
|
|
914
929
|
collabWindow: CollaborationWindow,
|
|
915
930
|
): void {
|
|
916
931
|
let seqSeglen = 0;
|
|
@@ -938,10 +953,10 @@ export class PartialSequenceLengths {
|
|
|
938
953
|
// if this segment was moved on insert, its length should
|
|
939
954
|
// only be visible to the inserting client
|
|
940
955
|
if (
|
|
941
|
-
segment.wasMovedOnInsert &&
|
|
942
956
|
segment.seq !== undefined &&
|
|
943
957
|
moveInfo &&
|
|
944
|
-
moveInfo.movedSeq < segment.seq
|
|
958
|
+
moveInfo.movedSeq < segment.seq &&
|
|
959
|
+
moveInfo.wasMovedOnInsert
|
|
945
960
|
) {
|
|
946
961
|
remoteObliteratedLen += segment.cachedLength;
|
|
947
962
|
} else {
|
|
@@ -964,7 +979,7 @@ export class PartialSequenceLengths {
|
|
|
964
979
|
if (removeHappenedFirst) {
|
|
965
980
|
remoteObliteratedLen -= segment.cachedLength;
|
|
966
981
|
} else if (
|
|
967
|
-
|
|
982
|
+
moveInfo.wasMovedOnInsert &&
|
|
968
983
|
segment.seq !== UnassignedSequenceNumber &&
|
|
969
984
|
segment.seq !== undefined &&
|
|
970
985
|
moveInfo.movedSeq > segment.seq
|
|
@@ -1135,7 +1150,7 @@ export class PartialSequenceLengths {
|
|
|
1135
1150
|
}
|
|
1136
1151
|
|
|
1137
1152
|
// Clear away partial sums for sequence numbers earlier than the current window
|
|
1138
|
-
|
|
1153
|
+
|
|
1139
1154
|
private zamboni(segmentWindow: CollaborationWindow): void {
|
|
1140
1155
|
this.minLength += this.partialLengths.copyDown(segmentWindow.minSeq);
|
|
1141
1156
|
this.minSeq = segmentWindow.minSeq;
|
package/src/perspective.ts
CHANGED
|
@@ -7,6 +7,17 @@ import { UnassignedSequenceNumber } from "./constants.js";
|
|
|
7
7
|
import { type MergeTree } from "./mergeTree.js";
|
|
8
8
|
import { LeafAction, backwardExcursion, forwardExcursion } from "./mergeTreeNodeWalk.js";
|
|
9
9
|
import { seqLTE, type ISegmentLeaf } from "./mergeTreeNodes.js";
|
|
10
|
+
import {
|
|
11
|
+
isInserted,
|
|
12
|
+
isMoved,
|
|
13
|
+
isRemoved,
|
|
14
|
+
type IInsertionInfo,
|
|
15
|
+
// eslint-disable-next-line import/no-deprecated
|
|
16
|
+
type IMoveInfo,
|
|
17
|
+
// eslint-disable-next-line import/no-deprecated
|
|
18
|
+
type IRemovalInfo,
|
|
19
|
+
type SegmentWithInfo,
|
|
20
|
+
} from "./segmentInfos.js";
|
|
10
21
|
|
|
11
22
|
/**
|
|
12
23
|
* Provides a view of a MergeTree from the perspective of a specific client at a specific sequence number.
|
|
@@ -77,7 +88,11 @@ export class PerspectiveImpl implements Perspective {
|
|
|
77
88
|
* @param localSeq - The latest local sequence number to consider.
|
|
78
89
|
* @returns true iff this segment was removed in the given perspective.
|
|
79
90
|
*/
|
|
80
|
-
export function wasRemovedBefore(
|
|
91
|
+
export function wasRemovedBefore(
|
|
92
|
+
// eslint-disable-next-line import/no-deprecated
|
|
93
|
+
seg: SegmentWithInfo<IInsertionInfo & IRemovalInfo>,
|
|
94
|
+
{ refSeq, localSeq }: SeqTime,
|
|
95
|
+
): boolean {
|
|
81
96
|
if (
|
|
82
97
|
seg.removedSeq === UnassignedSequenceNumber &&
|
|
83
98
|
localSeq !== undefined &&
|
|
@@ -95,7 +110,11 @@ export function wasRemovedBefore(seg: ISegmentLeaf, { refSeq, localSeq }: SeqTim
|
|
|
95
110
|
* @param localSeq - The latest local sequence number to consider.
|
|
96
111
|
* @returns true iff this segment was moved (aka obliterated) in the given perspective.
|
|
97
112
|
*/
|
|
98
|
-
export function wasMovedBefore(
|
|
113
|
+
export function wasMovedBefore(
|
|
114
|
+
// eslint-disable-next-line import/no-deprecated
|
|
115
|
+
seg: SegmentWithInfo<IInsertionInfo & IMoveInfo>,
|
|
116
|
+
{ refSeq, localSeq }: SeqTime,
|
|
117
|
+
): boolean {
|
|
99
118
|
if (
|
|
100
119
|
seg.movedSeq === UnassignedSequenceNumber &&
|
|
101
120
|
localSeq !== undefined &&
|
|
@@ -110,7 +129,11 @@ export function wasMovedBefore(seg: ISegmentLeaf, { refSeq, localSeq }: SeqTime)
|
|
|
110
129
|
* See {@link wasRemovedBefore} and {@link wasMovedBefore}.
|
|
111
130
|
*/
|
|
112
131
|
export function wasRemovedOrMovedBefore(seg: ISegmentLeaf, seqTime: SeqTime): boolean {
|
|
113
|
-
return
|
|
132
|
+
return (
|
|
133
|
+
isInserted(seg) &&
|
|
134
|
+
((isRemoved(seg) && wasRemovedBefore(seg, seqTime)) ||
|
|
135
|
+
(isMoved(seg) && wasMovedBefore(seg, seqTime)))
|
|
136
|
+
);
|
|
114
137
|
}
|
|
115
138
|
|
|
116
139
|
/**
|
|
@@ -124,7 +147,7 @@ export function isSegmentPresent(seg: ISegmentLeaf, seqTime: SeqTime): boolean {
|
|
|
124
147
|
const { refSeq, localSeq } = seqTime;
|
|
125
148
|
// If seg.seq is undefined, then this segment has existed since minSeq.
|
|
126
149
|
// It may have been moved or removed since.
|
|
127
|
-
if (seg
|
|
150
|
+
if (isInserted(seg)) {
|
|
128
151
|
if (seg.seq !== UnassignedSequenceNumber) {
|
|
129
152
|
if (!seqLTE(seg.seq, refSeq)) {
|
|
130
153
|
return false;
|
|
@@ -7,6 +7,7 @@ import { SlidingPreference } from "./localReference.js";
|
|
|
7
7
|
import { ISegment } from "./mergeTreeNodes.js";
|
|
8
8
|
import { ReferenceType } from "./ops.js";
|
|
9
9
|
import { PropertySet } from "./properties.js";
|
|
10
|
+
import { isMergeNodeInfo } from "./segmentInfos.js";
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* @internal
|
|
@@ -131,6 +132,8 @@ export function compareReferencePositions(a: ReferencePosition, b: ReferencePosi
|
|
|
131
132
|
if (aSeg === bSeg) {
|
|
132
133
|
return a.getOffset() - b.getOffset();
|
|
133
134
|
} else {
|
|
134
|
-
return aSeg
|
|
135
|
+
return !isMergeNodeInfo(aSeg) || (isMergeNodeInfo(bSeg) && aSeg.ordinal < bSeg.ordinal)
|
|
136
|
+
? -1
|
|
137
|
+
: 1;
|
|
135
138
|
}
|
|
136
139
|
}
|
package/src/revertibles.ts
CHANGED
|
@@ -13,11 +13,18 @@ import { LocalReferenceCollection, LocalReferencePosition } from "./localReferen
|
|
|
13
13
|
import { MergeTree, findRootMergeBlock } from "./mergeTree.js";
|
|
14
14
|
import { IMergeTreeDeltaCallbackArgs } from "./mergeTreeDeltaCallback.js";
|
|
15
15
|
import { depthFirstNodeWalk } from "./mergeTreeNodeWalk.js";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
assertSegmentLeaf,
|
|
18
|
+
isSegmentLeaf,
|
|
19
|
+
toSegmentLeaf,
|
|
20
|
+
type ISegmentLeaf,
|
|
21
|
+
type ISegmentPrivate,
|
|
22
|
+
} from "./mergeTreeNodes.js";
|
|
17
23
|
import { ITrackingGroup, Trackable, UnorderedTrackingGroup } from "./mergeTreeTracking.js";
|
|
18
24
|
import { IJSONSegment, MergeTreeDeltaType, ReferenceType } from "./ops.js";
|
|
19
25
|
import { PropertySet, matchProperties } from "./properties.js";
|
|
20
26
|
import { DetachedReferencePosition } from "./referencePositions.js";
|
|
27
|
+
import { toRemovalInfo } from "./segmentInfos.js";
|
|
21
28
|
|
|
22
29
|
/**
|
|
23
30
|
* @legacy
|
|
@@ -86,7 +93,7 @@ export interface MergeTreeWithRevert extends MergeTree {
|
|
|
86
93
|
export type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
87
94
|
function findMergeTreeWithRevert(trackable: Trackable): MergeTreeWithRevert {
|
|
88
95
|
const segmentOrNode = trackable.isLeaf() ? trackable : trackable.getSegment();
|
|
89
|
-
const maybeRoot = findRootMergeBlock(segmentOrNode);
|
|
96
|
+
const maybeRoot = findRootMergeBlock(toSegmentLeaf(segmentOrNode));
|
|
90
97
|
assert(
|
|
91
98
|
maybeRoot?.mergeTree !== undefined,
|
|
92
99
|
0x5c2 /* trackable is invalid as it is not in a rooted merge tree. */,
|
|
@@ -243,7 +250,7 @@ export function discardMergeTreeDeltaRevertible(
|
|
|
243
250
|
t.trackingCollection.unlink(r.trackingGroup);
|
|
244
251
|
// remove untracked local references
|
|
245
252
|
if (t.trackingCollection.empty && !t.isLeaf()) {
|
|
246
|
-
const segment:
|
|
253
|
+
const segment: ISegmentPrivate | undefined = t.getSegment();
|
|
247
254
|
segment?.localRefs?.removeLocalRef(t);
|
|
248
255
|
}
|
|
249
256
|
}
|
|
@@ -261,7 +268,7 @@ function revertLocalInsert(
|
|
|
261
268
|
tracked.trackingCollection.unlink(revertible.trackingGroup),
|
|
262
269
|
0x3f1 /* tracking group removed */,
|
|
263
270
|
);
|
|
264
|
-
assert(tracked
|
|
271
|
+
assert(isSegmentLeaf(tracked), 0x3f2 /* inserts must track segments */);
|
|
265
272
|
if (toRemovalInfo(tracked) === undefined) {
|
|
266
273
|
const start = getPosition(mergeTreeWithRevert, tracked);
|
|
267
274
|
driver.removeRange(start, start + tracked.cachedLength);
|
|
@@ -284,14 +291,14 @@ function revertLocalRemove(
|
|
|
284
291
|
|
|
285
292
|
assert(!tracked.isLeaf(), 0x3f4 /* removes must track local refs */);
|
|
286
293
|
|
|
287
|
-
const refSeg
|
|
294
|
+
const refSeg = tracked.getSegment();
|
|
288
295
|
let realPos = mergeTreeWithRevert.referencePositionToLocalPosition(tracked);
|
|
289
296
|
|
|
290
297
|
// References which are on EndOfStringSegment don't return detached for pos,
|
|
291
298
|
// they will return the length of the merge-tree. this case just catches
|
|
292
299
|
// random references, likely not created in the revertible flow,
|
|
293
300
|
// that are tying to be reverted for some reason.
|
|
294
|
-
if (realPos === DetachedReferencePosition || refSeg
|
|
301
|
+
if (realPos === DetachedReferencePosition || !isSegmentLeaf(refSeg)) {
|
|
295
302
|
throw new UsageError("Cannot insert at detached references position");
|
|
296
303
|
}
|
|
297
304
|
|
|
@@ -301,12 +308,12 @@ function revertLocalRemove(
|
|
|
301
308
|
|
|
302
309
|
const props = tracked.properties as RemoveSegmentRefProperties;
|
|
303
310
|
driver.insertFromSpec(realPos, props.segSpec);
|
|
304
|
-
const insertSegment
|
|
311
|
+
const insertSegment = mergeTreeWithRevert.getContainingSegment(
|
|
305
312
|
realPos,
|
|
306
313
|
mergeTreeWithRevert.collabWindow.currentSeq,
|
|
307
314
|
mergeTreeWithRevert.collabWindow.clientId,
|
|
308
315
|
).segment;
|
|
309
|
-
|
|
316
|
+
assertSegmentLeaf(insertSegment);
|
|
310
317
|
|
|
311
318
|
const localSlideFilter = (lref: LocalReferencePosition): boolean =>
|
|
312
319
|
(lref.properties as Partial<RemoveSegmentRefProperties>)?.referenceSpace ===
|
|
@@ -333,11 +340,10 @@ function revertLocalRemove(
|
|
|
333
340
|
}
|
|
334
341
|
};
|
|
335
342
|
depthFirstNodeWalk(
|
|
336
|
-
|
|
337
|
-
insertSegment.parent!,
|
|
343
|
+
insertSegment.parent,
|
|
338
344
|
insertSegment,
|
|
339
345
|
undefined,
|
|
340
|
-
(seg:
|
|
346
|
+
(seg: ISegmentPrivate) => {
|
|
341
347
|
if (seg.localRefs?.empty === false) {
|
|
342
348
|
return seg.localRefs.walkReferences(refHandler, undefined, forward);
|
|
343
349
|
}
|
|
@@ -370,7 +376,7 @@ function revertLocalRemove(
|
|
|
370
376
|
tg.link(insertSegment);
|
|
371
377
|
tg.unlink(tracked);
|
|
372
378
|
}
|
|
373
|
-
const segment:
|
|
379
|
+
const segment: ISegmentPrivate | undefined = tracked.getSegment();
|
|
374
380
|
segment?.localRefs?.removeLocalRef(tracked);
|
|
375
381
|
}
|
|
376
382
|
}
|
|
@@ -383,7 +389,7 @@ function revertLocalAnnotate(
|
|
|
383
389
|
while (revertible.trackingGroup.size > 0) {
|
|
384
390
|
const tracked = revertible.trackingGroup.tracked[0];
|
|
385
391
|
const unlinked = tracked.trackingCollection.unlink(revertible.trackingGroup);
|
|
386
|
-
assert(unlinked && tracked
|
|
392
|
+
assert(unlinked && isSegmentLeaf(tracked), 0x3f7 /* annotates must track segments */);
|
|
387
393
|
if (toRemovalInfo(tracked) === undefined) {
|
|
388
394
|
const start = getPosition(mergeTreeWithRevert, tracked);
|
|
389
395
|
driver.annotateRange(start, start + tracked.cachedLength, revertible.propertyDeltas);
|
|
@@ -4,16 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import { DoublyLinkedList, walkList } from "./collections/index.js";
|
|
7
|
-
// eslint-disable-next-line import/no-deprecated
|
|
8
7
|
import { SegmentGroup, type ISegmentLeaf } from "./mergeTreeNodes.js";
|
|
9
8
|
|
|
10
9
|
export class SegmentGroupCollection {
|
|
11
|
-
|
|
12
|
-
private readonly segmentGroups: DoublyLinkedList<SegmentGroup<ISegmentLeaf>>;
|
|
10
|
+
private readonly segmentGroups: DoublyLinkedList<SegmentGroup>;
|
|
13
11
|
|
|
14
12
|
constructor(private readonly segment: ISegmentLeaf) {
|
|
15
|
-
|
|
16
|
-
this.segmentGroups = new DoublyLinkedList<SegmentGroup<ISegmentLeaf>>();
|
|
13
|
+
this.segmentGroups = new DoublyLinkedList<SegmentGroup>();
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
public get size(): number {
|
|
@@ -24,19 +21,16 @@ export class SegmentGroupCollection {
|
|
|
24
21
|
return this.segmentGroups.empty;
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
public enqueue(segmentGroup: SegmentGroup<ISegmentLeaf>): void {
|
|
24
|
+
public enqueue(segmentGroup: SegmentGroup): void {
|
|
29
25
|
this.segmentGroups.push(segmentGroup);
|
|
30
26
|
segmentGroup.segments.push(this.segment);
|
|
31
27
|
}
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
public dequeue(): SegmentGroup<ISegmentLeaf> | undefined {
|
|
29
|
+
public dequeue(): SegmentGroup | undefined {
|
|
35
30
|
return this.segmentGroups.shift()?.data;
|
|
36
31
|
}
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
public remove?(segmentGroup: SegmentGroup<ISegmentLeaf>): boolean {
|
|
33
|
+
public remove(segmentGroup: SegmentGroup): boolean {
|
|
40
34
|
const found = this.segmentGroups.find((v) => v.data === segmentGroup);
|
|
41
35
|
if (found === undefined) {
|
|
42
36
|
return false;
|
|
@@ -45,8 +39,7 @@ export class SegmentGroupCollection {
|
|
|
45
39
|
return true;
|
|
46
40
|
}
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
public pop?(): SegmentGroup<ISegmentLeaf> | undefined {
|
|
42
|
+
public pop(): SegmentGroup | undefined {
|
|
50
43
|
return this.segmentGroups.pop ? this.segmentGroups.pop()?.data : undefined;
|
|
51
44
|
}
|
|
52
45
|
|
|
@@ -54,11 +47,7 @@ export class SegmentGroupCollection {
|
|
|
54
47
|
walkList(this.segmentGroups, (sg) => segmentGroups.enqueueOnCopy(sg.data, this.segment));
|
|
55
48
|
}
|
|
56
49
|
|
|
57
|
-
|
|
58
|
-
private enqueueOnCopy(
|
|
59
|
-
segmentGroup: SegmentGroup<ISegmentLeaf>,
|
|
60
|
-
sourceSegment: ISegmentLeaf,
|
|
61
|
-
): void {
|
|
50
|
+
private enqueueOnCopy(segmentGroup: SegmentGroup, sourceSegment: ISegmentLeaf): void {
|
|
62
51
|
this.enqueue(segmentGroup);
|
|
63
52
|
if (segmentGroup.previousProps) {
|
|
64
53
|
// duplicate the previousProps for this segment
|