@fluidframework/merge-tree 2.11.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 +45 -0
- package/api-report/merge-tree.legacy.alpha.api.md +50 -19
- 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 -15
- 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 +5 -4
- 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 +3 -4
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +2 -1
- package/dist/localReference.d.ts +1 -0
- package/dist/localReference.d.ts.map +1 -1
- package/dist/localReference.js +1 -0
- package/dist/localReference.js.map +1 -1
- package/dist/mergeTree.d.ts +8 -7
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +202 -211
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeNodeWalk.d.ts +5 -5
- 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 +181 -159
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +121 -109
- 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 +33 -27
- package/dist/partialLengths.js.map +1 -1
- package/dist/perspective.d.ts +10 -9
- 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 +13 -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 +4 -4
- 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.d.ts.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.d.ts.map +1 -1
- package/dist/test/wordUnitTests.spec.js +4 -2
- 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 -15
- 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 +5 -4
- 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/legacy.d.ts +2 -1
- package/lib/localReference.d.ts +1 -0
- package/lib/localReference.d.ts.map +1 -1
- package/lib/localReference.js +1 -0
- package/lib/localReference.js.map +1 -1
- package/lib/mergeTree.d.ts +8 -7
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +192 -201
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeNodeWalk.d.ts +5 -5
- 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 +181 -159
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +115 -105
- 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 +30 -24
- package/lib/partialLengths.js.map +1 -1
- package/lib/perspective.d.ts +10 -9
- 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 +11 -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 +4 -4
- 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.d.ts.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 +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.d.ts.map +1 -1
- package/lib/test/wordUnitTests.spec.js +4 -2
- 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 +18 -18
- package/src/MergeTreeTextHelper.ts +2 -4
- package/src/attributionPolicy.ts +5 -11
- package/src/client.ts +55 -44
- package/src/endOfTreeSegment.ts +7 -4
- package/src/index.ts +5 -6
- package/src/localReference.ts +1 -0
- package/src/mergeTree.ts +253 -271
- package/src/mergeTreeNodeWalk.ts +9 -8
- package/src/mergeTreeNodes.ts +300 -305
- package/src/mergeTreeTracking.ts +0 -3
- package/src/partialLengths.ts +44 -25
- package/src/perspective.ts +36 -13
- package/src/referencePositions.ts +4 -1
- package/src/revertibles.ts +20 -16
- 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 +12 -15
- package/src/zamboni.ts +10 -12
package/lib/mergeTree.js
CHANGED
|
@@ -9,43 +9,29 @@ import { DataProcessingError, UsageError } from "@fluidframework/telemetry-utils
|
|
|
9
9
|
import { DoublyLinkedList } from "./collections/index.js";
|
|
10
10
|
import { NonCollabClient, TreeMaintenanceSequenceNumber, UnassignedSequenceNumber, UniversalSequenceNumber, } from "./constants.js";
|
|
11
11
|
import { EndOfTreeSegment, StartOfTreeSegment } from "./endOfTreeSegment.js";
|
|
12
|
-
import { LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
|
|
13
|
-
import { MergeTreeMaintenanceType, } from "./mergeTreeDeltaCallback.js";
|
|
14
|
-
import { NodeAction, backwardExcursion, depthFirstNodeWalk, forwardExcursion, walkAllChildSegments, } from "./mergeTreeNodeWalk.js";
|
|
15
12
|
import {
|
|
16
13
|
// eslint-disable-next-line import/no-deprecated
|
|
17
|
-
|
|
14
|
+
LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
|
|
15
|
+
import { MergeTreeMaintenanceType, } from "./mergeTreeDeltaCallback.js";
|
|
16
|
+
import { NodeAction, backwardExcursion, depthFirstNodeWalk, forwardExcursion, walkAllChildSegments, } from "./mergeTreeNodeWalk.js";
|
|
17
|
+
import { CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, assertSegmentLeaf, assignChild, isSegmentLeaf, reservedMarkerIdKey, seqLTE, } from "./mergeTreeNodes.js";
|
|
18
18
|
import { createAnnotateRangeOp, createInsertSegmentOp, createRemoveRangeOp, } from "./opBuilder.js";
|
|
19
19
|
import { MergeTreeDeltaType, ReferenceType, } from "./ops.js";
|
|
20
20
|
import { PartialSequenceLengths } from "./partialLengths.js";
|
|
21
21
|
import { PerspectiveImpl, isSegmentPresent } from "./perspective.js";
|
|
22
22
|
import { createMap, extend, extendIfUndefined } from "./properties.js";
|
|
23
23
|
import { DetachedReferencePosition, refGetTileLabels, refHasTileLabel, refTypeIncludesFlag, } from "./referencePositions.js";
|
|
24
|
-
// eslint-disable-next-line import/no-deprecated
|
|
25
24
|
import { SegmentGroupCollection } from "./segmentGroupCollection.js";
|
|
26
|
-
|
|
25
|
+
import { assertMoved, assertRemoved, isMergeNodeInfo, isMoved, isRemoved, overwriteInfo, removeRemovalInfo, toMoveInfo, toRemovalInfo, } from "./segmentInfos.js";
|
|
27
26
|
import { copyPropertiesAndManager, PropertiesManager, PropertiesRollback, } from "./segmentPropertiesManager.js";
|
|
28
27
|
import { Side } from "./sequencePlace.js";
|
|
29
28
|
import { SortedSegmentSet } from "./sortedSegmentSet.js";
|
|
30
29
|
import { zamboniSegments } from "./zamboni.js";
|
|
31
|
-
function markSegmentMoved(seg, moveInfo) {
|
|
32
|
-
seg.moveDst = moveInfo.moveDst;
|
|
33
|
-
seg.movedClientIds = [...moveInfo.movedClientIds];
|
|
34
|
-
seg.movedSeqs = [moveInfo.movedSeq];
|
|
35
|
-
seg.movedSeq = moveInfo.movedSeq;
|
|
36
|
-
seg.localMovedSeq = moveInfo.localMovedSeq;
|
|
37
|
-
seg.wasMovedOnInsert = moveInfo.wasMovedOnInsert;
|
|
38
|
-
}
|
|
39
|
-
function isMoved(segment) {
|
|
40
|
-
return toMoveInfo(segment) !== undefined;
|
|
41
|
-
}
|
|
42
|
-
function isRemoved(segment) {
|
|
43
|
-
return toRemovalInfo(segment) !== undefined;
|
|
44
|
-
}
|
|
45
30
|
function isRemovedAndAcked(segment) {
|
|
46
31
|
const removalInfo = toRemovalInfo(segment);
|
|
47
32
|
return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
|
|
48
33
|
}
|
|
34
|
+
// eslint-disable-next-line import/no-deprecated
|
|
49
35
|
function isMovedAndAcked(segment) {
|
|
50
36
|
const moveInfo = toMoveInfo(segment);
|
|
51
37
|
return moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber;
|
|
@@ -84,27 +70,25 @@ function ackSegment(segment, segmentGroup, opArgs) {
|
|
|
84
70
|
return true;
|
|
85
71
|
}
|
|
86
72
|
case MergeTreeDeltaType.REMOVE: {
|
|
87
|
-
|
|
88
|
-
assert(removalInfo !== undefined, 0x046 /* "On remove ack, missing removal info!" */);
|
|
73
|
+
assertRemoved(segment);
|
|
89
74
|
segment.localRemovedSeq = undefined;
|
|
90
|
-
if (
|
|
91
|
-
|
|
75
|
+
if (segment.removedSeq === UnassignedSequenceNumber) {
|
|
76
|
+
segment.removedSeq = sequenceNumber;
|
|
92
77
|
return true;
|
|
93
78
|
}
|
|
94
79
|
return false;
|
|
95
80
|
}
|
|
96
81
|
case MergeTreeDeltaType.OBLITERATE:
|
|
97
82
|
case MergeTreeDeltaType.OBLITERATE_SIDED: {
|
|
98
|
-
|
|
99
|
-
assert(moveInfo !== undefined, 0x86e /* On obliterate ack, missing move info! */);
|
|
83
|
+
assertMoved(segment);
|
|
100
84
|
const obliterateInfo = segmentGroup.obliterateInfo;
|
|
101
85
|
assert(obliterateInfo !== undefined, 0xa40 /* must have obliterate info */);
|
|
102
86
|
segment.localMovedSeq = obliterateInfo.localSeq = undefined;
|
|
103
|
-
const seqIdx =
|
|
87
|
+
const seqIdx = segment.movedSeqs.indexOf(UnassignedSequenceNumber);
|
|
104
88
|
assert(seqIdx !== -1, 0x86f /* expected movedSeqs to contain unacked seq */);
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
|
|
89
|
+
segment.movedSeqs[seqIdx] = sequenceNumber;
|
|
90
|
+
if (segment.movedSeq === UnassignedSequenceNumber) {
|
|
91
|
+
segment.movedSeq = sequenceNumber;
|
|
108
92
|
return true;
|
|
109
93
|
}
|
|
110
94
|
return false;
|
|
@@ -141,7 +125,6 @@ export function findRootMergeBlock(segmentOrNode) {
|
|
|
141
125
|
* entries for all segments visited during excursion.
|
|
142
126
|
* This can reduce the number of times the tree needs to be scanned if a range containing many
|
|
143
127
|
* SlideOnRemove references is removed.
|
|
144
|
-
* @internal
|
|
145
128
|
*/
|
|
146
129
|
function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWARD, cache, useNewSlidingBehavior = false) {
|
|
147
130
|
if (!segment ||
|
|
@@ -161,7 +144,8 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
|
|
|
161
144
|
return false;
|
|
162
145
|
}
|
|
163
146
|
if (cache !== undefined &&
|
|
164
|
-
(seg
|
|
147
|
+
(toRemovalInfo(seg)?.removedSeq === toRemovalInfo(segment)?.removedSeq ||
|
|
148
|
+
toMoveInfo(seg)?.movedSeq === toMoveInfo(segment)?.movedSeq)) {
|
|
165
149
|
cache.set(seg, result);
|
|
166
150
|
}
|
|
167
151
|
return true;
|
|
@@ -208,7 +192,7 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
|
|
|
208
192
|
* @internal
|
|
209
193
|
*/
|
|
210
194
|
export function getSlideToSegoff(segoff, slidingPreference = SlidingPreference.FORWARD, useNewSlidingBehavior = false) {
|
|
211
|
-
if (segoff.segment
|
|
195
|
+
if (!isSegmentLeaf(segoff.segment)) {
|
|
212
196
|
return segoff;
|
|
213
197
|
}
|
|
214
198
|
const [segment, _] = getSlideToSegment(segoff.segment, slidingPreference, undefined, useNewSlidingBehavior);
|
|
@@ -235,7 +219,6 @@ class Obliterates {
|
|
|
235
219
|
* See https://github.com/microsoft/FluidFramework/blob/main/packages/dds/merge-tree/docs/Obliterate.md#remote-perspective
|
|
236
220
|
* for additional context
|
|
237
221
|
*/
|
|
238
|
-
// eslint-disable-next-line import/no-deprecated
|
|
239
222
|
this.seqOrdered = new DoublyLinkedList();
|
|
240
223
|
/**
|
|
241
224
|
* This contains a sorted lists of all obliterate starts
|
|
@@ -253,7 +236,6 @@ class Obliterates {
|
|
|
253
236
|
this.mergeTree.removeLocalReferencePosition(ob.data.end);
|
|
254
237
|
}
|
|
255
238
|
}
|
|
256
|
-
// eslint-disable-next-line import/no-deprecated
|
|
257
239
|
addOrUpdate(obliterateInfo) {
|
|
258
240
|
const { seq, start } = obliterateInfo;
|
|
259
241
|
if (seq !== UnassignedSequenceNumber) {
|
|
@@ -264,14 +246,14 @@ class Obliterates {
|
|
|
264
246
|
empty() {
|
|
265
247
|
return this.startOrdered.size === 0;
|
|
266
248
|
}
|
|
267
|
-
// eslint-disable-next-line import/no-deprecated
|
|
268
249
|
findOverlapping(seg) {
|
|
269
|
-
// eslint-disable-next-line import/no-deprecated
|
|
270
250
|
const overlapping = [];
|
|
271
251
|
for (const start of this.startOrdered.items) {
|
|
272
|
-
|
|
252
|
+
const startSeg = start.getSegment();
|
|
253
|
+
if (isMergeNodeInfo(startSeg) && startSeg.ordinal <= seg.ordinal) {
|
|
273
254
|
const ob = start.properties?.obliterate;
|
|
274
|
-
|
|
255
|
+
const endSeg = ob.end.getSegment();
|
|
256
|
+
if (isMergeNodeInfo(endSeg) && endSeg.ordinal >= seg.ordinal) {
|
|
275
257
|
overlapping.push(ob);
|
|
276
258
|
}
|
|
277
259
|
}
|
|
@@ -289,9 +271,7 @@ class Obliterates {
|
|
|
289
271
|
export class MergeTree {
|
|
290
272
|
constructor(options) {
|
|
291
273
|
this.options = options;
|
|
292
|
-
// eslint-disable-next-line import/no-deprecated
|
|
293
274
|
this.collabWindow = new CollaborationWindow();
|
|
294
|
-
// eslint-disable-next-line import/no-deprecated
|
|
295
275
|
this.pendingSegments = new DoublyLinkedList();
|
|
296
276
|
this.segmentsToScour = new Heap(LRUSegmentComparer);
|
|
297
277
|
/**
|
|
@@ -309,6 +289,7 @@ export class MergeTree {
|
|
|
309
289
|
return {};
|
|
310
290
|
}
|
|
311
291
|
const next = segment.splitAt(pos);
|
|
292
|
+
assertSegmentLeaf(next);
|
|
312
293
|
if (segment?.segmentGroups) {
|
|
313
294
|
next.segmentGroups ?? (next.segmentGroups = new SegmentGroupCollection(next));
|
|
314
295
|
segment.segmentGroups.copyTo(next.segmentGroups);
|
|
@@ -371,7 +352,9 @@ export class MergeTree {
|
|
|
371
352
|
}
|
|
372
353
|
assert(refSeq !== undefined, 0x398 /* localSeq provided for local length without refSeq */);
|
|
373
354
|
assert(segment.seq !== undefined, 0x399 /* segment with no seq in mergeTree */);
|
|
374
|
-
const { seq
|
|
355
|
+
const { seq } = segment;
|
|
356
|
+
const { removedSeq, localRemovedSeq } = removalInfo ?? {};
|
|
357
|
+
const { movedSeq, localMovedSeq } = moveInfo ?? {};
|
|
375
358
|
if (seq === UnassignedSequenceNumber) {
|
|
376
359
|
assert(segment.localSeq !== undefined, 0x39a /* unacked segment with undefined localSeq */);
|
|
377
360
|
// inserted locally, still un-acked
|
|
@@ -407,7 +390,7 @@ export class MergeTree {
|
|
|
407
390
|
}
|
|
408
391
|
addNode(block, node) {
|
|
409
392
|
const index = block.childCount++;
|
|
410
|
-
|
|
393
|
+
assignChild(block, node, index, false);
|
|
411
394
|
return index;
|
|
412
395
|
}
|
|
413
396
|
reloadFromSegments(segments) {
|
|
@@ -501,12 +484,12 @@ export class MergeTree {
|
|
|
501
484
|
assert(localSeq === undefined || clientId === this.collabWindow.clientId, 0x39b /* localSeq provided for non-local client */);
|
|
502
485
|
let segment;
|
|
503
486
|
let offset;
|
|
504
|
-
const leaf = (leafSeg,
|
|
487
|
+
const leaf = (leafSeg, _, start) => {
|
|
505
488
|
segment = leafSeg;
|
|
506
489
|
offset = start;
|
|
507
490
|
return false;
|
|
508
491
|
};
|
|
509
|
-
this.nodeMap(refSeq, clientId, leaf, undefined,
|
|
492
|
+
this.nodeMap(refSeq, clientId, leaf, undefined, pos, pos + 1, localSeq);
|
|
510
493
|
return { segment, offset };
|
|
511
494
|
}
|
|
512
495
|
/**
|
|
@@ -531,7 +514,9 @@ export class MergeTree {
|
|
|
531
514
|
*/
|
|
532
515
|
slideAckedRemovedSegmentReferences(segments) {
|
|
533
516
|
// References are slid in groups to preserve their order.
|
|
517
|
+
// eslint-disable-next-line import/no-deprecated
|
|
534
518
|
let currentForwardSlideGroup = [];
|
|
519
|
+
// eslint-disable-next-line import/no-deprecated
|
|
535
520
|
let currentBackwardSlideGroup = [];
|
|
536
521
|
let currentForwardMaybeEndpoint;
|
|
537
522
|
let currentForwardSlideDestination;
|
|
@@ -539,7 +524,9 @@ export class MergeTree {
|
|
|
539
524
|
let currentBackwardMaybeEndpoint;
|
|
540
525
|
let currentBackwardSlideDestination;
|
|
541
526
|
let currentBackwardSlideIsForward;
|
|
542
|
-
const slideGroup = (currentSlideDestination, currentSlideIsForward,
|
|
527
|
+
const slideGroup = (currentSlideDestination, currentSlideIsForward,
|
|
528
|
+
// eslint-disable-next-line import/no-deprecated
|
|
529
|
+
currentSlideGroup, pred, maybeEndpoint) => {
|
|
543
530
|
if (currentSlideIsForward === undefined) {
|
|
544
531
|
return;
|
|
545
532
|
}
|
|
@@ -547,6 +534,7 @@ export class MergeTree {
|
|
|
547
534
|
const endpointRefsToAdd = currentSlideGroup.map((collection) => filterLocalReferencePositions(collection, (ref) => pred(ref) && !!ref.canSlideToEndpoint));
|
|
548
535
|
if (maybeEndpoint) {
|
|
549
536
|
const endpoint = maybeEndpoint === "start" ? this.startOfTree : this.endOfTree;
|
|
537
|
+
// eslint-disable-next-line import/no-deprecated
|
|
550
538
|
const localRefs = LocalReferenceCollection.setOrGet(endpoint);
|
|
551
539
|
if (currentSlideIsForward) {
|
|
552
540
|
localRefs.addBeforeTombstones(...endpointRefsToAdd);
|
|
@@ -567,6 +555,7 @@ export class MergeTree {
|
|
|
567
555
|
}
|
|
568
556
|
}
|
|
569
557
|
else {
|
|
558
|
+
// eslint-disable-next-line import/no-deprecated
|
|
570
559
|
const localRefs = LocalReferenceCollection.setOrGet(currentSlideDestination);
|
|
571
560
|
if (currentSlideIsForward) {
|
|
572
561
|
localRefs.addBeforeTombstones(...nonEndpointRefsToAdd);
|
|
@@ -576,7 +565,9 @@ export class MergeTree {
|
|
|
576
565
|
}
|
|
577
566
|
}
|
|
578
567
|
};
|
|
579
|
-
const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward,
|
|
568
|
+
const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward,
|
|
569
|
+
// eslint-disable-next-line import/no-deprecated
|
|
570
|
+
currentSlideGroup, pred, slidingPreference, currentMaybeEndpoint, reassign) => {
|
|
580
571
|
// avoid sliding logic if this segment doesn't have any references
|
|
581
572
|
// with the given sliding preference
|
|
582
573
|
if (!segment.localRefs || !anyLocalReferencePosition(segment.localRefs, pred)) {
|
|
@@ -633,7 +624,6 @@ export class MergeTree {
|
|
|
633
624
|
if (this.localPartialsComputed) {
|
|
634
625
|
return;
|
|
635
626
|
}
|
|
636
|
-
// eslint-disable-next-line import/no-deprecated
|
|
637
627
|
const rebaseCollabWindow = new CollaborationWindow();
|
|
638
628
|
rebaseCollabWindow.loadFrom(this.collabWindow);
|
|
639
629
|
if (refSeq < this.collabWindow.minSeq) {
|
|
@@ -717,24 +707,26 @@ export class MergeTree {
|
|
|
717
707
|
*/
|
|
718
708
|
referencePositionToLocalPosition(refPos, refSeq = Number.MAX_SAFE_INTEGER, clientId = this.collabWindow.clientId, localSeq = this.collabWindow.localSeq) {
|
|
719
709
|
const seg = refPos.getSegment();
|
|
720
|
-
if (seg
|
|
710
|
+
if (!isSegmentLeaf(seg)) {
|
|
721
711
|
// We have no idea where this reference is, because it refers to a segment which is not in the tree.
|
|
722
712
|
return DetachedReferencePosition;
|
|
723
713
|
}
|
|
724
714
|
if (refPos.isLeaf()) {
|
|
725
|
-
return this.getPosition(
|
|
715
|
+
return this.getPosition(seg, refSeq, clientId, localSeq);
|
|
726
716
|
}
|
|
727
717
|
if (refTypeIncludesFlag(refPos, ReferenceType.Transient) || seg.localRefs?.has(refPos)) {
|
|
728
718
|
if (seg !== this.startOfTree &&
|
|
729
719
|
seg !== this.endOfTree &&
|
|
730
720
|
!isSegmentPresent(seg, { refSeq, localSeq })) {
|
|
731
721
|
const forward = refPos.slidingPreference === SlidingPreference.FORWARD;
|
|
732
|
-
const
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
722
|
+
const moveInfo = toMoveInfo(seg);
|
|
723
|
+
const removeInfo = toRemovalInfo(seg);
|
|
724
|
+
const slideSeq = moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber
|
|
725
|
+
? moveInfo.movedSeq
|
|
726
|
+
: removeInfo !== undefined && removeInfo.removedSeq !== UnassignedSequenceNumber
|
|
727
|
+
? removeInfo.removedSeq
|
|
736
728
|
: refSeq;
|
|
737
|
-
const slideLocalSeq =
|
|
729
|
+
const slideLocalSeq = moveInfo?.localMovedSeq ?? removeInfo?.localRemovedSeq;
|
|
738
730
|
const perspective = new PerspectiveImpl(this, {
|
|
739
731
|
refSeq: slideSeq,
|
|
740
732
|
localSeq: slideLocalSeq,
|
|
@@ -762,11 +754,10 @@ export class MergeTree {
|
|
|
762
754
|
searchForMarker(startPos, clientId, markerLabel, forwards = true) {
|
|
763
755
|
let foundMarker;
|
|
764
756
|
const { segment } = this.getContainingSegment(startPos, UniversalSequenceNumber, clientId);
|
|
765
|
-
|
|
766
|
-
if (segWithParent?.parent === undefined) {
|
|
757
|
+
if (!isSegmentLeaf(segment)) {
|
|
767
758
|
return undefined;
|
|
768
759
|
}
|
|
769
|
-
depthFirstNodeWalk(
|
|
760
|
+
depthFirstNodeWalk(segment.parent, segment, (node) => {
|
|
770
761
|
if (node.isLeaf()) {
|
|
771
762
|
if (Marker.is(node) && refHasTileLabel(node, markerLabel)) {
|
|
772
763
|
foundMarker = node;
|
|
@@ -788,8 +779,8 @@ export class MergeTree {
|
|
|
788
779
|
updateRoot(splitNode) {
|
|
789
780
|
if (splitNode !== undefined) {
|
|
790
781
|
const newRoot = this.makeBlock(2);
|
|
791
|
-
|
|
792
|
-
|
|
782
|
+
assignChild(newRoot, this.root, 0, false);
|
|
783
|
+
assignChild(newRoot, splitNode, 1, false);
|
|
793
784
|
this.root = newRoot;
|
|
794
785
|
this.nodeUpdateOrdinals(this.root);
|
|
795
786
|
this.nodeUpdateLengthNewStructure(this.root);
|
|
@@ -845,9 +836,7 @@ export class MergeTree {
|
|
|
845
836
|
zamboniSegments(this);
|
|
846
837
|
}
|
|
847
838
|
}
|
|
848
|
-
addToPendingList(segment,
|
|
849
|
-
// eslint-disable-next-line import/no-deprecated
|
|
850
|
-
segmentGroup, localSeq, previousProps) {
|
|
839
|
+
addToPendingList(segment, segmentGroup, localSeq, previousProps) {
|
|
851
840
|
let _segmentGroup = segmentGroup;
|
|
852
841
|
if (_segmentGroup === undefined) {
|
|
853
842
|
_segmentGroup = {
|
|
@@ -867,7 +856,6 @@ export class MergeTree {
|
|
|
867
856
|
if (previousProps) {
|
|
868
857
|
_segmentGroup.previousProps.push(previousProps);
|
|
869
858
|
}
|
|
870
|
-
// eslint-disable-next-line import/no-deprecated
|
|
871
859
|
const segmentGroups = (segment.segmentGroups ?? (segment.segmentGroups = new SegmentGroupCollection(segment)));
|
|
872
860
|
segmentGroups.enqueue(_segmentGroup);
|
|
873
861
|
return _segmentGroup;
|
|
@@ -894,7 +882,7 @@ export class MergeTree {
|
|
|
894
882
|
if (relativePos.id) {
|
|
895
883
|
marker = this.getMarkerFromId(relativePos.id);
|
|
896
884
|
}
|
|
897
|
-
if (marker) {
|
|
885
|
+
if (isSegmentLeaf(marker)) {
|
|
898
886
|
pos = this.getPosition(marker, refseq, clientId);
|
|
899
887
|
if (relativePos.before) {
|
|
900
888
|
if (relativePos.offset !== undefined) {
|
|
@@ -952,7 +940,7 @@ export class MergeTree {
|
|
|
952
940
|
}
|
|
953
941
|
const segmentInfo = this.getContainingSegment(remoteClientPosition, remoteClientRefSeq, remoteClientId);
|
|
954
942
|
const { currentSeq, clientId } = this.collabWindow;
|
|
955
|
-
if (segmentInfo?.segment) {
|
|
943
|
+
if (isSegmentLeaf(segmentInfo?.segment)) {
|
|
956
944
|
const segmentPosition = this.getPosition(segmentInfo.segment, currentSeq, clientId);
|
|
957
945
|
return segmentPosition + segmentInfo.offset;
|
|
958
946
|
}
|
|
@@ -973,7 +961,6 @@ export class MergeTree {
|
|
|
973
961
|
});
|
|
974
962
|
return siblingExists;
|
|
975
963
|
};
|
|
976
|
-
// eslint-disable-next-line import/no-deprecated
|
|
977
964
|
let segmentGroup;
|
|
978
965
|
const saveIfLocal = (locSegment) => {
|
|
979
966
|
// Save segment so we can assign sequence number when acked by server
|
|
@@ -1003,92 +990,95 @@ export class MergeTree {
|
|
|
1003
990
|
}
|
|
1004
991
|
return segmentChanges;
|
|
1005
992
|
};
|
|
993
|
+
const insertInfo = {
|
|
994
|
+
clientId,
|
|
995
|
+
seq,
|
|
996
|
+
localSeq,
|
|
997
|
+
};
|
|
1006
998
|
// TODO: build tree from segs and insert all at once
|
|
1007
999
|
let insertPos = pos;
|
|
1008
|
-
for (const newSegment of newSegments
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
if (
|
|
1014
|
-
|
|
1015
|
-
if (markerId) {
|
|
1016
|
-
this.idToMarker.set(markerId, newSegment);
|
|
1017
|
-
}
|
|
1000
|
+
for (const newSegment of newSegments
|
|
1001
|
+
.filter((s) => s.cachedLength > 0)
|
|
1002
|
+
.map((s) => overwriteInfo(s, insertInfo))) {
|
|
1003
|
+
if (Marker.is(newSegment)) {
|
|
1004
|
+
const markerId = newSegment.getId();
|
|
1005
|
+
if (markerId) {
|
|
1006
|
+
this.idToMarker.set(markerId, newSegment);
|
|
1018
1007
|
}
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1008
|
+
}
|
|
1009
|
+
const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
|
|
1010
|
+
leaf: onLeaf,
|
|
1011
|
+
candidateSegment: newSegment,
|
|
1012
|
+
continuePredicate: continueFrom,
|
|
1013
|
+
});
|
|
1014
|
+
if (!isSegmentLeaf(newSegment)) {
|
|
1015
|
+
// Indicates an attempt to insert past the end of the merge-tree's content.
|
|
1016
|
+
const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
|
|
1017
|
+
throw new errorConstructor("MergeTree insert failed", {
|
|
1018
|
+
currentSeq: this.collabWindow.currentSeq,
|
|
1019
|
+
minSeq: this.collabWindow.minSeq,
|
|
1020
|
+
segSeq: insertInfo.seq,
|
|
1023
1021
|
});
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
|
|
1052
|
-
: ob.seq;
|
|
1053
|
-
if (normalizedObSeq > refSeq) {
|
|
1054
|
-
if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
|
|
1055
|
-
normalizedOldestSeq = normalizedObSeq;
|
|
1056
|
-
oldest = ob;
|
|
1057
|
-
movedClientIds.unshift(ob.clientId);
|
|
1058
|
-
movedSeqs.unshift(ob.seq);
|
|
1059
|
-
}
|
|
1060
|
-
else {
|
|
1061
|
-
movedClientIds.push(ob.clientId);
|
|
1062
|
-
movedSeqs.push(ob.seq);
|
|
1063
|
-
}
|
|
1064
|
-
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1065
|
-
normalizedNewestSeq = normalizedObSeq;
|
|
1066
|
-
newest = ob;
|
|
1067
|
-
}
|
|
1022
|
+
}
|
|
1023
|
+
this.updateRoot(splitNode);
|
|
1024
|
+
insertPos += newSegment.cachedLength;
|
|
1025
|
+
if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
|
|
1026
|
+
saveIfLocal(newSegment);
|
|
1027
|
+
continue;
|
|
1028
|
+
}
|
|
1029
|
+
let oldest;
|
|
1030
|
+
let normalizedOldestSeq = 0;
|
|
1031
|
+
let newest;
|
|
1032
|
+
let normalizedNewestSeq = 0;
|
|
1033
|
+
const movedClientIds = [];
|
|
1034
|
+
const movedSeqs = [];
|
|
1035
|
+
for (const ob of this.obliterates.findOverlapping(newSegment)) {
|
|
1036
|
+
// compute a normalized seq that takes into account local seqs
|
|
1037
|
+
// but is still comparable to remote seqs to keep the checks below easy
|
|
1038
|
+
// REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
|
|
1039
|
+
// [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
|
|
1040
|
+
const normalizedObSeq = ob.seq === UnassignedSequenceNumber
|
|
1041
|
+
? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
|
|
1042
|
+
: ob.seq;
|
|
1043
|
+
if (normalizedObSeq > refSeq) {
|
|
1044
|
+
if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
|
|
1045
|
+
normalizedOldestSeq = normalizedObSeq;
|
|
1046
|
+
oldest = ob;
|
|
1047
|
+
movedClientIds.unshift(ob.clientId);
|
|
1048
|
+
movedSeqs.unshift(ob.seq);
|
|
1068
1049
|
}
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
movedClientIds,
|
|
1073
|
-
movedSeq: oldest.seq,
|
|
1074
|
-
movedSeqs,
|
|
1075
|
-
localMovedSeq: oldest.localSeq,
|
|
1076
|
-
wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
|
|
1077
|
-
};
|
|
1078
|
-
markSegmentMoved(newSegment, moveInfo);
|
|
1079
|
-
if (moveInfo.localMovedSeq !== undefined) {
|
|
1080
|
-
assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
|
|
1081
|
-
this.addToPendingList(newSegment, oldest.segmentGroup);
|
|
1050
|
+
else {
|
|
1051
|
+
movedClientIds.push(ob.clientId);
|
|
1052
|
+
movedSeqs.push(ob.seq);
|
|
1082
1053
|
}
|
|
1083
|
-
if (
|
|
1084
|
-
|
|
1054
|
+
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1055
|
+
normalizedNewestSeq = normalizedObSeq;
|
|
1056
|
+
newest = ob;
|
|
1085
1057
|
}
|
|
1086
1058
|
}
|
|
1087
|
-
|
|
1088
|
-
|
|
1059
|
+
}
|
|
1060
|
+
if (oldest && newest?.clientId !== clientId) {
|
|
1061
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1062
|
+
const moveInfo = {
|
|
1063
|
+
movedClientIds,
|
|
1064
|
+
movedSeq: oldest.seq,
|
|
1065
|
+
movedSeqs,
|
|
1066
|
+
localMovedSeq: oldest.localSeq,
|
|
1067
|
+
wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
|
|
1068
|
+
};
|
|
1069
|
+
overwriteInfo(newSegment, moveInfo);
|
|
1070
|
+
if (moveInfo.localMovedSeq !== undefined) {
|
|
1071
|
+
assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
|
|
1072
|
+
this.addToPendingList(newSegment, oldest.segmentGroup);
|
|
1073
|
+
}
|
|
1074
|
+
if (newSegment.parent) {
|
|
1075
|
+
this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
|
|
1089
1076
|
}
|
|
1090
|
-
saveIfLocal(newSegment);
|
|
1091
1077
|
}
|
|
1078
|
+
else if (oldest && newest?.clientId === clientId) {
|
|
1079
|
+
newSegment.prevObliterateByInserter = newest;
|
|
1080
|
+
}
|
|
1081
|
+
saveIfLocal(newSegment);
|
|
1092
1082
|
}
|
|
1093
1083
|
}
|
|
1094
1084
|
ensureIntervalBoundary(pos, refSeq, clientId) {
|
|
@@ -1109,10 +1099,8 @@ export class MergeTree {
|
|
|
1109
1099
|
const newSeq = seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER : seq;
|
|
1110
1100
|
const segSeq = node.seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER - 1 : (node.seq ?? 0);
|
|
1111
1101
|
return (newSeq > segSeq ||
|
|
1112
|
-
(node.movedSeq !==
|
|
1113
|
-
|
|
1114
|
-
node.movedSeq > seq) ||
|
|
1115
|
-
(node.removedSeq !== undefined &&
|
|
1102
|
+
(isMoved(node) && node.movedSeq !== UnassignedSequenceNumber && node.movedSeq > seq) ||
|
|
1103
|
+
(isRemoved(node) &&
|
|
1116
1104
|
node.removedSeq !== UnassignedSequenceNumber &&
|
|
1117
1105
|
node.removedSeq > seq));
|
|
1118
1106
|
}
|
|
@@ -1144,7 +1132,7 @@ export class MergeTree {
|
|
|
1144
1132
|
const segment = child;
|
|
1145
1133
|
const segmentChanges = context.leaf(segment, _pos, context);
|
|
1146
1134
|
if (segmentChanges.replaceCurrent) {
|
|
1147
|
-
|
|
1135
|
+
assignChild(block, segmentChanges.replaceCurrent, childIndex, false);
|
|
1148
1136
|
segmentChanges.replaceCurrent.ordinal = child.ordinal;
|
|
1149
1137
|
}
|
|
1150
1138
|
if (segmentChanges.next) {
|
|
@@ -1195,7 +1183,7 @@ export class MergeTree {
|
|
|
1195
1183
|
block.children[i] = block.children[i - 1];
|
|
1196
1184
|
block.children[i].index = i;
|
|
1197
1185
|
}
|
|
1198
|
-
|
|
1186
|
+
assignChild(block, newNode, childIndex, false);
|
|
1199
1187
|
block.childCount++;
|
|
1200
1188
|
block.setOrdinal(newNode, childIndex);
|
|
1201
1189
|
if (block.childCount < MaxNodesInBlock) {
|
|
@@ -1224,7 +1212,7 @@ export class MergeTree {
|
|
|
1224
1212
|
// Update ordinals to reflect lowered child count
|
|
1225
1213
|
this.nodeUpdateOrdinals(node);
|
|
1226
1214
|
for (let i = 0; i < halfCount; i++) {
|
|
1227
|
-
|
|
1215
|
+
assignChild(newNode, node.children[halfCount + i], i, false);
|
|
1228
1216
|
node.children[halfCount + i] = undefined;
|
|
1229
1217
|
}
|
|
1230
1218
|
this.nodeUpdateLengthNewStructure(node);
|
|
@@ -1251,9 +1239,7 @@ export class MergeTree {
|
|
|
1251
1239
|
* @param opArgs - The op args for the annotate op. this is passed to the merge tree callback if there is one
|
|
1252
1240
|
* @param rollback - Whether this is for a local rollback and what kind
|
|
1253
1241
|
*/
|
|
1254
|
-
annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs,
|
|
1255
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1256
|
-
rollback = PropertiesRollback.None) {
|
|
1242
|
+
annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs, rollback = PropertiesRollback.None) {
|
|
1257
1243
|
if (propsOrAdjust.adjust !== undefined) {
|
|
1258
1244
|
errorIfOptionNotTrue(this.options, "mergeTreeEnableAnnotateAdjust");
|
|
1259
1245
|
}
|
|
@@ -1261,7 +1247,6 @@ export class MergeTree {
|
|
|
1261
1247
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1262
1248
|
const deltaSegments = [];
|
|
1263
1249
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1264
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1265
1250
|
let segmentGroup;
|
|
1266
1251
|
const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
|
|
1267
1252
|
const annotateSegment = (segment) => {
|
|
@@ -1285,7 +1270,7 @@ export class MergeTree {
|
|
|
1285
1270
|
}
|
|
1286
1271
|
return true;
|
|
1287
1272
|
};
|
|
1288
|
-
this.nodeMap(refSeq, clientId, annotateSegment, undefined,
|
|
1273
|
+
this.nodeMap(refSeq, clientId, annotateSegment, undefined, start, end);
|
|
1289
1274
|
// OpArgs == undefined => test code
|
|
1290
1275
|
if (deltaSegments.length > 0) {
|
|
1291
1276
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
@@ -1306,9 +1291,9 @@ export class MergeTree {
|
|
|
1306
1291
|
this.ensureIntervalBoundary(endPos, refSeq, clientId);
|
|
1307
1292
|
let _overwrite = false;
|
|
1308
1293
|
const localOverlapWithRefs = [];
|
|
1294
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1309
1295
|
const movedSegments = [];
|
|
1310
1296
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1311
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1312
1297
|
const obliterate = {
|
|
1313
1298
|
clientId,
|
|
1314
1299
|
end: createDetachedLocalReferencePosition(undefined),
|
|
@@ -1320,7 +1305,7 @@ export class MergeTree {
|
|
|
1320
1305
|
};
|
|
1321
1306
|
const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
|
|
1322
1307
|
const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
|
|
1323
|
-
assert(startSeg
|
|
1308
|
+
assert(isSegmentLeaf(startSeg) && isSegmentLeaf(endSeg), 0xa3f /* segments cannot be undefined */);
|
|
1324
1309
|
obliterate.start = this.createLocalReferencePosition(startSeg, start.side === Side.Before ? 0 : Math.max(startSeg.cachedLength - 1, 0), ReferenceType.StayOnRemove, {
|
|
1325
1310
|
obliterate,
|
|
1326
1311
|
});
|
|
@@ -1341,7 +1326,7 @@ export class MergeTree {
|
|
|
1341
1326
|
this.pendingSegments.push(obliterate.segmentGroup);
|
|
1342
1327
|
}
|
|
1343
1328
|
this.obliterates.addOrUpdate(obliterate);
|
|
1344
|
-
const markMoved = (segment, pos
|
|
1329
|
+
const markMoved = (segment, pos) => {
|
|
1345
1330
|
if ((start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
|
|
1346
1331
|
(end.side === Side.Before &&
|
|
1347
1332
|
endPos === pos &&
|
|
@@ -1358,23 +1343,27 @@ export class MergeTree {
|
|
|
1358
1343
|
// Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
|
|
1359
1344
|
return true;
|
|
1360
1345
|
}
|
|
1361
|
-
|
|
1346
|
+
const wasMovedOnInsert = clientId !== segment.clientId &&
|
|
1362
1347
|
segment.seq !== undefined &&
|
|
1363
1348
|
seq !== UnassignedSequenceNumber &&
|
|
1364
|
-
(refSeq < segment.seq || segment.seq === UnassignedSequenceNumber)
|
|
1365
|
-
segment.wasMovedOnInsert = true;
|
|
1366
|
-
}
|
|
1349
|
+
(refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
|
|
1367
1350
|
if (existingMoveInfo === undefined) {
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1351
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1352
|
+
const movedSeg = overwriteInfo(segment, {
|
|
1353
|
+
movedClientIds: [clientId],
|
|
1354
|
+
movedSeq: seq,
|
|
1355
|
+
localMovedSeq: localSeq,
|
|
1356
|
+
movedSeqs: [seq],
|
|
1357
|
+
wasMovedOnInsert,
|
|
1358
|
+
});
|
|
1359
|
+
if (!toRemovalInfo(movedSeg)) {
|
|
1360
|
+
movedSegments.push(movedSeg);
|
|
1374
1361
|
}
|
|
1375
1362
|
}
|
|
1376
1363
|
else {
|
|
1377
1364
|
_overwrite = true;
|
|
1365
|
+
// never move wasMovedOnInsert from true to false
|
|
1366
|
+
existingMoveInfo.wasMovedOnInsert || (existingMoveInfo.wasMovedOnInsert = wasMovedOnInsert);
|
|
1378
1367
|
if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
|
|
1379
1368
|
// we moved this locally, but someone else moved it first
|
|
1380
1369
|
// so put them at the head of the list
|
|
@@ -1393,6 +1382,7 @@ export class MergeTree {
|
|
|
1393
1382
|
existingMoveInfo.movedSeqs.push(seq);
|
|
1394
1383
|
}
|
|
1395
1384
|
}
|
|
1385
|
+
assertMoved(segment);
|
|
1396
1386
|
// Save segment so can assign moved sequence number when acked by server
|
|
1397
1387
|
if (this.collabWindow.collaborating) {
|
|
1398
1388
|
if (segment.movedSeq === UnassignedSequenceNumber &&
|
|
@@ -1407,7 +1397,7 @@ export class MergeTree {
|
|
|
1407
1397
|
}
|
|
1408
1398
|
return true;
|
|
1409
1399
|
};
|
|
1410
|
-
const afterMarkMoved = (node
|
|
1400
|
+
const afterMarkMoved = (node) => {
|
|
1411
1401
|
if (_overwrite) {
|
|
1412
1402
|
this.nodeUpdateLengthNewStructure(node);
|
|
1413
1403
|
}
|
|
@@ -1416,21 +1406,21 @@ export class MergeTree {
|
|
|
1416
1406
|
}
|
|
1417
1407
|
return true;
|
|
1418
1408
|
};
|
|
1419
|
-
this.nodeMap(refSeq, clientId, markMoved,
|
|
1409
|
+
this.nodeMap(refSeq, clientId, markMoved, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
|
|
1420
1410
|
undefined, seq === UnassignedSequenceNumber ? undefined : seq);
|
|
1421
1411
|
this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
|
|
1422
1412
|
// opArgs == undefined => test code
|
|
1423
1413
|
if (start.pos !== end.pos || start.side !== end.side) {
|
|
1424
1414
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
1425
1415
|
operation: MergeTreeDeltaType.OBLITERATE,
|
|
1426
|
-
deltaSegments: movedSegments,
|
|
1416
|
+
deltaSegments: movedSegments.map((segment) => ({ segment })),
|
|
1427
1417
|
});
|
|
1428
1418
|
}
|
|
1429
1419
|
// these events are newly removed
|
|
1430
1420
|
// so we slide after eventing in case the consumer wants to make reference
|
|
1431
1421
|
// changes at remove time, like add a ref to track undo redo.
|
|
1432
1422
|
if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
|
|
1433
|
-
this.slideAckedRemovedSegmentReferences(movedSegments
|
|
1423
|
+
this.slideAckedRemovedSegmentReferences(movedSegments);
|
|
1434
1424
|
}
|
|
1435
1425
|
if (this.collabWindow.collaborating &&
|
|
1436
1426
|
seq !== UnassignedSequenceNumber &&
|
|
@@ -1453,19 +1443,22 @@ export class MergeTree {
|
|
|
1453
1443
|
let _overwrite = false;
|
|
1454
1444
|
this.ensureIntervalBoundary(start, refSeq, clientId);
|
|
1455
1445
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1456
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1457
1446
|
let segmentGroup;
|
|
1447
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1458
1448
|
const removedSegments = [];
|
|
1459
1449
|
const localOverlapWithRefs = [];
|
|
1460
1450
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1461
1451
|
const markRemoved = (segment, pos, _start, _end) => {
|
|
1462
1452
|
const existingRemovalInfo = toRemovalInfo(segment);
|
|
1463
1453
|
if (existingRemovalInfo === undefined) {
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1454
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1455
|
+
const removed = overwriteInfo(segment, {
|
|
1456
|
+
removedClientIds: [clientId],
|
|
1457
|
+
removedSeq: seq,
|
|
1458
|
+
localRemovedSeq: localSeq,
|
|
1459
|
+
});
|
|
1460
|
+
if (!toMoveInfo(removed)) {
|
|
1461
|
+
removedSegments.push(removed);
|
|
1469
1462
|
}
|
|
1470
1463
|
}
|
|
1471
1464
|
else {
|
|
@@ -1486,6 +1479,7 @@ export class MergeTree {
|
|
|
1486
1479
|
existingRemovalInfo.removedClientIds.push(clientId);
|
|
1487
1480
|
}
|
|
1488
1481
|
}
|
|
1482
|
+
assertRemoved(segment);
|
|
1489
1483
|
// Save segment so we can assign removed sequence number when acked by server
|
|
1490
1484
|
if (this.collabWindow.collaborating) {
|
|
1491
1485
|
if (segment.removedSeq === UnassignedSequenceNumber &&
|
|
@@ -1500,7 +1494,7 @@ export class MergeTree {
|
|
|
1500
1494
|
}
|
|
1501
1495
|
return true;
|
|
1502
1496
|
};
|
|
1503
|
-
const afterMarkRemoved = (node
|
|
1497
|
+
const afterMarkRemoved = (node) => {
|
|
1504
1498
|
if (_overwrite) {
|
|
1505
1499
|
this.nodeUpdateLengthNewStructure(node);
|
|
1506
1500
|
}
|
|
@@ -1509,7 +1503,7 @@ export class MergeTree {
|
|
|
1509
1503
|
}
|
|
1510
1504
|
return true;
|
|
1511
1505
|
};
|
|
1512
|
-
this.nodeMap(refSeq, clientId, markRemoved,
|
|
1506
|
+
this.nodeMap(refSeq, clientId, markRemoved, afterMarkRemoved, start, end);
|
|
1513
1507
|
// these segments are already viewed as being removed locally and are not event-ed
|
|
1514
1508
|
// so can slide non-StayOnRemove refs immediately
|
|
1515
1509
|
this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
|
|
@@ -1517,14 +1511,14 @@ export class MergeTree {
|
|
|
1517
1511
|
if (removedSegments.length > 0) {
|
|
1518
1512
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
1519
1513
|
operation: MergeTreeDeltaType.REMOVE,
|
|
1520
|
-
deltaSegments: removedSegments,
|
|
1514
|
+
deltaSegments: removedSegments.map((segment) => ({ segment })),
|
|
1521
1515
|
});
|
|
1522
1516
|
}
|
|
1523
1517
|
// these events are newly removed
|
|
1524
1518
|
// so we slide after eventing in case the consumer wants to make reference
|
|
1525
1519
|
// changes at remove time, like add a ref to track undo redo.
|
|
1526
1520
|
if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
|
|
1527
|
-
this.slideAckedRemovedSegmentReferences(removedSegments
|
|
1521
|
+
this.slideAckedRemovedSegmentReferences(removedSegments);
|
|
1528
1522
|
}
|
|
1529
1523
|
if (this.collabWindow.collaborating &&
|
|
1530
1524
|
seq !== UnassignedSequenceNumber &&
|
|
@@ -1535,24 +1529,21 @@ export class MergeTree {
|
|
|
1535
1529
|
/**
|
|
1536
1530
|
* Revert an unacked local op
|
|
1537
1531
|
*/
|
|
1538
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1539
1532
|
rollback(op, localOpMetadata) {
|
|
1540
1533
|
if (op.type === MergeTreeDeltaType.REMOVE) {
|
|
1541
|
-
const pendingSegmentGroup = this.pendingSegments.pop
|
|
1534
|
+
const pendingSegmentGroup = this.pendingSegments.pop()?.data;
|
|
1542
1535
|
if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
|
|
1543
1536
|
throw new Error("Rollback op doesn't match last edit");
|
|
1544
1537
|
}
|
|
1545
1538
|
// Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
|
|
1546
1539
|
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1547
1540
|
pendingSegmentGroup.segments.forEach((segment) => {
|
|
1548
|
-
const segmentSegmentGroup = segment?.segmentGroups?.pop
|
|
1541
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop();
|
|
1549
1542
|
assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ee /* Unexpected segmentGroup in segment */);
|
|
1550
|
-
assert(segment.removedClientIds
|
|
1551
|
-
|
|
1552
|
-
segment
|
|
1553
|
-
|
|
1554
|
-
segment.localRemovedSeq = undefined;
|
|
1555
|
-
for (let updateNode = segment.parent; updateNode !== undefined; updateNode = updateNode.parent) {
|
|
1543
|
+
assert(isRemoved(segment) && segment.removedClientIds[0] === this.collabWindow.clientId, 0x39d /* Rollback segment removedClientId does not match local client */);
|
|
1544
|
+
let updateNode = segment.parent;
|
|
1545
|
+
removeRemovalInfo(segment);
|
|
1546
|
+
for (updateNode; updateNode !== undefined; updateNode = updateNode.parent) {
|
|
1556
1547
|
this.blockUpdateLength(updateNode, UnassignedSequenceNumber, this.collabWindow.clientId);
|
|
1557
1548
|
}
|
|
1558
1549
|
// Note: optional chaining short-circuits:
|
|
@@ -1565,7 +1556,7 @@ export class MergeTree {
|
|
|
1565
1556
|
}
|
|
1566
1557
|
else if (op.type === MergeTreeDeltaType.INSERT ||
|
|
1567
1558
|
op.type === MergeTreeDeltaType.ANNOTATE) {
|
|
1568
|
-
const pendingSegmentGroup = this.pendingSegments.pop
|
|
1559
|
+
const pendingSegmentGroup = this.pendingSegments.pop()?.data;
|
|
1569
1560
|
if (pendingSegmentGroup === undefined ||
|
|
1570
1561
|
pendingSegmentGroup !== localOpMetadata ||
|
|
1571
1562
|
(op.type === MergeTreeDeltaType.ANNOTATE && !pendingSegmentGroup.previousProps)) {
|
|
@@ -1573,7 +1564,7 @@ export class MergeTree {
|
|
|
1573
1564
|
}
|
|
1574
1565
|
let i = 0;
|
|
1575
1566
|
for (const segment of pendingSegmentGroup.segments) {
|
|
1576
|
-
const segmentSegmentGroup = segment?.segmentGroups?.pop
|
|
1567
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop();
|
|
1577
1568
|
assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ef /* Unexpected segmentGroup in segment */);
|
|
1578
1569
|
const start = this.findRollbackPosition(segment);
|
|
1579
1570
|
if (op.type === MergeTreeDeltaType.INSERT) {
|
|
@@ -1605,7 +1596,7 @@ export class MergeTree {
|
|
|
1605
1596
|
return false;
|
|
1606
1597
|
}
|
|
1607
1598
|
// If not removed, increase position
|
|
1608
|
-
if (seg
|
|
1599
|
+
if (!isRemoved(seg)) {
|
|
1609
1600
|
segmentPosition += seg.cachedLength;
|
|
1610
1601
|
}
|
|
1611
1602
|
return true;
|
|
@@ -1639,8 +1630,10 @@ export class MergeTree {
|
|
|
1639
1630
|
segment = this.endOfTree;
|
|
1640
1631
|
}
|
|
1641
1632
|
else {
|
|
1633
|
+
assertSegmentLeaf(_segment);
|
|
1642
1634
|
segment = _segment;
|
|
1643
1635
|
}
|
|
1636
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1644
1637
|
const localRefs = LocalReferenceCollection.setOrGet(segment);
|
|
1645
1638
|
const segRef = localRefs.createLocalRef(offset, refType, properties, slidingPreference, canSlideToEndpoint);
|
|
1646
1639
|
return segRef;
|
|
@@ -1702,7 +1695,7 @@ export class MergeTree {
|
|
|
1702
1695
|
for (let i = 0; i < newOrder.length; i++) {
|
|
1703
1696
|
const seg = newOrder[i];
|
|
1704
1697
|
const { parent, index, ordinal } = currentOrder[i];
|
|
1705
|
-
|
|
1698
|
+
assignChild(parent, seg, index, false);
|
|
1706
1699
|
seg.ordinal = ordinal;
|
|
1707
1700
|
}
|
|
1708
1701
|
for (const [segment, groups] of perSegmentTrackingGroups.entries()) {
|
|
@@ -1869,7 +1862,7 @@ export class MergeTree {
|
|
|
1869
1862
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1870
1863
|
}
|
|
1871
1864
|
}
|
|
1872
|
-
this.nodeMap(refSeq, clientId, handler, accum, undefined, start, end, undefined, visibilitySeq);
|
|
1865
|
+
this.nodeMap(refSeq, clientId, (seg, pos, _start, _end) => handler(seg, pos, refSeq, clientId, _start, _end, accum), undefined, start, end, undefined, visibilitySeq);
|
|
1873
1866
|
}
|
|
1874
1867
|
/**
|
|
1875
1868
|
* Map over all visible segments in a given range
|
|
@@ -1894,7 +1887,7 @@ export class MergeTree {
|
|
|
1894
1887
|
* but it will not count as a segment within the range. That is, it will be
|
|
1895
1888
|
* ignored for the purposes of tracking when traversal should end.
|
|
1896
1889
|
*/
|
|
1897
|
-
nodeMap(refSeq, clientId, leaf,
|
|
1890
|
+
nodeMap(refSeq, clientId, leaf, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
|
|
1898
1891
|
const endPos = end ?? this.nodeLength(this.root, refSeq, clientId, localSeq) ?? 0;
|
|
1899
1892
|
if (endPos === start) {
|
|
1900
1893
|
return;
|
|
@@ -1921,14 +1914,12 @@ export class MergeTree {
|
|
|
1921
1914
|
return NodeAction.Skip;
|
|
1922
1915
|
}
|
|
1923
1916
|
if (node.isLeaf()) {
|
|
1924
|
-
if (leaf(node, pos,
|
|
1917
|
+
if (leaf(node, pos, start - pos, endPos - pos) === false) {
|
|
1925
1918
|
return NodeAction.Exit;
|
|
1926
1919
|
}
|
|
1927
1920
|
pos = nextPos;
|
|
1928
1921
|
}
|
|
1929
|
-
}, undefined, post
|
|
1930
|
-
? undefined
|
|
1931
|
-
: (block) => post(block, pos, refSeq, clientId, start - pos, endPos - pos, accum));
|
|
1922
|
+
}, undefined, post);
|
|
1932
1923
|
}
|
|
1933
1924
|
}
|
|
1934
1925
|
MergeTree.options = {
|