@fluidframework/merge-tree 2.12.0 → 2.20.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 +46 -0
- package/api-report/merge-tree.legacy.alpha.api.md +0 -108
- 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 +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -4
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +0 -4
- package/dist/localReference.d.ts +5 -7
- package/dist/localReference.d.ts.map +1 -1
- package/dist/localReference.js +1 -3
- 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 +187 -228
- 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 +65 -325
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +96 -130
- 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/opBuilder.d.ts +0 -5
- package/dist/opBuilder.d.ts.map +1 -1
- package/dist/opBuilder.js +0 -5
- package/dist/opBuilder.js.map +1 -1
- package/dist/package.json +2 -1
- package/dist/partialLengths.d.ts +2 -2
- package/dist/partialLengths.d.ts.map +1 -1
- package/dist/partialLengths.js +29 -31
- 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 +5 -2
- 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 -14
- 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 +251 -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 +36 -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 +28 -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 +1 -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 +0 -4
- package/lib/localReference.d.ts +5 -7
- package/lib/localReference.d.ts.map +1 -1
- package/lib/localReference.js +1 -3
- 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 +175 -220
- 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 +65 -325
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +92 -127
- 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/opBuilder.d.ts +0 -5
- package/lib/opBuilder.d.ts.map +1 -1
- package/lib/opBuilder.js +0 -5
- package/lib/opBuilder.js.map +1 -1
- package/lib/partialLengths.d.ts +2 -2
- package/lib/partialLengths.d.ts.map +1 -1
- package/lib/partialLengths.js +26 -28
- 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 +5 -2
- 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 -12
- 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 +251 -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 +36 -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 +29 -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 +77 -19
- package/src/MergeTreeTextHelper.ts +2 -4
- package/src/attributionPolicy.ts +5 -13
- package/src/client.ts +55 -44
- package/src/endOfTreeSegment.ts +3 -5
- package/src/index.ts +0 -7
- package/src/localReference.ts +6 -8
- package/src/mergeTree.ts +233 -290
- package/src/mergeTreeNodeWalk.ts +3 -2
- package/src/mergeTreeNodes.ts +160 -490
- package/src/mergeTreeTracking.ts +0 -3
- package/src/opBuilder.ts +0 -5
- package/src/partialLengths.ts +40 -29
- package/src/perspective.ts +23 -4
- package/src/referencePositions.ts +4 -1
- package/src/revertibles.ts +19 -16
- package/src/segmentGroupCollection.ts +7 -18
- package/src/segmentInfos.ts +371 -0
- package/src/snapshotLoader.ts +56 -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/lib/mergeTree.js
CHANGED
|
@@ -9,50 +9,26 @@ 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 {
|
|
13
|
-
// eslint-disable-next-line import/no-deprecated
|
|
14
|
-
LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
|
|
12
|
+
import { LocalReferenceCollection, SlidingPreference, anyLocalReferencePosition, createDetachedLocalReferencePosition, filterLocalReferencePositions, } from "./localReference.js";
|
|
15
13
|
import { MergeTreeMaintenanceType, } from "./mergeTreeDeltaCallback.js";
|
|
16
14
|
import { NodeAction, backwardExcursion, depthFirstNodeWalk, forwardExcursion, walkAllChildSegments, } from "./mergeTreeNodeWalk.js";
|
|
17
|
-
import {
|
|
18
|
-
// eslint-disable-next-line import/no-deprecated
|
|
19
|
-
CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, reservedMarkerIdKey, seqLTE, toMoveInfo, toRemovalInfo, } from "./mergeTreeNodes.js";
|
|
15
|
+
import { CollaborationWindow, Marker, MaxNodesInBlock, MergeBlock, assertSegmentLeaf, assignChild, isSegmentLeaf, reservedMarkerIdKey, seqLTE, } from "./mergeTreeNodes.js";
|
|
20
16
|
import { createAnnotateRangeOp, createInsertSegmentOp, createRemoveRangeOp, } from "./opBuilder.js";
|
|
21
17
|
import { MergeTreeDeltaType, ReferenceType, } from "./ops.js";
|
|
22
18
|
import { PartialSequenceLengths } from "./partialLengths.js";
|
|
23
19
|
import { PerspectiveImpl, isSegmentPresent } from "./perspective.js";
|
|
24
20
|
import { createMap, extend, extendIfUndefined } from "./properties.js";
|
|
25
21
|
import { DetachedReferencePosition, refGetTileLabels, refHasTileLabel, refTypeIncludesFlag, } from "./referencePositions.js";
|
|
26
|
-
// eslint-disable-next-line import/no-deprecated
|
|
27
22
|
import { SegmentGroupCollection } from "./segmentGroupCollection.js";
|
|
28
|
-
|
|
23
|
+
import { assertMoved, assertRemoved, isMergeNodeInfo, isMoved, isRemoved, overwriteInfo, removeRemovalInfo, toMoveInfo, toRemovalInfo, } from "./segmentInfos.js";
|
|
29
24
|
import { copyPropertiesAndManager, PropertiesManager, PropertiesRollback, } from "./segmentPropertiesManager.js";
|
|
30
25
|
import { Side } from "./sequencePlace.js";
|
|
31
26
|
import { SortedSegmentSet } from "./sortedSegmentSet.js";
|
|
32
27
|
import { zamboniSegments } from "./zamboni.js";
|
|
33
|
-
// eslint-disable-next-line import/no-deprecated
|
|
34
|
-
function markSegmentMoved(seg, moveInfo) {
|
|
35
|
-
seg.moveDst = moveInfo.moveDst;
|
|
36
|
-
seg.movedClientIds = [...moveInfo.movedClientIds];
|
|
37
|
-
seg.movedSeqs = [moveInfo.movedSeq];
|
|
38
|
-
seg.movedSeq = moveInfo.movedSeq;
|
|
39
|
-
seg.localMovedSeq = moveInfo.localMovedSeq;
|
|
40
|
-
seg.wasMovedOnInsert = moveInfo.wasMovedOnInsert;
|
|
41
|
-
}
|
|
42
|
-
// eslint-disable-next-line import/no-deprecated
|
|
43
|
-
function isMoved(segment) {
|
|
44
|
-
return toMoveInfo(segment) !== undefined;
|
|
45
|
-
}
|
|
46
|
-
// eslint-disable-next-line import/no-deprecated
|
|
47
|
-
function isRemoved(segment) {
|
|
48
|
-
return toRemovalInfo(segment) !== undefined;
|
|
49
|
-
}
|
|
50
|
-
// eslint-disable-next-line import/no-deprecated
|
|
51
28
|
function isRemovedAndAcked(segment) {
|
|
52
29
|
const removalInfo = toRemovalInfo(segment);
|
|
53
30
|
return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
|
|
54
31
|
}
|
|
55
|
-
// eslint-disable-next-line import/no-deprecated
|
|
56
32
|
function isMovedAndAcked(segment) {
|
|
57
33
|
const moveInfo = toMoveInfo(segment);
|
|
58
34
|
return moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber;
|
|
@@ -91,29 +67,25 @@ function ackSegment(segment, segmentGroup, opArgs) {
|
|
|
91
67
|
return true;
|
|
92
68
|
}
|
|
93
69
|
case MergeTreeDeltaType.REMOVE: {
|
|
94
|
-
|
|
95
|
-
const removalInfo = toRemovalInfo(segment);
|
|
96
|
-
assert(removalInfo !== undefined, 0x046 /* "On remove ack, missing removal info!" */);
|
|
70
|
+
assertRemoved(segment);
|
|
97
71
|
segment.localRemovedSeq = undefined;
|
|
98
|
-
if (
|
|
99
|
-
|
|
72
|
+
if (segment.removedSeq === UnassignedSequenceNumber) {
|
|
73
|
+
segment.removedSeq = sequenceNumber;
|
|
100
74
|
return true;
|
|
101
75
|
}
|
|
102
76
|
return false;
|
|
103
77
|
}
|
|
104
78
|
case MergeTreeDeltaType.OBLITERATE:
|
|
105
79
|
case MergeTreeDeltaType.OBLITERATE_SIDED: {
|
|
106
|
-
|
|
107
|
-
const moveInfo = toMoveInfo(segment);
|
|
108
|
-
assert(moveInfo !== undefined, 0x86e /* On obliterate ack, missing move info! */);
|
|
80
|
+
assertMoved(segment);
|
|
109
81
|
const obliterateInfo = segmentGroup.obliterateInfo;
|
|
110
82
|
assert(obliterateInfo !== undefined, 0xa40 /* must have obliterate info */);
|
|
111
83
|
segment.localMovedSeq = obliterateInfo.localSeq = undefined;
|
|
112
|
-
const seqIdx =
|
|
84
|
+
const seqIdx = segment.movedSeqs.indexOf(UnassignedSequenceNumber);
|
|
113
85
|
assert(seqIdx !== -1, 0x86f /* expected movedSeqs to contain unacked seq */);
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
86
|
+
segment.movedSeqs[seqIdx] = sequenceNumber;
|
|
87
|
+
if (segment.movedSeq === UnassignedSequenceNumber) {
|
|
88
|
+
segment.movedSeq = sequenceNumber;
|
|
117
89
|
return true;
|
|
118
90
|
}
|
|
119
91
|
return false;
|
|
@@ -150,7 +122,6 @@ export function findRootMergeBlock(segmentOrNode) {
|
|
|
150
122
|
* entries for all segments visited during excursion.
|
|
151
123
|
* This can reduce the number of times the tree needs to be scanned if a range containing many
|
|
152
124
|
* SlideOnRemove references is removed.
|
|
153
|
-
* @internal
|
|
154
125
|
*/
|
|
155
126
|
function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWARD, cache, useNewSlidingBehavior = false) {
|
|
156
127
|
if (!segment ||
|
|
@@ -170,7 +141,8 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
|
|
|
170
141
|
return false;
|
|
171
142
|
}
|
|
172
143
|
if (cache !== undefined &&
|
|
173
|
-
(seg
|
|
144
|
+
(toRemovalInfo(seg)?.removedSeq === toRemovalInfo(segment)?.removedSeq ||
|
|
145
|
+
toMoveInfo(seg)?.movedSeq === toMoveInfo(segment)?.movedSeq)) {
|
|
174
146
|
cache.set(seg, result);
|
|
175
147
|
}
|
|
176
148
|
return true;
|
|
@@ -217,7 +189,7 @@ function getSlideToSegment(segment, slidingPreference = SlidingPreference.FORWAR
|
|
|
217
189
|
* @internal
|
|
218
190
|
*/
|
|
219
191
|
export function getSlideToSegoff(segoff, slidingPreference = SlidingPreference.FORWARD, useNewSlidingBehavior = false) {
|
|
220
|
-
if (segoff.segment
|
|
192
|
+
if (!isSegmentLeaf(segoff.segment)) {
|
|
221
193
|
return segoff;
|
|
222
194
|
}
|
|
223
195
|
const [segment, _] = getSlideToSegment(segoff.segment, slidingPreference, undefined, useNewSlidingBehavior);
|
|
@@ -244,7 +216,6 @@ class Obliterates {
|
|
|
244
216
|
* See https://github.com/microsoft/FluidFramework/blob/main/packages/dds/merge-tree/docs/Obliterate.md#remote-perspective
|
|
245
217
|
* for additional context
|
|
246
218
|
*/
|
|
247
|
-
// eslint-disable-next-line import/no-deprecated
|
|
248
219
|
this.seqOrdered = new DoublyLinkedList();
|
|
249
220
|
/**
|
|
250
221
|
* This contains a sorted lists of all obliterate starts
|
|
@@ -262,7 +233,6 @@ class Obliterates {
|
|
|
262
233
|
this.mergeTree.removeLocalReferencePosition(ob.data.end);
|
|
263
234
|
}
|
|
264
235
|
}
|
|
265
|
-
// eslint-disable-next-line import/no-deprecated
|
|
266
236
|
addOrUpdate(obliterateInfo) {
|
|
267
237
|
const { seq, start } = obliterateInfo;
|
|
268
238
|
if (seq !== UnassignedSequenceNumber) {
|
|
@@ -273,14 +243,14 @@ class Obliterates {
|
|
|
273
243
|
empty() {
|
|
274
244
|
return this.startOrdered.size === 0;
|
|
275
245
|
}
|
|
276
|
-
// eslint-disable-next-line import/no-deprecated
|
|
277
246
|
findOverlapping(seg) {
|
|
278
|
-
// eslint-disable-next-line import/no-deprecated
|
|
279
247
|
const overlapping = [];
|
|
280
248
|
for (const start of this.startOrdered.items) {
|
|
281
|
-
|
|
249
|
+
const startSeg = start.getSegment();
|
|
250
|
+
if (isMergeNodeInfo(startSeg) && startSeg.ordinal <= seg.ordinal) {
|
|
282
251
|
const ob = start.properties?.obliterate;
|
|
283
|
-
|
|
252
|
+
const endSeg = ob.end.getSegment();
|
|
253
|
+
if (isMergeNodeInfo(endSeg) && endSeg.ordinal >= seg.ordinal) {
|
|
284
254
|
overlapping.push(ob);
|
|
285
255
|
}
|
|
286
256
|
}
|
|
@@ -298,9 +268,7 @@ class Obliterates {
|
|
|
298
268
|
export class MergeTree {
|
|
299
269
|
constructor(options) {
|
|
300
270
|
this.options = options;
|
|
301
|
-
// eslint-disable-next-line import/no-deprecated
|
|
302
271
|
this.collabWindow = new CollaborationWindow();
|
|
303
|
-
// eslint-disable-next-line import/no-deprecated
|
|
304
272
|
this.pendingSegments = new DoublyLinkedList();
|
|
305
273
|
this.segmentsToScour = new Heap(LRUSegmentComparer);
|
|
306
274
|
/**
|
|
@@ -318,6 +286,7 @@ export class MergeTree {
|
|
|
318
286
|
return {};
|
|
319
287
|
}
|
|
320
288
|
const next = segment.splitAt(pos);
|
|
289
|
+
assertSegmentLeaf(next);
|
|
321
290
|
if (segment?.segmentGroups) {
|
|
322
291
|
next.segmentGroups ?? (next.segmentGroups = new SegmentGroupCollection(next));
|
|
323
292
|
segment.segmentGroups.copyTo(next.segmentGroups);
|
|
@@ -380,7 +349,9 @@ export class MergeTree {
|
|
|
380
349
|
}
|
|
381
350
|
assert(refSeq !== undefined, 0x398 /* localSeq provided for local length without refSeq */);
|
|
382
351
|
assert(segment.seq !== undefined, 0x399 /* segment with no seq in mergeTree */);
|
|
383
|
-
const { seq
|
|
352
|
+
const { seq } = segment;
|
|
353
|
+
const { removedSeq, localRemovedSeq } = removalInfo ?? {};
|
|
354
|
+
const { movedSeq, localMovedSeq } = moveInfo ?? {};
|
|
384
355
|
if (seq === UnassignedSequenceNumber) {
|
|
385
356
|
assert(segment.localSeq !== undefined, 0x39a /* unacked segment with undefined localSeq */);
|
|
386
357
|
// inserted locally, still un-acked
|
|
@@ -416,7 +387,7 @@ export class MergeTree {
|
|
|
416
387
|
}
|
|
417
388
|
addNode(block, node) {
|
|
418
389
|
const index = block.childCount++;
|
|
419
|
-
|
|
390
|
+
assignChild(block, node, index, false);
|
|
420
391
|
return index;
|
|
421
392
|
}
|
|
422
393
|
reloadFromSegments(segments) {
|
|
@@ -510,12 +481,12 @@ export class MergeTree {
|
|
|
510
481
|
assert(localSeq === undefined || clientId === this.collabWindow.clientId, 0x39b /* localSeq provided for non-local client */);
|
|
511
482
|
let segment;
|
|
512
483
|
let offset;
|
|
513
|
-
const leaf = (leafSeg,
|
|
484
|
+
const leaf = (leafSeg, _, start) => {
|
|
514
485
|
segment = leafSeg;
|
|
515
486
|
offset = start;
|
|
516
487
|
return false;
|
|
517
488
|
};
|
|
518
|
-
this.nodeMap(refSeq, clientId, leaf, undefined,
|
|
489
|
+
this.nodeMap(refSeq, clientId, leaf, undefined, pos, pos + 1, localSeq);
|
|
519
490
|
return { segment, offset };
|
|
520
491
|
}
|
|
521
492
|
/**
|
|
@@ -540,9 +511,7 @@ export class MergeTree {
|
|
|
540
511
|
*/
|
|
541
512
|
slideAckedRemovedSegmentReferences(segments) {
|
|
542
513
|
// References are slid in groups to preserve their order.
|
|
543
|
-
// eslint-disable-next-line import/no-deprecated
|
|
544
514
|
let currentForwardSlideGroup = [];
|
|
545
|
-
// eslint-disable-next-line import/no-deprecated
|
|
546
515
|
let currentBackwardSlideGroup = [];
|
|
547
516
|
let currentForwardMaybeEndpoint;
|
|
548
517
|
let currentForwardSlideDestination;
|
|
@@ -550,9 +519,7 @@ export class MergeTree {
|
|
|
550
519
|
let currentBackwardMaybeEndpoint;
|
|
551
520
|
let currentBackwardSlideDestination;
|
|
552
521
|
let currentBackwardSlideIsForward;
|
|
553
|
-
const slideGroup = (currentSlideDestination, currentSlideIsForward,
|
|
554
|
-
// eslint-disable-next-line import/no-deprecated
|
|
555
|
-
currentSlideGroup, pred, maybeEndpoint) => {
|
|
522
|
+
const slideGroup = (currentSlideDestination, currentSlideIsForward, currentSlideGroup, pred, maybeEndpoint) => {
|
|
556
523
|
if (currentSlideIsForward === undefined) {
|
|
557
524
|
return;
|
|
558
525
|
}
|
|
@@ -560,7 +527,6 @@ export class MergeTree {
|
|
|
560
527
|
const endpointRefsToAdd = currentSlideGroup.map((collection) => filterLocalReferencePositions(collection, (ref) => pred(ref) && !!ref.canSlideToEndpoint));
|
|
561
528
|
if (maybeEndpoint) {
|
|
562
529
|
const endpoint = maybeEndpoint === "start" ? this.startOfTree : this.endOfTree;
|
|
563
|
-
// eslint-disable-next-line import/no-deprecated
|
|
564
530
|
const localRefs = LocalReferenceCollection.setOrGet(endpoint);
|
|
565
531
|
if (currentSlideIsForward) {
|
|
566
532
|
localRefs.addBeforeTombstones(...endpointRefsToAdd);
|
|
@@ -581,7 +547,6 @@ export class MergeTree {
|
|
|
581
547
|
}
|
|
582
548
|
}
|
|
583
549
|
else {
|
|
584
|
-
// eslint-disable-next-line import/no-deprecated
|
|
585
550
|
const localRefs = LocalReferenceCollection.setOrGet(currentSlideDestination);
|
|
586
551
|
if (currentSlideIsForward) {
|
|
587
552
|
localRefs.addBeforeTombstones(...nonEndpointRefsToAdd);
|
|
@@ -591,9 +556,7 @@ export class MergeTree {
|
|
|
591
556
|
}
|
|
592
557
|
}
|
|
593
558
|
};
|
|
594
|
-
const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward,
|
|
595
|
-
// eslint-disable-next-line import/no-deprecated
|
|
596
|
-
currentSlideGroup, pred, slidingPreference, currentMaybeEndpoint, reassign) => {
|
|
559
|
+
const trySlideSegment = (segment, currentSlideDestination, currentSlideIsForward, currentSlideGroup, pred, slidingPreference, currentMaybeEndpoint, reassign) => {
|
|
597
560
|
// avoid sliding logic if this segment doesn't have any references
|
|
598
561
|
// with the given sliding preference
|
|
599
562
|
if (!segment.localRefs || !anyLocalReferencePosition(segment.localRefs, pred)) {
|
|
@@ -650,7 +613,6 @@ export class MergeTree {
|
|
|
650
613
|
if (this.localPartialsComputed) {
|
|
651
614
|
return;
|
|
652
615
|
}
|
|
653
|
-
// eslint-disable-next-line import/no-deprecated
|
|
654
616
|
const rebaseCollabWindow = new CollaborationWindow();
|
|
655
617
|
rebaseCollabWindow.loadFrom(this.collabWindow);
|
|
656
618
|
if (refSeq < this.collabWindow.minSeq) {
|
|
@@ -734,24 +696,26 @@ export class MergeTree {
|
|
|
734
696
|
*/
|
|
735
697
|
referencePositionToLocalPosition(refPos, refSeq = Number.MAX_SAFE_INTEGER, clientId = this.collabWindow.clientId, localSeq = this.collabWindow.localSeq) {
|
|
736
698
|
const seg = refPos.getSegment();
|
|
737
|
-
if (seg
|
|
699
|
+
if (!isSegmentLeaf(seg)) {
|
|
738
700
|
// We have no idea where this reference is, because it refers to a segment which is not in the tree.
|
|
739
701
|
return DetachedReferencePosition;
|
|
740
702
|
}
|
|
741
703
|
if (refPos.isLeaf()) {
|
|
742
|
-
return this.getPosition(
|
|
704
|
+
return this.getPosition(seg, refSeq, clientId, localSeq);
|
|
743
705
|
}
|
|
744
706
|
if (refTypeIncludesFlag(refPos, ReferenceType.Transient) || seg.localRefs?.has(refPos)) {
|
|
745
707
|
if (seg !== this.startOfTree &&
|
|
746
708
|
seg !== this.endOfTree &&
|
|
747
709
|
!isSegmentPresent(seg, { refSeq, localSeq })) {
|
|
748
710
|
const forward = refPos.slidingPreference === SlidingPreference.FORWARD;
|
|
749
|
-
const
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
711
|
+
const moveInfo = toMoveInfo(seg);
|
|
712
|
+
const removeInfo = toRemovalInfo(seg);
|
|
713
|
+
const slideSeq = moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber
|
|
714
|
+
? moveInfo.movedSeq
|
|
715
|
+
: removeInfo !== undefined && removeInfo.removedSeq !== UnassignedSequenceNumber
|
|
716
|
+
? removeInfo.removedSeq
|
|
753
717
|
: refSeq;
|
|
754
|
-
const slideLocalSeq =
|
|
718
|
+
const slideLocalSeq = moveInfo?.localMovedSeq ?? removeInfo?.localRemovedSeq;
|
|
755
719
|
const perspective = new PerspectiveImpl(this, {
|
|
756
720
|
refSeq: slideSeq,
|
|
757
721
|
localSeq: slideLocalSeq,
|
|
@@ -779,11 +743,10 @@ export class MergeTree {
|
|
|
779
743
|
searchForMarker(startPos, clientId, markerLabel, forwards = true) {
|
|
780
744
|
let foundMarker;
|
|
781
745
|
const { segment } = this.getContainingSegment(startPos, UniversalSequenceNumber, clientId);
|
|
782
|
-
|
|
783
|
-
if (segWithParent?.parent === undefined) {
|
|
746
|
+
if (!isSegmentLeaf(segment)) {
|
|
784
747
|
return undefined;
|
|
785
748
|
}
|
|
786
|
-
depthFirstNodeWalk(
|
|
749
|
+
depthFirstNodeWalk(segment.parent, segment, (node) => {
|
|
787
750
|
if (node.isLeaf()) {
|
|
788
751
|
if (Marker.is(node) && refHasTileLabel(node, markerLabel)) {
|
|
789
752
|
foundMarker = node;
|
|
@@ -805,8 +768,8 @@ export class MergeTree {
|
|
|
805
768
|
updateRoot(splitNode) {
|
|
806
769
|
if (splitNode !== undefined) {
|
|
807
770
|
const newRoot = this.makeBlock(2);
|
|
808
|
-
|
|
809
|
-
|
|
771
|
+
assignChild(newRoot, this.root, 0, false);
|
|
772
|
+
assignChild(newRoot, splitNode, 1, false);
|
|
810
773
|
this.root = newRoot;
|
|
811
774
|
this.nodeUpdateOrdinals(this.root);
|
|
812
775
|
this.nodeUpdateLengthNewStructure(this.root);
|
|
@@ -862,9 +825,7 @@ export class MergeTree {
|
|
|
862
825
|
zamboniSegments(this);
|
|
863
826
|
}
|
|
864
827
|
}
|
|
865
|
-
addToPendingList(segment,
|
|
866
|
-
// eslint-disable-next-line import/no-deprecated
|
|
867
|
-
segmentGroup, localSeq, previousProps) {
|
|
828
|
+
addToPendingList(segment, segmentGroup, localSeq, previousProps) {
|
|
868
829
|
let _segmentGroup = segmentGroup;
|
|
869
830
|
if (_segmentGroup === undefined) {
|
|
870
831
|
_segmentGroup = {
|
|
@@ -884,7 +845,6 @@ export class MergeTree {
|
|
|
884
845
|
if (previousProps) {
|
|
885
846
|
_segmentGroup.previousProps.push(previousProps);
|
|
886
847
|
}
|
|
887
|
-
// eslint-disable-next-line import/no-deprecated
|
|
888
848
|
const segmentGroups = (segment.segmentGroups ?? (segment.segmentGroups = new SegmentGroupCollection(segment)));
|
|
889
849
|
segmentGroups.enqueue(_segmentGroup);
|
|
890
850
|
return _segmentGroup;
|
|
@@ -911,7 +871,7 @@ export class MergeTree {
|
|
|
911
871
|
if (relativePos.id) {
|
|
912
872
|
marker = this.getMarkerFromId(relativePos.id);
|
|
913
873
|
}
|
|
914
|
-
if (marker) {
|
|
874
|
+
if (isSegmentLeaf(marker)) {
|
|
915
875
|
pos = this.getPosition(marker, refseq, clientId);
|
|
916
876
|
if (relativePos.before) {
|
|
917
877
|
if (relativePos.offset !== undefined) {
|
|
@@ -969,7 +929,7 @@ export class MergeTree {
|
|
|
969
929
|
}
|
|
970
930
|
const segmentInfo = this.getContainingSegment(remoteClientPosition, remoteClientRefSeq, remoteClientId);
|
|
971
931
|
const { currentSeq, clientId } = this.collabWindow;
|
|
972
|
-
if (segmentInfo?.segment) {
|
|
932
|
+
if (isSegmentLeaf(segmentInfo?.segment)) {
|
|
973
933
|
const segmentPosition = this.getPosition(segmentInfo.segment, currentSeq, clientId);
|
|
974
934
|
return segmentPosition + segmentInfo.offset;
|
|
975
935
|
}
|
|
@@ -990,7 +950,6 @@ export class MergeTree {
|
|
|
990
950
|
});
|
|
991
951
|
return siblingExists;
|
|
992
952
|
};
|
|
993
|
-
// eslint-disable-next-line import/no-deprecated
|
|
994
953
|
let segmentGroup;
|
|
995
954
|
const saveIfLocal = (locSegment) => {
|
|
996
955
|
// Save segment so we can assign sequence number when acked by server
|
|
@@ -1020,93 +979,94 @@ export class MergeTree {
|
|
|
1020
979
|
}
|
|
1021
980
|
return segmentChanges;
|
|
1022
981
|
};
|
|
982
|
+
const insertInfo = {
|
|
983
|
+
clientId,
|
|
984
|
+
seq,
|
|
985
|
+
localSeq,
|
|
986
|
+
};
|
|
1023
987
|
// TODO: build tree from segs and insert all at once
|
|
1024
988
|
let insertPos = pos;
|
|
1025
|
-
for (const newSegment of newSegments
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
if (
|
|
1031
|
-
|
|
1032
|
-
if (markerId) {
|
|
1033
|
-
this.idToMarker.set(markerId, newSegment);
|
|
1034
|
-
}
|
|
989
|
+
for (const newSegment of newSegments
|
|
990
|
+
.filter((s) => s.cachedLength > 0)
|
|
991
|
+
.map((s) => overwriteInfo(s, insertInfo))) {
|
|
992
|
+
if (Marker.is(newSegment)) {
|
|
993
|
+
const markerId = newSegment.getId();
|
|
994
|
+
if (markerId) {
|
|
995
|
+
this.idToMarker.set(markerId, newSegment);
|
|
1035
996
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
997
|
+
}
|
|
998
|
+
const splitNode = this.insertingWalk(this.root, insertPos, refSeq, clientId, seq, {
|
|
999
|
+
leaf: onLeaf,
|
|
1000
|
+
candidateSegment: newSegment,
|
|
1001
|
+
continuePredicate: continueFrom,
|
|
1002
|
+
});
|
|
1003
|
+
if (!isSegmentLeaf(newSegment)) {
|
|
1004
|
+
// Indicates an attempt to insert past the end of the merge-tree's content.
|
|
1005
|
+
const errorConstructor = localSeq === undefined ? DataProcessingError : UsageError;
|
|
1006
|
+
throw new errorConstructor("MergeTree insert failed", {
|
|
1007
|
+
currentSeq: this.collabWindow.currentSeq,
|
|
1008
|
+
minSeq: this.collabWindow.minSeq,
|
|
1009
|
+
segSeq: insertInfo.seq,
|
|
1040
1010
|
});
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
|
|
1069
|
-
: ob.seq;
|
|
1070
|
-
if (normalizedObSeq > refSeq) {
|
|
1071
|
-
if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
|
|
1072
|
-
normalizedOldestSeq = normalizedObSeq;
|
|
1073
|
-
oldest = ob;
|
|
1074
|
-
movedClientIds.unshift(ob.clientId);
|
|
1075
|
-
movedSeqs.unshift(ob.seq);
|
|
1076
|
-
}
|
|
1077
|
-
else {
|
|
1078
|
-
movedClientIds.push(ob.clientId);
|
|
1079
|
-
movedSeqs.push(ob.seq);
|
|
1080
|
-
}
|
|
1081
|
-
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1082
|
-
normalizedNewestSeq = normalizedObSeq;
|
|
1083
|
-
newest = ob;
|
|
1084
|
-
}
|
|
1011
|
+
}
|
|
1012
|
+
this.updateRoot(splitNode);
|
|
1013
|
+
insertPos += newSegment.cachedLength;
|
|
1014
|
+
if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
|
|
1015
|
+
saveIfLocal(newSegment);
|
|
1016
|
+
continue;
|
|
1017
|
+
}
|
|
1018
|
+
let oldest;
|
|
1019
|
+
let normalizedOldestSeq = 0;
|
|
1020
|
+
let newest;
|
|
1021
|
+
let normalizedNewestSeq = 0;
|
|
1022
|
+
const movedClientIds = [];
|
|
1023
|
+
const movedSeqs = [];
|
|
1024
|
+
for (const ob of this.obliterates.findOverlapping(newSegment)) {
|
|
1025
|
+
// compute a normalized seq that takes into account local seqs
|
|
1026
|
+
// but is still comparable to remote seqs to keep the checks below easy
|
|
1027
|
+
// REMOTE SEQUENCE NUMBERS LOCAL SEQUENCE NUMBERS
|
|
1028
|
+
// [0, 1, 2, 3, ..., 100, ..., 1000, ..., (MAX - MaxLocalSeq), L1, L2, L3, L4, ..., L100, ..., L1000, ...(MAX)]
|
|
1029
|
+
const normalizedObSeq = ob.seq === UnassignedSequenceNumber
|
|
1030
|
+
? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
|
|
1031
|
+
: ob.seq;
|
|
1032
|
+
if (normalizedObSeq > refSeq) {
|
|
1033
|
+
if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
|
|
1034
|
+
normalizedOldestSeq = normalizedObSeq;
|
|
1035
|
+
oldest = ob;
|
|
1036
|
+
movedClientIds.unshift(ob.clientId);
|
|
1037
|
+
movedSeqs.unshift(ob.seq);
|
|
1085
1038
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
const moveInfo = {
|
|
1090
|
-
movedClientIds,
|
|
1091
|
-
movedSeq: oldest.seq,
|
|
1092
|
-
movedSeqs,
|
|
1093
|
-
localMovedSeq: oldest.localSeq,
|
|
1094
|
-
wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
|
|
1095
|
-
};
|
|
1096
|
-
markSegmentMoved(newSegment, moveInfo);
|
|
1097
|
-
if (moveInfo.localMovedSeq !== undefined) {
|
|
1098
|
-
assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
|
|
1099
|
-
this.addToPendingList(newSegment, oldest.segmentGroup);
|
|
1039
|
+
else {
|
|
1040
|
+
movedClientIds.push(ob.clientId);
|
|
1041
|
+
movedSeqs.push(ob.seq);
|
|
1100
1042
|
}
|
|
1101
|
-
if (
|
|
1102
|
-
|
|
1043
|
+
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1044
|
+
normalizedNewestSeq = normalizedObSeq;
|
|
1045
|
+
newest = ob;
|
|
1103
1046
|
}
|
|
1104
1047
|
}
|
|
1105
|
-
|
|
1106
|
-
|
|
1048
|
+
}
|
|
1049
|
+
if (oldest && newest?.clientId !== clientId) {
|
|
1050
|
+
const moveInfo = {
|
|
1051
|
+
movedClientIds,
|
|
1052
|
+
movedSeq: oldest.seq,
|
|
1053
|
+
movedSeqs,
|
|
1054
|
+
localMovedSeq: oldest.localSeq,
|
|
1055
|
+
wasMovedOnInsert: oldest.seq !== UnassignedSequenceNumber,
|
|
1056
|
+
};
|
|
1057
|
+
overwriteInfo(newSegment, moveInfo);
|
|
1058
|
+
if (moveInfo.localMovedSeq !== undefined) {
|
|
1059
|
+
assert(oldest.segmentGroup !== undefined, 0x86c /* expected segment group to exist */);
|
|
1060
|
+
this.addToPendingList(newSegment, oldest.segmentGroup);
|
|
1061
|
+
}
|
|
1062
|
+
if (newSegment.parent) {
|
|
1063
|
+
this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
|
|
1107
1064
|
}
|
|
1108
|
-
saveIfLocal(newSegment);
|
|
1109
1065
|
}
|
|
1066
|
+
else if (oldest && newest?.clientId === clientId) {
|
|
1067
|
+
newSegment.prevObliterateByInserter = newest;
|
|
1068
|
+
}
|
|
1069
|
+
saveIfLocal(newSegment);
|
|
1110
1070
|
}
|
|
1111
1071
|
}
|
|
1112
1072
|
ensureIntervalBoundary(pos, refSeq, clientId) {
|
|
@@ -1127,10 +1087,8 @@ export class MergeTree {
|
|
|
1127
1087
|
const newSeq = seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER : seq;
|
|
1128
1088
|
const segSeq = node.seq === UnassignedSequenceNumber ? Number.MAX_SAFE_INTEGER - 1 : (node.seq ?? 0);
|
|
1129
1089
|
return (newSeq > segSeq ||
|
|
1130
|
-
(node.movedSeq !==
|
|
1131
|
-
|
|
1132
|
-
node.movedSeq > seq) ||
|
|
1133
|
-
(node.removedSeq !== undefined &&
|
|
1090
|
+
(isMoved(node) && node.movedSeq !== UnassignedSequenceNumber && node.movedSeq > seq) ||
|
|
1091
|
+
(isRemoved(node) &&
|
|
1134
1092
|
node.removedSeq !== UnassignedSequenceNumber &&
|
|
1135
1093
|
node.removedSeq > seq));
|
|
1136
1094
|
}
|
|
@@ -1162,7 +1120,7 @@ export class MergeTree {
|
|
|
1162
1120
|
const segment = child;
|
|
1163
1121
|
const segmentChanges = context.leaf(segment, _pos, context);
|
|
1164
1122
|
if (segmentChanges.replaceCurrent) {
|
|
1165
|
-
|
|
1123
|
+
assignChild(block, segmentChanges.replaceCurrent, childIndex, false);
|
|
1166
1124
|
segmentChanges.replaceCurrent.ordinal = child.ordinal;
|
|
1167
1125
|
}
|
|
1168
1126
|
if (segmentChanges.next) {
|
|
@@ -1213,7 +1171,7 @@ export class MergeTree {
|
|
|
1213
1171
|
block.children[i] = block.children[i - 1];
|
|
1214
1172
|
block.children[i].index = i;
|
|
1215
1173
|
}
|
|
1216
|
-
|
|
1174
|
+
assignChild(block, newNode, childIndex, false);
|
|
1217
1175
|
block.childCount++;
|
|
1218
1176
|
block.setOrdinal(newNode, childIndex);
|
|
1219
1177
|
if (block.childCount < MaxNodesInBlock) {
|
|
@@ -1242,7 +1200,7 @@ export class MergeTree {
|
|
|
1242
1200
|
// Update ordinals to reflect lowered child count
|
|
1243
1201
|
this.nodeUpdateOrdinals(node);
|
|
1244
1202
|
for (let i = 0; i < halfCount; i++) {
|
|
1245
|
-
|
|
1203
|
+
assignChild(newNode, node.children[halfCount + i], i, false);
|
|
1246
1204
|
node.children[halfCount + i] = undefined;
|
|
1247
1205
|
}
|
|
1248
1206
|
this.nodeUpdateLengthNewStructure(node);
|
|
@@ -1269,9 +1227,7 @@ export class MergeTree {
|
|
|
1269
1227
|
* @param opArgs - The op args for the annotate op. this is passed to the merge tree callback if there is one
|
|
1270
1228
|
* @param rollback - Whether this is for a local rollback and what kind
|
|
1271
1229
|
*/
|
|
1272
|
-
annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs,
|
|
1273
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1274
|
-
rollback = PropertiesRollback.None) {
|
|
1230
|
+
annotateRange(start, end, propsOrAdjust, refSeq, clientId, seq, opArgs, rollback = PropertiesRollback.None) {
|
|
1275
1231
|
if (propsOrAdjust.adjust !== undefined) {
|
|
1276
1232
|
errorIfOptionNotTrue(this.options, "mergeTreeEnableAnnotateAdjust");
|
|
1277
1233
|
}
|
|
@@ -1279,7 +1235,6 @@ export class MergeTree {
|
|
|
1279
1235
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1280
1236
|
const deltaSegments = [];
|
|
1281
1237
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1282
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1283
1238
|
let segmentGroup;
|
|
1284
1239
|
const opObj = propsOrAdjust.props ?? propsOrAdjust.adjust;
|
|
1285
1240
|
const annotateSegment = (segment) => {
|
|
@@ -1303,7 +1258,7 @@ export class MergeTree {
|
|
|
1303
1258
|
}
|
|
1304
1259
|
return true;
|
|
1305
1260
|
};
|
|
1306
|
-
this.nodeMap(refSeq, clientId, annotateSegment, undefined,
|
|
1261
|
+
this.nodeMap(refSeq, clientId, annotateSegment, undefined, start, end);
|
|
1307
1262
|
// OpArgs == undefined => test code
|
|
1308
1263
|
if (deltaSegments.length > 0) {
|
|
1309
1264
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
@@ -1326,7 +1281,6 @@ export class MergeTree {
|
|
|
1326
1281
|
const localOverlapWithRefs = [];
|
|
1327
1282
|
const movedSegments = [];
|
|
1328
1283
|
const localSeq = seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1329
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1330
1284
|
const obliterate = {
|
|
1331
1285
|
clientId,
|
|
1332
1286
|
end: createDetachedLocalReferencePosition(undefined),
|
|
@@ -1338,7 +1292,7 @@ export class MergeTree {
|
|
|
1338
1292
|
};
|
|
1339
1293
|
const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
|
|
1340
1294
|
const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
|
|
1341
|
-
assert(startSeg
|
|
1295
|
+
assert(isSegmentLeaf(startSeg) && isSegmentLeaf(endSeg), 0xa3f /* segments cannot be undefined */);
|
|
1342
1296
|
obliterate.start = this.createLocalReferencePosition(startSeg, start.side === Side.Before ? 0 : Math.max(startSeg.cachedLength - 1, 0), ReferenceType.StayOnRemove, {
|
|
1343
1297
|
obliterate,
|
|
1344
1298
|
});
|
|
@@ -1359,7 +1313,7 @@ export class MergeTree {
|
|
|
1359
1313
|
this.pendingSegments.push(obliterate.segmentGroup);
|
|
1360
1314
|
}
|
|
1361
1315
|
this.obliterates.addOrUpdate(obliterate);
|
|
1362
|
-
const markMoved = (segment, pos
|
|
1316
|
+
const markMoved = (segment, pos) => {
|
|
1363
1317
|
if ((start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
|
|
1364
1318
|
(end.side === Side.Before &&
|
|
1365
1319
|
endPos === pos &&
|
|
@@ -1376,23 +1330,26 @@ export class MergeTree {
|
|
|
1376
1330
|
// Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
|
|
1377
1331
|
return true;
|
|
1378
1332
|
}
|
|
1379
|
-
|
|
1333
|
+
const wasMovedOnInsert = clientId !== segment.clientId &&
|
|
1380
1334
|
segment.seq !== undefined &&
|
|
1381
1335
|
seq !== UnassignedSequenceNumber &&
|
|
1382
|
-
(refSeq < segment.seq || segment.seq === UnassignedSequenceNumber)
|
|
1383
|
-
segment.wasMovedOnInsert = true;
|
|
1384
|
-
}
|
|
1336
|
+
(refSeq < segment.seq || segment.seq === UnassignedSequenceNumber);
|
|
1385
1337
|
if (existingMoveInfo === undefined) {
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1338
|
+
const movedSeg = overwriteInfo(segment, {
|
|
1339
|
+
movedClientIds: [clientId],
|
|
1340
|
+
movedSeq: seq,
|
|
1341
|
+
localMovedSeq: localSeq,
|
|
1342
|
+
movedSeqs: [seq],
|
|
1343
|
+
wasMovedOnInsert,
|
|
1344
|
+
});
|
|
1345
|
+
if (!toRemovalInfo(movedSeg)) {
|
|
1346
|
+
movedSegments.push(movedSeg);
|
|
1392
1347
|
}
|
|
1393
1348
|
}
|
|
1394
1349
|
else {
|
|
1395
1350
|
_overwrite = true;
|
|
1351
|
+
// never move wasMovedOnInsert from true to false
|
|
1352
|
+
existingMoveInfo.wasMovedOnInsert || (existingMoveInfo.wasMovedOnInsert = wasMovedOnInsert);
|
|
1396
1353
|
if (existingMoveInfo.movedSeq === UnassignedSequenceNumber) {
|
|
1397
1354
|
// we moved this locally, but someone else moved it first
|
|
1398
1355
|
// so put them at the head of the list
|
|
@@ -1411,6 +1368,7 @@ export class MergeTree {
|
|
|
1411
1368
|
existingMoveInfo.movedSeqs.push(seq);
|
|
1412
1369
|
}
|
|
1413
1370
|
}
|
|
1371
|
+
assertMoved(segment);
|
|
1414
1372
|
// Save segment so can assign moved sequence number when acked by server
|
|
1415
1373
|
if (this.collabWindow.collaborating) {
|
|
1416
1374
|
if (segment.movedSeq === UnassignedSequenceNumber &&
|
|
@@ -1425,7 +1383,7 @@ export class MergeTree {
|
|
|
1425
1383
|
}
|
|
1426
1384
|
return true;
|
|
1427
1385
|
};
|
|
1428
|
-
const afterMarkMoved = (node
|
|
1386
|
+
const afterMarkMoved = (node) => {
|
|
1429
1387
|
if (_overwrite) {
|
|
1430
1388
|
this.nodeUpdateLengthNewStructure(node);
|
|
1431
1389
|
}
|
|
@@ -1434,21 +1392,21 @@ export class MergeTree {
|
|
|
1434
1392
|
}
|
|
1435
1393
|
return true;
|
|
1436
1394
|
};
|
|
1437
|
-
this.nodeMap(refSeq, clientId, markMoved,
|
|
1395
|
+
this.nodeMap(refSeq, clientId, markMoved, afterMarkMoved, start.pos, end.pos + 1, // include the segment containing the end reference
|
|
1438
1396
|
undefined, seq === UnassignedSequenceNumber ? undefined : seq);
|
|
1439
1397
|
this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
|
|
1440
1398
|
// opArgs == undefined => test code
|
|
1441
1399
|
if (start.pos !== end.pos || start.side !== end.side) {
|
|
1442
1400
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
1443
1401
|
operation: MergeTreeDeltaType.OBLITERATE,
|
|
1444
|
-
deltaSegments: movedSegments,
|
|
1402
|
+
deltaSegments: movedSegments.map((segment) => ({ segment })),
|
|
1445
1403
|
});
|
|
1446
1404
|
}
|
|
1447
1405
|
// these events are newly removed
|
|
1448
1406
|
// so we slide after eventing in case the consumer wants to make reference
|
|
1449
1407
|
// changes at remove time, like add a ref to track undo redo.
|
|
1450
1408
|
if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
|
|
1451
|
-
this.slideAckedRemovedSegmentReferences(movedSegments
|
|
1409
|
+
this.slideAckedRemovedSegmentReferences(movedSegments);
|
|
1452
1410
|
}
|
|
1453
1411
|
if (this.collabWindow.collaborating &&
|
|
1454
1412
|
seq !== UnassignedSequenceNumber &&
|
|
@@ -1471,7 +1429,6 @@ export class MergeTree {
|
|
|
1471
1429
|
let _overwrite = false;
|
|
1472
1430
|
this.ensureIntervalBoundary(start, refSeq, clientId);
|
|
1473
1431
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1474
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1475
1432
|
let segmentGroup;
|
|
1476
1433
|
const removedSegments = [];
|
|
1477
1434
|
const localOverlapWithRefs = [];
|
|
@@ -1479,11 +1436,13 @@ export class MergeTree {
|
|
|
1479
1436
|
const markRemoved = (segment, pos, _start, _end) => {
|
|
1480
1437
|
const existingRemovalInfo = toRemovalInfo(segment);
|
|
1481
1438
|
if (existingRemovalInfo === undefined) {
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1439
|
+
const removed = overwriteInfo(segment, {
|
|
1440
|
+
removedClientIds: [clientId],
|
|
1441
|
+
removedSeq: seq,
|
|
1442
|
+
localRemovedSeq: localSeq,
|
|
1443
|
+
});
|
|
1444
|
+
if (!toMoveInfo(removed)) {
|
|
1445
|
+
removedSegments.push(removed);
|
|
1487
1446
|
}
|
|
1488
1447
|
}
|
|
1489
1448
|
else {
|
|
@@ -1504,6 +1463,7 @@ export class MergeTree {
|
|
|
1504
1463
|
existingRemovalInfo.removedClientIds.push(clientId);
|
|
1505
1464
|
}
|
|
1506
1465
|
}
|
|
1466
|
+
assertRemoved(segment);
|
|
1507
1467
|
// Save segment so we can assign removed sequence number when acked by server
|
|
1508
1468
|
if (this.collabWindow.collaborating) {
|
|
1509
1469
|
if (segment.removedSeq === UnassignedSequenceNumber &&
|
|
@@ -1518,7 +1478,7 @@ export class MergeTree {
|
|
|
1518
1478
|
}
|
|
1519
1479
|
return true;
|
|
1520
1480
|
};
|
|
1521
|
-
const afterMarkRemoved = (node
|
|
1481
|
+
const afterMarkRemoved = (node) => {
|
|
1522
1482
|
if (_overwrite) {
|
|
1523
1483
|
this.nodeUpdateLengthNewStructure(node);
|
|
1524
1484
|
}
|
|
@@ -1527,7 +1487,7 @@ export class MergeTree {
|
|
|
1527
1487
|
}
|
|
1528
1488
|
return true;
|
|
1529
1489
|
};
|
|
1530
|
-
this.nodeMap(refSeq, clientId, markRemoved,
|
|
1490
|
+
this.nodeMap(refSeq, clientId, markRemoved, afterMarkRemoved, start, end);
|
|
1531
1491
|
// these segments are already viewed as being removed locally and are not event-ed
|
|
1532
1492
|
// so can slide non-StayOnRemove refs immediately
|
|
1533
1493
|
this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
|
|
@@ -1535,14 +1495,14 @@ export class MergeTree {
|
|
|
1535
1495
|
if (removedSegments.length > 0) {
|
|
1536
1496
|
this.mergeTreeDeltaCallback?.(opArgs, {
|
|
1537
1497
|
operation: MergeTreeDeltaType.REMOVE,
|
|
1538
|
-
deltaSegments: removedSegments,
|
|
1498
|
+
deltaSegments: removedSegments.map((segment) => ({ segment })),
|
|
1539
1499
|
});
|
|
1540
1500
|
}
|
|
1541
1501
|
// these events are newly removed
|
|
1542
1502
|
// so we slide after eventing in case the consumer wants to make reference
|
|
1543
1503
|
// changes at remove time, like add a ref to track undo redo.
|
|
1544
1504
|
if (!this.collabWindow.collaborating || clientId !== this.collabWindow.clientId) {
|
|
1545
|
-
this.slideAckedRemovedSegmentReferences(removedSegments
|
|
1505
|
+
this.slideAckedRemovedSegmentReferences(removedSegments);
|
|
1546
1506
|
}
|
|
1547
1507
|
if (this.collabWindow.collaborating &&
|
|
1548
1508
|
seq !== UnassignedSequenceNumber &&
|
|
@@ -1553,24 +1513,21 @@ export class MergeTree {
|
|
|
1553
1513
|
/**
|
|
1554
1514
|
* Revert an unacked local op
|
|
1555
1515
|
*/
|
|
1556
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1557
1516
|
rollback(op, localOpMetadata) {
|
|
1558
1517
|
if (op.type === MergeTreeDeltaType.REMOVE) {
|
|
1559
|
-
const pendingSegmentGroup = this.pendingSegments.pop
|
|
1518
|
+
const pendingSegmentGroup = this.pendingSegments.pop()?.data;
|
|
1560
1519
|
if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
|
|
1561
1520
|
throw new Error("Rollback op doesn't match last edit");
|
|
1562
1521
|
}
|
|
1563
1522
|
// Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
|
|
1564
1523
|
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1565
1524
|
pendingSegmentGroup.segments.forEach((segment) => {
|
|
1566
|
-
const segmentSegmentGroup = segment?.segmentGroups?.pop
|
|
1525
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop();
|
|
1567
1526
|
assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ee /* Unexpected segmentGroup in segment */);
|
|
1568
|
-
assert(segment.removedClientIds
|
|
1569
|
-
|
|
1570
|
-
segment
|
|
1571
|
-
|
|
1572
|
-
segment.localRemovedSeq = undefined;
|
|
1573
|
-
for (let updateNode = segment.parent; updateNode !== undefined; updateNode = updateNode.parent) {
|
|
1527
|
+
assert(isRemoved(segment) && segment.removedClientIds[0] === this.collabWindow.clientId, 0x39d /* Rollback segment removedClientId does not match local client */);
|
|
1528
|
+
let updateNode = segment.parent;
|
|
1529
|
+
removeRemovalInfo(segment);
|
|
1530
|
+
for (updateNode; updateNode !== undefined; updateNode = updateNode.parent) {
|
|
1574
1531
|
this.blockUpdateLength(updateNode, UnassignedSequenceNumber, this.collabWindow.clientId);
|
|
1575
1532
|
}
|
|
1576
1533
|
// Note: optional chaining short-circuits:
|
|
@@ -1583,7 +1540,7 @@ export class MergeTree {
|
|
|
1583
1540
|
}
|
|
1584
1541
|
else if (op.type === MergeTreeDeltaType.INSERT ||
|
|
1585
1542
|
op.type === MergeTreeDeltaType.ANNOTATE) {
|
|
1586
|
-
const pendingSegmentGroup = this.pendingSegments.pop
|
|
1543
|
+
const pendingSegmentGroup = this.pendingSegments.pop()?.data;
|
|
1587
1544
|
if (pendingSegmentGroup === undefined ||
|
|
1588
1545
|
pendingSegmentGroup !== localOpMetadata ||
|
|
1589
1546
|
(op.type === MergeTreeDeltaType.ANNOTATE && !pendingSegmentGroup.previousProps)) {
|
|
@@ -1591,7 +1548,7 @@ export class MergeTree {
|
|
|
1591
1548
|
}
|
|
1592
1549
|
let i = 0;
|
|
1593
1550
|
for (const segment of pendingSegmentGroup.segments) {
|
|
1594
|
-
const segmentSegmentGroup = segment?.segmentGroups?.pop
|
|
1551
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop();
|
|
1595
1552
|
assert(segmentSegmentGroup === pendingSegmentGroup, 0x3ef /* Unexpected segmentGroup in segment */);
|
|
1596
1553
|
const start = this.findRollbackPosition(segment);
|
|
1597
1554
|
if (op.type === MergeTreeDeltaType.INSERT) {
|
|
@@ -1623,7 +1580,7 @@ export class MergeTree {
|
|
|
1623
1580
|
return false;
|
|
1624
1581
|
}
|
|
1625
1582
|
// If not removed, increase position
|
|
1626
|
-
if (seg
|
|
1583
|
+
if (!isRemoved(seg)) {
|
|
1627
1584
|
segmentPosition += seg.cachedLength;
|
|
1628
1585
|
}
|
|
1629
1586
|
return true;
|
|
@@ -1657,9 +1614,9 @@ export class MergeTree {
|
|
|
1657
1614
|
segment = this.endOfTree;
|
|
1658
1615
|
}
|
|
1659
1616
|
else {
|
|
1617
|
+
assertSegmentLeaf(_segment);
|
|
1660
1618
|
segment = _segment;
|
|
1661
1619
|
}
|
|
1662
|
-
// eslint-disable-next-line import/no-deprecated
|
|
1663
1620
|
const localRefs = LocalReferenceCollection.setOrGet(segment);
|
|
1664
1621
|
const segRef = localRefs.createLocalRef(offset, refType, properties, slidingPreference, canSlideToEndpoint);
|
|
1665
1622
|
return segRef;
|
|
@@ -1721,7 +1678,7 @@ export class MergeTree {
|
|
|
1721
1678
|
for (let i = 0; i < newOrder.length; i++) {
|
|
1722
1679
|
const seg = newOrder[i];
|
|
1723
1680
|
const { parent, index, ordinal } = currentOrder[i];
|
|
1724
|
-
|
|
1681
|
+
assignChild(parent, seg, index, false);
|
|
1725
1682
|
seg.ordinal = ordinal;
|
|
1726
1683
|
}
|
|
1727
1684
|
for (const [segment, groups] of perSegmentTrackingGroups.entries()) {
|
|
@@ -1888,7 +1845,7 @@ export class MergeTree {
|
|
|
1888
1845
|
this.ensureIntervalBoundary(end, refSeq, clientId);
|
|
1889
1846
|
}
|
|
1890
1847
|
}
|
|
1891
|
-
this.nodeMap(refSeq, clientId, handler, accum, undefined, start, end, undefined, visibilitySeq);
|
|
1848
|
+
this.nodeMap(refSeq, clientId, (seg, pos, _start, _end) => handler(seg, pos, refSeq, clientId, _start, _end, accum), undefined, start, end, undefined, visibilitySeq);
|
|
1892
1849
|
}
|
|
1893
1850
|
/**
|
|
1894
1851
|
* Map over all visible segments in a given range
|
|
@@ -1913,7 +1870,7 @@ export class MergeTree {
|
|
|
1913
1870
|
* but it will not count as a segment within the range. That is, it will be
|
|
1914
1871
|
* ignored for the purposes of tracking when traversal should end.
|
|
1915
1872
|
*/
|
|
1916
|
-
nodeMap(refSeq, clientId, leaf,
|
|
1873
|
+
nodeMap(refSeq, clientId, leaf, post, start = 0, end, localSeq, visibilitySeq = refSeq) {
|
|
1917
1874
|
const endPos = end ?? this.nodeLength(this.root, refSeq, clientId, localSeq) ?? 0;
|
|
1918
1875
|
if (endPos === start) {
|
|
1919
1876
|
return;
|
|
@@ -1940,14 +1897,12 @@ export class MergeTree {
|
|
|
1940
1897
|
return NodeAction.Skip;
|
|
1941
1898
|
}
|
|
1942
1899
|
if (node.isLeaf()) {
|
|
1943
|
-
if (leaf(node, pos,
|
|
1900
|
+
if (leaf(node, pos, start - pos, endPos - pos) === false) {
|
|
1944
1901
|
return NodeAction.Exit;
|
|
1945
1902
|
}
|
|
1946
1903
|
pos = nextPos;
|
|
1947
1904
|
}
|
|
1948
|
-
}, undefined, post
|
|
1949
|
-
? undefined
|
|
1950
|
-
: (block) => post(block, pos, refSeq, clientId, start - pos, endPos - pos, accum));
|
|
1905
|
+
}, undefined, post);
|
|
1951
1906
|
}
|
|
1952
1907
|
}
|
|
1953
1908
|
MergeTree.options = {
|