@fluidframework/merge-tree 2.4.0-294316 → 2.4.0-297385
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/api-report/merge-tree.legacy.alpha.api.md +25 -5
- package/dist/attributionPolicy.d.ts.map +1 -1
- package/dist/attributionPolicy.js +10 -3
- package/dist/attributionPolicy.js.map +1 -1
- package/dist/client.d.ts +14 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +97 -9
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/legacy.d.ts +1 -0
- package/dist/localReference.d.ts +1 -1
- package/dist/localReference.d.ts.map +1 -1
- package/dist/localReference.js.map +1 -1
- package/dist/mergeTree.d.ts +22 -8
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +98 -24
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeNodes.d.ts +27 -2
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +2 -18
- package/dist/mergeTreeNodes.js.map +1 -1
- package/dist/opBuilder.d.ts +15 -1
- package/dist/opBuilder.d.ts.map +1 -1
- package/dist/opBuilder.js +28 -1
- package/dist/opBuilder.js.map +1 -1
- package/dist/ops.d.ts +27 -1
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +1 -0
- package/dist/ops.js.map +1 -1
- package/dist/revertibles.d.ts.map +1 -1
- package/dist/revertibles.js +4 -2
- package/dist/revertibles.js.map +1 -1
- package/dist/sequencePlace.d.ts +4 -0
- package/dist/sequencePlace.d.ts.map +1 -1
- package/dist/sequencePlace.js +17 -1
- package/dist/sequencePlace.js.map +1 -1
- package/dist/snapshotV1.d.ts.map +1 -1
- package/dist/snapshotV1.js +0 -2
- package/dist/snapshotV1.js.map +1 -1
- package/dist/snapshotlegacy.d.ts.map +1 -1
- package/dist/snapshotlegacy.js +0 -1
- package/dist/snapshotlegacy.js.map +1 -1
- package/dist/test/client.annotateMarker.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +3 -3
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.rollback.spec.js.map +1 -1
- package/dist/test/mergeTree.annotate.spec.js +29 -19
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/obliterate.concurrent.spec.js +18 -0
- package/dist/test/obliterate.concurrent.spec.js.map +1 -1
- package/dist/test/obliterate.rangeExpansion.spec.js +109 -53
- package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/dist/test/obliterate.spec.js +2 -2
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/reconnectHelper.d.ts +8 -6
- package/dist/test/reconnectHelper.d.ts.map +1 -1
- package/dist/test/reconnectHelper.js +14 -13
- package/dist/test/reconnectHelper.js.map +1 -1
- package/dist/test/revertibleFarm.spec.js.map +1 -1
- package/dist/test/testClientLogger.d.ts.map +1 -1
- package/dist/test/testClientLogger.js +19 -8
- package/dist/test/testClientLogger.js.map +1 -1
- package/dist/zamboni.js +2 -1
- package/dist/zamboni.js.map +1 -1
- package/lib/attributionPolicy.d.ts.map +1 -1
- package/lib/attributionPolicy.js +10 -3
- package/lib/attributionPolicy.js.map +1 -1
- package/lib/client.d.ts +14 -4
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +98 -10
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +2 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/legacy.d.ts +1 -0
- package/lib/localReference.d.ts +1 -1
- package/lib/localReference.d.ts.map +1 -1
- package/lib/localReference.js.map +1 -1
- package/lib/mergeTree.d.ts +22 -8
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +100 -26
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeNodes.d.ts +27 -2
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +2 -18
- package/lib/mergeTreeNodes.js.map +1 -1
- package/lib/opBuilder.d.ts +15 -1
- package/lib/opBuilder.d.ts.map +1 -1
- package/lib/opBuilder.js +26 -0
- package/lib/opBuilder.js.map +1 -1
- package/lib/ops.d.ts +27 -1
- package/lib/ops.d.ts.map +1 -1
- package/lib/ops.js +1 -0
- package/lib/ops.js.map +1 -1
- package/lib/revertibles.d.ts.map +1 -1
- package/lib/revertibles.js +5 -3
- package/lib/revertibles.js.map +1 -1
- package/lib/sequencePlace.d.ts +4 -0
- package/lib/sequencePlace.d.ts.map +1 -1
- package/lib/sequencePlace.js +15 -0
- package/lib/sequencePlace.js.map +1 -1
- package/lib/snapshotV1.d.ts.map +1 -1
- package/lib/snapshotV1.js +0 -2
- package/lib/snapshotV1.js.map +1 -1
- package/lib/snapshotlegacy.d.ts.map +1 -1
- package/lib/snapshotlegacy.js +0 -1
- package/lib/snapshotlegacy.js.map +1 -1
- package/lib/test/client.annotateMarker.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +3 -3
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.rollback.spec.js.map +1 -1
- package/lib/test/mergeTree.annotate.spec.js +29 -19
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/obliterate.concurrent.spec.js +18 -0
- package/lib/test/obliterate.concurrent.spec.js.map +1 -1
- package/lib/test/obliterate.rangeExpansion.spec.js +109 -53
- package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/lib/test/obliterate.spec.js +2 -2
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/reconnectHelper.d.ts +8 -6
- package/lib/test/reconnectHelper.d.ts.map +1 -1
- package/lib/test/reconnectHelper.js +15 -14
- package/lib/test/reconnectHelper.js.map +1 -1
- package/lib/test/revertibleFarm.spec.js.map +1 -1
- package/lib/test/testClientLogger.d.ts.map +1 -1
- package/lib/test/testClientLogger.js +19 -8
- package/lib/test/testClientLogger.js.map +1 -1
- package/lib/zamboni.js +2 -1
- package/lib/zamboni.js.map +1 -1
- package/package.json +31 -18
- package/src/attributionPolicy.ts +5 -0
- package/src/client.ts +136 -21
- package/src/index.ts +2 -0
- package/src/localReference.ts +5 -5
- package/src/mergeTree.ts +200 -75
- package/src/mergeTreeNodes.ts +37 -23
- package/src/opBuilder.ts +32 -0
- package/src/ops.ts +23 -1
- package/src/revertibles.ts +12 -5
- package/src/sequencePlace.ts +16 -0
- package/src/snapshotV1.ts +0 -2
- package/src/snapshotlegacy.ts +0 -1
- package/src/zamboni.ts +3 -2
package/src/mergeTree.ts
CHANGED
|
@@ -49,7 +49,6 @@ import {
|
|
|
49
49
|
IMergeNode,
|
|
50
50
|
IMoveInfo,
|
|
51
51
|
IRemovalInfo,
|
|
52
|
-
ISegment,
|
|
53
52
|
ISegmentAction,
|
|
54
53
|
ISegmentChanges,
|
|
55
54
|
ISegmentLeaf,
|
|
@@ -63,6 +62,7 @@ import {
|
|
|
63
62
|
seqLTE,
|
|
64
63
|
toMoveInfo,
|
|
65
64
|
toRemovalInfo,
|
|
65
|
+
type ISegmentInternal,
|
|
66
66
|
// eslint-disable-next-line import/no-deprecated
|
|
67
67
|
type ObliterateInfo,
|
|
68
68
|
} from "./mergeTreeNodes.js";
|
|
@@ -80,7 +80,7 @@ import {
|
|
|
80
80
|
} from "./ops.js";
|
|
81
81
|
import { PartialSequenceLengths } from "./partialLengths.js";
|
|
82
82
|
import { PerspectiveImpl, isSegmentPresent } from "./perspective.js";
|
|
83
|
-
import { PropertySet, createMap, extend, extendIfUndefined } from "./properties.js";
|
|
83
|
+
import { PropertySet, clone, createMap, extend, extendIfUndefined } from "./properties.js";
|
|
84
84
|
import {
|
|
85
85
|
DetachedReferencePosition,
|
|
86
86
|
ReferencePosition,
|
|
@@ -89,11 +89,14 @@ import {
|
|
|
89
89
|
refTypeIncludesFlag,
|
|
90
90
|
} from "./referencePositions.js";
|
|
91
91
|
// eslint-disable-next-line import/no-deprecated
|
|
92
|
-
import {
|
|
92
|
+
import { SegmentGroupCollection } from "./segmentGroupCollection.js";
|
|
93
|
+
// eslint-disable-next-line import/no-deprecated
|
|
94
|
+
import { PropertiesManager, PropertiesRollback } from "./segmentPropertiesManager.js";
|
|
95
|
+
import { Side, type InteriorSequencePlace } from "./sequencePlace.js";
|
|
93
96
|
import { SortedSegmentSet } from "./sortedSegmentSet.js";
|
|
94
97
|
import { zamboniSegments } from "./zamboni.js";
|
|
95
98
|
|
|
96
|
-
function markSegmentMoved(seg:
|
|
99
|
+
function markSegmentMoved(seg: ISegmentLeaf, moveInfo: IMoveInfo): void {
|
|
97
100
|
seg.moveDst = moveInfo.moveDst;
|
|
98
101
|
seg.movedClientIds = [...moveInfo.movedClientIds];
|
|
99
102
|
seg.movedSeqs = [moveInfo.movedSeq];
|
|
@@ -102,29 +105,29 @@ function markSegmentMoved(seg: ISegment, moveInfo: IMoveInfo): void {
|
|
|
102
105
|
seg.wasMovedOnInsert = moveInfo.wasMovedOnInsert;
|
|
103
106
|
}
|
|
104
107
|
|
|
105
|
-
function isMoved(segment:
|
|
108
|
+
function isMoved(segment: ISegmentLeaf): segment is ISegmentLeaf & IMoveInfo {
|
|
106
109
|
return toMoveInfo(segment) !== undefined;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
|
-
function isRemoved(segment:
|
|
112
|
+
function isRemoved(segment: ISegmentLeaf): segment is ISegmentLeaf & IRemovalInfo {
|
|
110
113
|
return toRemovalInfo(segment) !== undefined;
|
|
111
114
|
}
|
|
112
115
|
|
|
113
|
-
function isRemovedAndAcked(segment:
|
|
116
|
+
function isRemovedAndAcked(segment: ISegmentLeaf): segment is ISegmentLeaf & IRemovalInfo {
|
|
114
117
|
const removalInfo = toRemovalInfo(segment);
|
|
115
118
|
return removalInfo !== undefined && removalInfo.removedSeq !== UnassignedSequenceNumber;
|
|
116
119
|
}
|
|
117
120
|
|
|
118
|
-
function isMovedAndAcked(segment:
|
|
121
|
+
function isMovedAndAcked(segment: ISegmentLeaf): segment is ISegmentLeaf & IMoveInfo {
|
|
119
122
|
const moveInfo = toMoveInfo(segment);
|
|
120
123
|
return moveInfo !== undefined && moveInfo.movedSeq !== UnassignedSequenceNumber;
|
|
121
124
|
}
|
|
122
125
|
|
|
123
|
-
function isRemovedAndAckedOrMovedAndAcked(segment:
|
|
126
|
+
function isRemovedAndAckedOrMovedAndAcked(segment: ISegmentLeaf): boolean {
|
|
124
127
|
return isRemovedAndAcked(segment) || isMovedAndAcked(segment);
|
|
125
128
|
}
|
|
126
129
|
|
|
127
|
-
function isRemovedOrMoved(segment:
|
|
130
|
+
function isRemovedOrMoved(segment: ISegmentLeaf): boolean {
|
|
128
131
|
return isRemoved(segment) || isMoved(segment);
|
|
129
132
|
}
|
|
130
133
|
|
|
@@ -197,6 +200,17 @@ export interface IMergeTreeOptions {
|
|
|
197
200
|
* @defaultValue `false`
|
|
198
201
|
*/
|
|
199
202
|
mergeTreeEnableObliterateReconnect?: boolean;
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Enables support for obliterate endpoint expansion.
|
|
206
|
+
* When enabled, obliterate operations can have sidedness specified for their endpoints.
|
|
207
|
+
* If an endpoint is externally anchored
|
|
208
|
+
* (aka the start is after a given position, or the end is before a given position),
|
|
209
|
+
* then concurrent inserts adjacent to the exclusive endpoint of an obliterated range will be included in the obliteration
|
|
210
|
+
*
|
|
211
|
+
* @defaultValue `false`
|
|
212
|
+
*/
|
|
213
|
+
mergeTreeEnableSidedObliterate?: boolean;
|
|
200
214
|
}
|
|
201
215
|
export function errorIfOptionNotTrue(
|
|
202
216
|
options: IMergeTreeOptions | undefined,
|
|
@@ -210,6 +224,7 @@ export function errorIfOptionNotTrue(
|
|
|
210
224
|
/**
|
|
211
225
|
* @legacy
|
|
212
226
|
* @alpha
|
|
227
|
+
* @deprecated This functionality was not meant to be exported and will be removed in a future release
|
|
213
228
|
*/
|
|
214
229
|
export interface IMergeTreeAttributionOptions {
|
|
215
230
|
/**
|
|
@@ -237,6 +252,7 @@ export interface IMergeTreeAttributionOptions {
|
|
|
237
252
|
* @sealed
|
|
238
253
|
* @legacy
|
|
239
254
|
* @alpha
|
|
255
|
+
* @deprecated This functionality was not meant to be exported and will be removed in a future release
|
|
240
256
|
*/
|
|
241
257
|
export interface AttributionPolicy {
|
|
242
258
|
/**
|
|
@@ -301,11 +317,11 @@ export function findRootMergeBlock(
|
|
|
301
317
|
* @internal
|
|
302
318
|
*/
|
|
303
319
|
function getSlideToSegment(
|
|
304
|
-
segment:
|
|
320
|
+
segment: ISegmentLeaf | undefined,
|
|
305
321
|
slidingPreference: SlidingPreference = SlidingPreference.FORWARD,
|
|
306
|
-
cache?: Map<
|
|
322
|
+
cache?: Map<ISegmentLeaf, { seg?: ISegmentLeaf }>,
|
|
307
323
|
useNewSlidingBehavior: boolean = false,
|
|
308
|
-
): [
|
|
324
|
+
): [ISegmentLeaf | undefined, "start" | "end" | undefined] {
|
|
309
325
|
if (
|
|
310
326
|
!segment ||
|
|
311
327
|
!isRemovedAndAckedOrMovedAndAcked(segment) ||
|
|
@@ -318,9 +334,9 @@ function getSlideToSegment(
|
|
|
318
334
|
if (cachedSegment !== undefined) {
|
|
319
335
|
return [cachedSegment.seg, undefined];
|
|
320
336
|
}
|
|
321
|
-
const result: { seg?:
|
|
337
|
+
const result: { seg?: ISegmentLeaf } = {};
|
|
322
338
|
cache?.set(segment, result);
|
|
323
|
-
const goFurtherToFindSlideToSegment = (seg:
|
|
339
|
+
const goFurtherToFindSlideToSegment = (seg: ISegmentLeaf): boolean => {
|
|
324
340
|
if (seg.seq !== UnassignedSequenceNumber && !isRemovedAndAckedOrMovedAndAcked(seg)) {
|
|
325
341
|
result.seg = seg;
|
|
326
342
|
return false;
|
|
@@ -378,11 +394,11 @@ function getSlideToSegment(
|
|
|
378
394
|
* @internal
|
|
379
395
|
*/
|
|
380
396
|
export function getSlideToSegoff(
|
|
381
|
-
segoff: { segment:
|
|
397
|
+
segoff: { segment: ISegmentInternal | undefined; offset: number | undefined },
|
|
382
398
|
slidingPreference: SlidingPreference = SlidingPreference.FORWARD,
|
|
383
399
|
useNewSlidingBehavior: boolean = false,
|
|
384
400
|
): {
|
|
385
|
-
segment:
|
|
401
|
+
segment: ISegmentInternal | undefined;
|
|
386
402
|
offset: number | undefined;
|
|
387
403
|
} {
|
|
388
404
|
if (segoff.segment === undefined) {
|
|
@@ -456,7 +472,7 @@ class Obliterates {
|
|
|
456
472
|
}
|
|
457
473
|
|
|
458
474
|
// eslint-disable-next-line import/no-deprecated
|
|
459
|
-
public findOverlapping(seg:
|
|
475
|
+
public findOverlapping(seg: ISegmentLeaf): Iterable<ObliterateInfo> {
|
|
460
476
|
// eslint-disable-next-line import/no-deprecated
|
|
461
477
|
const overlapping: ObliterateInfo[] = [];
|
|
462
478
|
for (const start of this.startOrdered.items) {
|
|
@@ -541,7 +557,7 @@ export class MergeTree {
|
|
|
541
557
|
* numbers corresponding to un-acked operations give valid results.
|
|
542
558
|
*/
|
|
543
559
|
public localNetLength(
|
|
544
|
-
segment:
|
|
560
|
+
segment: ISegmentLeaf,
|
|
545
561
|
refSeq?: number,
|
|
546
562
|
localSeq?: number,
|
|
547
563
|
): number | undefined {
|
|
@@ -617,7 +633,7 @@ export class MergeTree {
|
|
|
617
633
|
return index;
|
|
618
634
|
}
|
|
619
635
|
|
|
620
|
-
public reloadFromSegments(segments:
|
|
636
|
+
public reloadFromSegments(segments: ISegmentLeaf[]): void {
|
|
621
637
|
// This code assumes that a later call to `startCollaboration()` will initialize partial lengths.
|
|
622
638
|
assert(
|
|
623
639
|
!this.collabWindow.collaborating,
|
|
@@ -728,7 +744,7 @@ export class MergeTree {
|
|
|
728
744
|
return totalOffset;
|
|
729
745
|
}
|
|
730
746
|
|
|
731
|
-
public getContainingSegment<T extends
|
|
747
|
+
public getContainingSegment<T extends ISegmentLeaf>(
|
|
732
748
|
pos: number,
|
|
733
749
|
refSeq: number,
|
|
734
750
|
clientId: number,
|
|
@@ -745,7 +761,7 @@ export class MergeTree {
|
|
|
745
761
|
let offset: number | undefined;
|
|
746
762
|
|
|
747
763
|
const leaf = (
|
|
748
|
-
leafSeg:
|
|
764
|
+
leafSeg: ISegmentLeaf,
|
|
749
765
|
segpos: number,
|
|
750
766
|
_refSeq: number,
|
|
751
767
|
_clientId: number,
|
|
@@ -779,17 +795,17 @@ export class MergeTree {
|
|
|
779
795
|
*
|
|
780
796
|
* @param segments - An array of (not necessarily contiguous) segments with increasing ordinals.
|
|
781
797
|
*/
|
|
782
|
-
private slideAckedRemovedSegmentReferences(segments:
|
|
798
|
+
private slideAckedRemovedSegmentReferences(segments: ISegmentLeaf[]): void {
|
|
783
799
|
// References are slid in groups to preserve their order.
|
|
784
800
|
let currentForwardSlideGroup: LocalReferenceCollection[] = [];
|
|
785
801
|
let currentBackwardSlideGroup: LocalReferenceCollection[] = [];
|
|
786
802
|
|
|
787
803
|
let currentForwardMaybeEndpoint: "start" | "end" | undefined;
|
|
788
|
-
let currentForwardSlideDestination:
|
|
804
|
+
let currentForwardSlideDestination: ISegmentLeaf | undefined;
|
|
789
805
|
let currentForwardSlideIsForward: boolean | undefined;
|
|
790
806
|
|
|
791
807
|
let currentBackwardMaybeEndpoint: "start" | "end" | undefined;
|
|
792
|
-
let currentBackwardSlideDestination:
|
|
808
|
+
let currentBackwardSlideDestination: ISegmentLeaf | undefined;
|
|
793
809
|
let currentBackwardSlideIsForward: boolean | undefined;
|
|
794
810
|
|
|
795
811
|
const slideGroup = (
|
|
@@ -848,8 +864,8 @@ export class MergeTree {
|
|
|
848
864
|
};
|
|
849
865
|
|
|
850
866
|
const trySlideSegment = (
|
|
851
|
-
segment:
|
|
852
|
-
currentSlideDestination:
|
|
867
|
+
segment: ISegmentLeaf,
|
|
868
|
+
currentSlideDestination: ISegmentLeaf | undefined,
|
|
853
869
|
currentSlideIsForward: boolean | undefined,
|
|
854
870
|
currentSlideGroup: LocalReferenceCollection[],
|
|
855
871
|
pred: (ref: LocalReferencePosition) => boolean,
|
|
@@ -857,7 +873,7 @@ export class MergeTree {
|
|
|
857
873
|
currentMaybeEndpoint: "start" | "end" | undefined,
|
|
858
874
|
reassign: (
|
|
859
875
|
localRefs: LocalReferenceCollection,
|
|
860
|
-
slideToSegment:
|
|
876
|
+
slideToSegment: ISegmentLeaf | undefined,
|
|
861
877
|
slideIsForward: boolean,
|
|
862
878
|
maybeEndpoint: "start" | "end" | undefined,
|
|
863
879
|
) => void,
|
|
@@ -902,8 +918,8 @@ export class MergeTree {
|
|
|
902
918
|
}
|
|
903
919
|
};
|
|
904
920
|
|
|
905
|
-
const forwardSegmentCache = new Map<
|
|
906
|
-
const backwardSegmentCache = new Map<
|
|
921
|
+
const forwardSegmentCache = new Map<ISegmentLeaf, { seg?: ISegmentLeaf }>();
|
|
922
|
+
const backwardSegmentCache = new Map<ISegmentLeaf, { seg?: ISegmentLeaf }>();
|
|
907
923
|
for (const segment of segments) {
|
|
908
924
|
assert(
|
|
909
925
|
isRemovedAndAckedOrMovedAndAcked(segment),
|
|
@@ -1234,7 +1250,10 @@ export class MergeTree {
|
|
|
1234
1250
|
});
|
|
1235
1251
|
});
|
|
1236
1252
|
|
|
1237
|
-
if (
|
|
1253
|
+
if (
|
|
1254
|
+
opArgs.op.type === MergeTreeDeltaType.OBLITERATE ||
|
|
1255
|
+
opArgs.op.type === MergeTreeDeltaType.OBLITERATE_SIDED
|
|
1256
|
+
) {
|
|
1238
1257
|
this.obliterates.addOrUpdate(pendingSegmentGroup.obliterateInfo!);
|
|
1239
1258
|
}
|
|
1240
1259
|
|
|
@@ -1242,7 +1261,8 @@ export class MergeTree {
|
|
|
1242
1261
|
// positions after slide are final
|
|
1243
1262
|
if (
|
|
1244
1263
|
opArgs.op.type === MergeTreeDeltaType.REMOVE ||
|
|
1245
|
-
opArgs.op.type === MergeTreeDeltaType.OBLITERATE
|
|
1264
|
+
opArgs.op.type === MergeTreeDeltaType.OBLITERATE ||
|
|
1265
|
+
opArgs.op.type === MergeTreeDeltaType.OBLITERATE_SIDED
|
|
1246
1266
|
) {
|
|
1247
1267
|
this.slideAckedRemovedSegmentReferences(pendingSegmentGroup.segments);
|
|
1248
1268
|
}
|
|
@@ -1265,7 +1285,7 @@ export class MergeTree {
|
|
|
1265
1285
|
}
|
|
1266
1286
|
|
|
1267
1287
|
private addToPendingList(
|
|
1268
|
-
segment:
|
|
1288
|
+
segment: ISegmentLeaf,
|
|
1269
1289
|
// eslint-disable-next-line import/no-deprecated
|
|
1270
1290
|
segmentGroup?: SegmentGroup,
|
|
1271
1291
|
localSeq?: number,
|
|
@@ -1294,8 +1314,9 @@ export class MergeTree {
|
|
|
1294
1314
|
if (previousProps) {
|
|
1295
1315
|
_segmentGroup.previousProps!.push(previousProps);
|
|
1296
1316
|
}
|
|
1297
|
-
|
|
1298
|
-
segment.segmentGroups
|
|
1317
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1318
|
+
const segmentGroups = (segment.segmentGroups ??= new SegmentGroupCollection(segment));
|
|
1319
|
+
segmentGroups.enqueue(_segmentGroup);
|
|
1299
1320
|
return _segmentGroup;
|
|
1300
1321
|
}
|
|
1301
1322
|
|
|
@@ -1344,7 +1365,7 @@ export class MergeTree {
|
|
|
1344
1365
|
|
|
1345
1366
|
public insertSegments(
|
|
1346
1367
|
pos: number,
|
|
1347
|
-
segments:
|
|
1368
|
+
segments: ISegmentLeaf[],
|
|
1348
1369
|
refSeq: number,
|
|
1349
1370
|
clientId: number,
|
|
1350
1371
|
seq: number,
|
|
@@ -1441,7 +1462,7 @@ export class MergeTree {
|
|
|
1441
1462
|
};
|
|
1442
1463
|
// eslint-disable-next-line import/no-deprecated
|
|
1443
1464
|
let segmentGroup: SegmentGroup;
|
|
1444
|
-
const saveIfLocal = (locSegment:
|
|
1465
|
+
const saveIfLocal = (locSegment: ISegmentLeaf): void => {
|
|
1445
1466
|
// Save segment so we can assign sequence number when acked by server
|
|
1446
1467
|
if (this.collabWindow.collaborating) {
|
|
1447
1468
|
if (
|
|
@@ -1462,7 +1483,7 @@ export class MergeTree {
|
|
|
1462
1483
|
}
|
|
1463
1484
|
};
|
|
1464
1485
|
const onLeaf = (
|
|
1465
|
-
segment:
|
|
1486
|
+
segment: ISegmentLeaf | undefined,
|
|
1466
1487
|
_pos: number,
|
|
1467
1488
|
context: InsertContext,
|
|
1468
1489
|
// Keeping this function within the scope of blockInsert for readability.
|
|
@@ -1510,11 +1531,11 @@ export class MergeTree {
|
|
|
1510
1531
|
}
|
|
1511
1532
|
|
|
1512
1533
|
this.updateRoot(splitNode);
|
|
1513
|
-
saveIfLocal(newSegment);
|
|
1514
1534
|
|
|
1515
1535
|
insertPos += newSegment.cachedLength;
|
|
1516
1536
|
|
|
1517
1537
|
if (!this.options?.mergeTreeEnableObliterate || this.obliterates.empty()) {
|
|
1538
|
+
saveIfLocal(newSegment);
|
|
1518
1539
|
continue;
|
|
1519
1540
|
}
|
|
1520
1541
|
|
|
@@ -1542,13 +1563,13 @@ export class MergeTree {
|
|
|
1542
1563
|
movedClientIds.unshift(ob.clientId);
|
|
1543
1564
|
movedSeqs.unshift(ob.seq);
|
|
1544
1565
|
} else {
|
|
1545
|
-
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1546
|
-
normalizedNewestSeq = normalizedObSeq;
|
|
1547
|
-
newest = ob;
|
|
1548
|
-
}
|
|
1549
1566
|
movedClientIds.push(ob.clientId);
|
|
1550
1567
|
movedSeqs.push(ob.seq);
|
|
1551
1568
|
}
|
|
1569
|
+
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1570
|
+
normalizedNewestSeq = normalizedObSeq;
|
|
1571
|
+
newest = ob;
|
|
1572
|
+
}
|
|
1552
1573
|
}
|
|
1553
1574
|
}
|
|
1554
1575
|
|
|
@@ -1575,20 +1596,52 @@ export class MergeTree {
|
|
|
1575
1596
|
if (newSegment.parent) {
|
|
1576
1597
|
this.blockUpdatePathLengths(newSegment.parent, seq, clientId);
|
|
1577
1598
|
}
|
|
1599
|
+
} else if (oldest && newest?.clientId === clientId) {
|
|
1600
|
+
newSegment.prevObliterateByInserter = newest;
|
|
1578
1601
|
}
|
|
1602
|
+
|
|
1603
|
+
saveIfLocal(newSegment);
|
|
1579
1604
|
}
|
|
1580
1605
|
}
|
|
1581
1606
|
}
|
|
1582
1607
|
|
|
1583
1608
|
private readonly splitLeafSegment = (
|
|
1584
|
-
segment:
|
|
1609
|
+
segment: ISegmentLeaf | undefined,
|
|
1585
1610
|
pos: number,
|
|
1586
1611
|
): ISegmentChanges => {
|
|
1587
1612
|
if (!(pos > 0 && segment)) {
|
|
1588
1613
|
return {};
|
|
1589
1614
|
}
|
|
1590
1615
|
|
|
1591
|
-
const next = segment.splitAt(pos)!;
|
|
1616
|
+
const next: ISegmentLeaf = segment.splitAt(pos)!;
|
|
1617
|
+
|
|
1618
|
+
if (segment?.segmentGroups) {
|
|
1619
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1620
|
+
next.segmentGroups ??= new SegmentGroupCollection(next);
|
|
1621
|
+
segment.segmentGroups.copyTo(next);
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
if (segment.prevObliterateByInserter) {
|
|
1625
|
+
next.prevObliterateByInserter = segment.prevObliterateByInserter;
|
|
1626
|
+
}
|
|
1627
|
+
|
|
1628
|
+
if (segment.properties) {
|
|
1629
|
+
if (segment.propertyManager === undefined) {
|
|
1630
|
+
next.properties = clone(segment.properties);
|
|
1631
|
+
} else {
|
|
1632
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1633
|
+
next.propertyManager ??= new PropertiesManager();
|
|
1634
|
+
next.properties = segment.propertyManager.copyTo(
|
|
1635
|
+
segment.properties,
|
|
1636
|
+
next.properties,
|
|
1637
|
+
next.propertyManager,
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
if (segment.localRefs) {
|
|
1642
|
+
segment.localRefs.split(pos, next);
|
|
1643
|
+
}
|
|
1644
|
+
|
|
1592
1645
|
this.mergeTreeMaintenanceCallback?.(
|
|
1593
1646
|
{
|
|
1594
1647
|
operation: MergeTreeMaintenanceType.SPLIT,
|
|
@@ -1805,6 +1858,7 @@ export class MergeTree {
|
|
|
1805
1858
|
clientId: number,
|
|
1806
1859
|
seq: number,
|
|
1807
1860
|
opArgs: IMergeTreeDeltaOpArgs,
|
|
1861
|
+
|
|
1808
1862
|
// eslint-disable-next-line import/no-deprecated
|
|
1809
1863
|
rollback: PropertiesRollback = PropertiesRollback.None,
|
|
1810
1864
|
): void {
|
|
@@ -1815,19 +1869,25 @@ export class MergeTree {
|
|
|
1815
1869
|
seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1816
1870
|
// eslint-disable-next-line import/no-deprecated
|
|
1817
1871
|
let segmentGroup: SegmentGroup | undefined;
|
|
1818
|
-
const annotateSegment = (segment:
|
|
1872
|
+
const annotateSegment = (segment: ISegmentLeaf): boolean => {
|
|
1819
1873
|
assert(
|
|
1820
1874
|
!Marker.is(segment) ||
|
|
1821
1875
|
!(reservedMarkerIdKey in props) ||
|
|
1822
1876
|
props.markerId === segment.properties?.markerId,
|
|
1823
1877
|
0x5ad /* Cannot change the markerId of an existing marker */,
|
|
1824
1878
|
);
|
|
1825
|
-
|
|
1879
|
+
|
|
1880
|
+
// eslint-disable-next-line import/no-deprecated
|
|
1881
|
+
const propertyManager = (segment.propertyManager ??= new PropertiesManager());
|
|
1882
|
+
const properties = (segment.properties ??= createMap());
|
|
1883
|
+
const propertyDeltas = propertyManager.addProperties(
|
|
1884
|
+
properties,
|
|
1826
1885
|
props,
|
|
1827
1886
|
seq,
|
|
1828
1887
|
this.collabWindow.collaborating,
|
|
1829
1888
|
rollback,
|
|
1830
1889
|
);
|
|
1890
|
+
|
|
1831
1891
|
if (!isRemovedOrMoved(segment)) {
|
|
1832
1892
|
deltaSegments.push({ segment, propertyDeltas });
|
|
1833
1893
|
}
|
|
@@ -1866,22 +1926,23 @@ export class MergeTree {
|
|
|
1866
1926
|
}
|
|
1867
1927
|
}
|
|
1868
1928
|
|
|
1869
|
-
|
|
1870
|
-
start:
|
|
1871
|
-
end:
|
|
1929
|
+
private obliterateRangeSided(
|
|
1930
|
+
start: InteriorSequencePlace,
|
|
1931
|
+
end: InteriorSequencePlace,
|
|
1872
1932
|
refSeq: number,
|
|
1873
1933
|
clientId: number,
|
|
1874
1934
|
seq: number,
|
|
1875
1935
|
overwrite: boolean = false,
|
|
1876
1936
|
opArgs: IMergeTreeDeltaOpArgs,
|
|
1877
1937
|
): void {
|
|
1878
|
-
|
|
1938
|
+
const startPos = start.side === Side.Before ? start.pos : start.pos + 1;
|
|
1939
|
+
const endPos = end.side === Side.Before ? end.pos : end.pos + 1;
|
|
1879
1940
|
|
|
1880
|
-
this.ensureIntervalBoundary(
|
|
1881
|
-
this.ensureIntervalBoundary(
|
|
1941
|
+
this.ensureIntervalBoundary(startPos, refSeq, clientId);
|
|
1942
|
+
this.ensureIntervalBoundary(endPos, refSeq, clientId);
|
|
1882
1943
|
|
|
1883
1944
|
let _overwrite = overwrite;
|
|
1884
|
-
const localOverlapWithRefs:
|
|
1945
|
+
const localOverlapWithRefs: ISegmentLeaf[] = [];
|
|
1885
1946
|
const movedSegments: IMergeTreeSegmentDelta[] = [];
|
|
1886
1947
|
const localSeq =
|
|
1887
1948
|
seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
@@ -1896,8 +1957,8 @@ export class MergeTree {
|
|
|
1896
1957
|
segmentGroup: undefined,
|
|
1897
1958
|
};
|
|
1898
1959
|
|
|
1899
|
-
const { segment: startSeg } = this.getContainingSegment(start, refSeq, clientId);
|
|
1900
|
-
const { segment: endSeg } = this.getContainingSegment(end
|
|
1960
|
+
const { segment: startSeg } = this.getContainingSegment(start.pos, refSeq, clientId);
|
|
1961
|
+
const { segment: endSeg } = this.getContainingSegment(end.pos, refSeq, clientId);
|
|
1901
1962
|
assert(
|
|
1902
1963
|
startSeg !== undefined && endSeg !== undefined,
|
|
1903
1964
|
0xa3f /* segments cannot be undefined */,
|
|
@@ -1905,7 +1966,7 @@ export class MergeTree {
|
|
|
1905
1966
|
|
|
1906
1967
|
obliterate.start = this.createLocalReferencePosition(
|
|
1907
1968
|
startSeg,
|
|
1908
|
-
0,
|
|
1969
|
+
start.side === Side.Before ? 0 : Math.max(startSeg.cachedLength - 1, 0),
|
|
1909
1970
|
ReferenceType.StayOnRemove,
|
|
1910
1971
|
{
|
|
1911
1972
|
obliterate,
|
|
@@ -1914,20 +1975,53 @@ export class MergeTree {
|
|
|
1914
1975
|
|
|
1915
1976
|
obliterate.end = this.createLocalReferencePosition(
|
|
1916
1977
|
endSeg,
|
|
1917
|
-
endSeg.cachedLength - 1,
|
|
1978
|
+
end.side === Side.Before ? 0 : Math.max(endSeg.cachedLength - 1, 0),
|
|
1918
1979
|
ReferenceType.StayOnRemove,
|
|
1919
1980
|
{
|
|
1920
1981
|
obliterate,
|
|
1921
1982
|
},
|
|
1922
1983
|
);
|
|
1923
1984
|
|
|
1985
|
+
// Always create a segment group for obliterate,
|
|
1986
|
+
// even if there are no segments currently in the obliteration range.
|
|
1987
|
+
// Segments may be concurrently inserted into the obliteration range,
|
|
1988
|
+
// at which point they are added to the segment group.
|
|
1989
|
+
obliterate.segmentGroup = {
|
|
1990
|
+
segments: [],
|
|
1991
|
+
localSeq,
|
|
1992
|
+
refSeq: this.collabWindow.currentSeq,
|
|
1993
|
+
obliterateInfo: obliterate,
|
|
1994
|
+
};
|
|
1995
|
+
if (this.collabWindow.collaborating && clientId === this.collabWindow.clientId) {
|
|
1996
|
+
this.pendingSegments.push(obliterate.segmentGroup);
|
|
1997
|
+
}
|
|
1998
|
+
this.obliterates.addOrUpdate(obliterate);
|
|
1999
|
+
|
|
1924
2000
|
const markMoved = (
|
|
1925
|
-
segment:
|
|
2001
|
+
segment: ISegmentLeaf,
|
|
1926
2002
|
pos: number,
|
|
1927
2003
|
_start: number,
|
|
1928
2004
|
_end: number,
|
|
1929
2005
|
): boolean => {
|
|
2006
|
+
if (
|
|
2007
|
+
(start.side === Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
|
|
2008
|
+
(end.side === Side.Before &&
|
|
2009
|
+
endPos === pos &&
|
|
2010
|
+
isSegmentPresent(segment, { refSeq, localSeq })) // exclusive end segment
|
|
2011
|
+
) {
|
|
2012
|
+
// We walk these segments because we want to also walk any concurrently inserted segments between here and the obliterated segments.
|
|
2013
|
+
// These segments are outside of the obliteration range though, so return true to keep walking.
|
|
2014
|
+
return true;
|
|
2015
|
+
}
|
|
1930
2016
|
const existingMoveInfo = toMoveInfo(segment);
|
|
2017
|
+
|
|
2018
|
+
if (segment.prevObliterateByInserter?.seq === UnassignedSequenceNumber) {
|
|
2019
|
+
// We chose to not obliterate this segment because we are aware of an unacked local obliteration.
|
|
2020
|
+
// The local obliterate has not been sequenced yet, so it is still the newest obliterate we are aware of.
|
|
2021
|
+
// Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
|
|
2022
|
+
return true;
|
|
2023
|
+
}
|
|
2024
|
+
|
|
1931
2025
|
if (
|
|
1932
2026
|
clientId !== segment.clientId &&
|
|
1933
2027
|
segment.seq !== undefined &&
|
|
@@ -1978,7 +2072,6 @@ export class MergeTree {
|
|
|
1978
2072
|
obliterate.segmentGroup,
|
|
1979
2073
|
localSeq,
|
|
1980
2074
|
);
|
|
1981
|
-
obliterate.segmentGroup.obliterateInfo ??= obliterate;
|
|
1982
2075
|
} else {
|
|
1983
2076
|
if (MergeTree.options.zamboniSegments) {
|
|
1984
2077
|
this.addToLRUSet(segment, seq);
|
|
@@ -2008,14 +2101,12 @@ export class MergeTree {
|
|
|
2008
2101
|
markMoved,
|
|
2009
2102
|
undefined,
|
|
2010
2103
|
afterMarkMoved,
|
|
2011
|
-
start,
|
|
2012
|
-
end,
|
|
2104
|
+
start.pos,
|
|
2105
|
+
end.pos + 1, // include the segment containing the end reference
|
|
2013
2106
|
undefined,
|
|
2014
2107
|
seq === UnassignedSequenceNumber ? undefined : seq,
|
|
2015
2108
|
);
|
|
2016
2109
|
|
|
2017
|
-
this.obliterates.addOrUpdate(obliterate);
|
|
2018
|
-
|
|
2019
2110
|
this.slideAckedRemovedSegmentReferences(localOverlapWithRefs);
|
|
2020
2111
|
// opArgs == undefined => test code
|
|
2021
2112
|
if (movedSegments.length > 0) {
|
|
@@ -2041,6 +2132,39 @@ export class MergeTree {
|
|
|
2041
2132
|
}
|
|
2042
2133
|
}
|
|
2043
2134
|
|
|
2135
|
+
public obliterateRange(
|
|
2136
|
+
start: number | InteriorSequencePlace,
|
|
2137
|
+
end: number | InteriorSequencePlace,
|
|
2138
|
+
refSeq: number,
|
|
2139
|
+
clientId: number,
|
|
2140
|
+
seq: number,
|
|
2141
|
+
overwrite: boolean = false,
|
|
2142
|
+
opArgs: IMergeTreeDeltaOpArgs,
|
|
2143
|
+
): void {
|
|
2144
|
+
errorIfOptionNotTrue(this.options, "mergeTreeEnableObliterate");
|
|
2145
|
+
if (this.options?.mergeTreeEnableSidedObliterate) {
|
|
2146
|
+
assert(
|
|
2147
|
+
typeof start === "object" && typeof end === "object",
|
|
2148
|
+
"Start and end must be of type InteriorSequencePlace if mergeTreeEnableSidedObliterate is enabled.",
|
|
2149
|
+
);
|
|
2150
|
+
this.obliterateRangeSided(start, end, refSeq, clientId, seq, overwrite, opArgs);
|
|
2151
|
+
} else {
|
|
2152
|
+
assert(
|
|
2153
|
+
typeof start === "number" && typeof end === "number",
|
|
2154
|
+
"Start and end must be numbers if mergeTreeEnableSidedObliterate is not enabled.",
|
|
2155
|
+
);
|
|
2156
|
+
this.obliterateRangeSided(
|
|
2157
|
+
{ pos: start, side: Side.Before },
|
|
2158
|
+
{ pos: end - 1, side: Side.After },
|
|
2159
|
+
refSeq,
|
|
2160
|
+
clientId,
|
|
2161
|
+
seq,
|
|
2162
|
+
overwrite,
|
|
2163
|
+
opArgs,
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2044
2168
|
public markRangeRemoved(
|
|
2045
2169
|
start: number,
|
|
2046
2170
|
end: number,
|
|
@@ -2056,11 +2180,11 @@ export class MergeTree {
|
|
|
2056
2180
|
// eslint-disable-next-line import/no-deprecated
|
|
2057
2181
|
let segmentGroup: SegmentGroup;
|
|
2058
2182
|
const removedSegments: IMergeTreeSegmentDelta[] = [];
|
|
2059
|
-
const localOverlapWithRefs:
|
|
2183
|
+
const localOverlapWithRefs: ISegmentLeaf[] = [];
|
|
2060
2184
|
const localSeq =
|
|
2061
2185
|
seq === UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
2062
2186
|
const markRemoved = (
|
|
2063
|
-
segment:
|
|
2187
|
+
segment: ISegmentLeaf,
|
|
2064
2188
|
pos: number,
|
|
2065
2189
|
_start: number,
|
|
2066
2190
|
_end: number,
|
|
@@ -2159,10 +2283,10 @@ export class MergeTree {
|
|
|
2159
2283
|
if (pendingSegmentGroup === undefined || pendingSegmentGroup !== localOpMetadata) {
|
|
2160
2284
|
throw new Error("Rollback op doesn't match last edit");
|
|
2161
2285
|
}
|
|
2162
|
-
// Disabling because a for of loop causes the type of segment to be
|
|
2286
|
+
// Disabling because a for of loop causes the type of segment to be ISegmentLeaf, which does not have parent information stored
|
|
2163
2287
|
// eslint-disable-next-line unicorn/no-array-for-each
|
|
2164
2288
|
pendingSegmentGroup.segments.forEach((segment: ISegmentLeaf) => {
|
|
2165
|
-
const segmentSegmentGroup = segment
|
|
2289
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
|
|
2166
2290
|
assert(
|
|
2167
2291
|
segmentSegmentGroup === pendingSegmentGroup,
|
|
2168
2292
|
0x3ee /* Unexpected segmentGroup in segment */,
|
|
@@ -2212,8 +2336,8 @@ export class MergeTree {
|
|
|
2212
2336
|
throw new Error("Rollback op doesn't match last edit");
|
|
2213
2337
|
}
|
|
2214
2338
|
let i = 0;
|
|
2215
|
-
for (const segment of pendingSegmentGroup.segments) {
|
|
2216
|
-
const segmentSegmentGroup = segment
|
|
2339
|
+
for (const segment of pendingSegmentGroup.segments as ISegmentLeaf[]) {
|
|
2340
|
+
const segmentSegmentGroup = segment?.segmentGroups?.pop?.();
|
|
2217
2341
|
assert(
|
|
2218
2342
|
segmentSegmentGroup === pendingSegmentGroup,
|
|
2219
2343
|
0x3ef /* Unexpected segmentGroup in segment */,
|
|
@@ -2244,6 +2368,7 @@ export class MergeTree {
|
|
|
2244
2368
|
this.collabWindow.clientId,
|
|
2245
2369
|
UniversalSequenceNumber,
|
|
2246
2370
|
{ op: annotateOp },
|
|
2371
|
+
|
|
2247
2372
|
// eslint-disable-next-line import/no-deprecated
|
|
2248
2373
|
PropertiesRollback.Rollback,
|
|
2249
2374
|
);
|
|
@@ -2258,7 +2383,7 @@ export class MergeTree {
|
|
|
2258
2383
|
/**
|
|
2259
2384
|
* Walk the segments up to the current segment and calculate its position
|
|
2260
2385
|
*/
|
|
2261
|
-
private findRollbackPosition(segment:
|
|
2386
|
+
private findRollbackPosition(segment: ISegmentLeaf): number {
|
|
2262
2387
|
let segmentPosition = 0;
|
|
2263
2388
|
walkAllChildSegments(this.root, (seg) => {
|
|
2264
2389
|
// If we've found the desired segment, terminate the walk and return 'segmentPosition'.
|
|
@@ -2361,7 +2486,7 @@ export class MergeTree {
|
|
|
2361
2486
|
}
|
|
2362
2487
|
|
|
2363
2488
|
for (
|
|
2364
|
-
let segmentToSlide: ListNode<
|
|
2489
|
+
let segmentToSlide: ListNode<ISegmentLeaf> | undefined = lastLocalSegment,
|
|
2365
2490
|
nearerSegment = lastLocalSegment?.prev;
|
|
2366
2491
|
segmentToSlide !== undefined;
|
|
2367
2492
|
segmentToSlide = nearerSegment, nearerSegment = nearerSegment?.prev
|
|
@@ -2399,7 +2524,7 @@ export class MergeTree {
|
|
|
2399
2524
|
const newOrder = Array.from(affectedSegments, ({ data }) => data);
|
|
2400
2525
|
for (const seg of newOrder)
|
|
2401
2526
|
seg.localRefs?.walkReferences((lref) => lref.callbacks?.beforeSlide?.(lref));
|
|
2402
|
-
const perSegmentTrackingGroups = new Map<
|
|
2527
|
+
const perSegmentTrackingGroups = new Map<ISegmentLeaf, TrackingGroup[]>();
|
|
2403
2528
|
for (const segment of newOrder) {
|
|
2404
2529
|
const { trackingCollection } = segment;
|
|
2405
2530
|
const trackingGroups = [...trackingCollection.trackingGroups];
|
|
@@ -2464,7 +2589,7 @@ export class MergeTree {
|
|
|
2464
2589
|
* it can fix up its local state to align with what would be expected of the op it resubmits.
|
|
2465
2590
|
*/
|
|
2466
2591
|
public normalizeSegmentsOnRebase(): void {
|
|
2467
|
-
let currentRangeToNormalize = new DoublyLinkedList<
|
|
2592
|
+
let currentRangeToNormalize = new DoublyLinkedList<ISegmentLeaf>();
|
|
2468
2593
|
let rangeContainsLocalSegs = false;
|
|
2469
2594
|
let rangeContainsRemoteRemovedSegs = false;
|
|
2470
2595
|
const normalize = (): void => {
|
|
@@ -2487,7 +2612,7 @@ export class MergeTree {
|
|
|
2487
2612
|
currentRangeToNormalize.push(seg);
|
|
2488
2613
|
} else {
|
|
2489
2614
|
normalize();
|
|
2490
|
-
currentRangeToNormalize = new DoublyLinkedList<
|
|
2615
|
+
currentRangeToNormalize = new DoublyLinkedList<ISegmentLeaf>();
|
|
2491
2616
|
rangeContainsLocalSegs = false;
|
|
2492
2617
|
rangeContainsRemoteRemovedSegs = false;
|
|
2493
2618
|
}
|