@fluidframework/merge-tree 2.21.0 → 2.23.0-323641
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/.eslintrc.cjs +0 -1
- package/CHANGELOG.md +4 -0
- package/README.md +1 -0
- package/dist/attributionCollection.js +5 -7
- package/dist/attributionCollection.js.map +1 -1
- package/dist/localReference.js +6 -8
- package/dist/localReference.js.map +1 -1
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +69 -34
- package/dist/mergeTree.js.map +1 -1
- package/dist/mergeTreeNodes.d.ts +15 -4
- package/dist/mergeTreeNodes.d.ts.map +1 -1
- package/dist/mergeTreeNodes.js +1 -1
- package/dist/mergeTreeNodes.js.map +1 -1
- package/dist/partialLengths.d.ts +114 -144
- package/dist/partialLengths.d.ts.map +1 -1
- package/dist/partialLengths.js +431 -525
- package/dist/partialLengths.js.map +1 -1
- package/dist/perspective.d.ts +10 -1
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +10 -1
- package/dist/perspective.js.map +1 -1
- package/dist/properties.d.ts.map +1 -1
- package/dist/properties.js +2 -3
- package/dist/properties.js.map +1 -1
- package/dist/revertibles.js +3 -3
- package/dist/revertibles.js.map +1 -1
- package/dist/segmentInfos.d.ts +3 -0
- package/dist/segmentInfos.d.ts.map +1 -1
- package/dist/segmentInfos.js.map +1 -1
- package/dist/segmentPropertiesManager.js +3 -3
- package/dist/segmentPropertiesManager.js.map +1 -1
- package/dist/snapshotLoader.js +2 -2
- package/dist/snapshotLoader.js.map +1 -1
- package/dist/sortedSegmentSet.d.ts +5 -3
- package/dist/sortedSegmentSet.d.ts.map +1 -1
- package/dist/sortedSegmentSet.js +33 -41
- package/dist/sortedSegmentSet.js.map +1 -1
- package/dist/sortedSet.d.ts +20 -3
- package/dist/sortedSet.d.ts.map +1 -1
- package/dist/sortedSet.js +23 -14
- package/dist/sortedSet.js.map +1 -1
- package/dist/test/Snapshot.perf.spec.js +1 -1
- package/dist/test/Snapshot.perf.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +20 -0
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.js +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.js.map +1 -1
- package/dist/test/client.attributionFarm.spec.js +1 -1
- package/dist/test/client.attributionFarm.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +48 -0
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.obliterateFarm.spec.d.ts.map +1 -1
- package/dist/test/client.obliterateFarm.spec.js +24 -3
- package/dist/test/client.obliterateFarm.spec.js.map +1 -1
- package/dist/test/client.reconnectFarm.spec.js +1 -1
- package/dist/test/client.reconnectFarm.spec.js.map +1 -1
- package/dist/test/client.searchForMarker.spec.js +2 -2
- package/dist/test/client.searchForMarker.spec.js.map +1 -1
- package/dist/test/mergeTreeOperationRunner.d.ts +1 -1
- package/dist/test/mergeTreeOperationRunner.d.ts.map +1 -1
- package/dist/test/mergeTreeOperationRunner.js +23 -11
- package/dist/test/mergeTreeOperationRunner.js.map +1 -1
- package/dist/test/obliterate.concurrent.spec.js +45 -1
- package/dist/test/obliterate.concurrent.spec.js.map +1 -1
- package/dist/test/obliterate.rangeExpansion.spec.js +81 -5
- package/dist/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/dist/test/obliterate.spec.js +3 -3
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/obliterateOperations.d.ts +1 -0
- package/dist/test/obliterateOperations.d.ts.map +1 -1
- package/dist/test/obliterateOperations.js +57 -24
- package/dist/test/obliterateOperations.js.map +1 -1
- package/dist/test/partialSyncHelper.d.ts +42 -0
- package/dist/test/partialSyncHelper.d.ts.map +1 -0
- package/dist/test/partialSyncHelper.js +96 -0
- package/dist/test/partialSyncHelper.js.map +1 -0
- package/dist/test/revertibles.spec.js +3 -3
- package/dist/test/revertibles.spec.js.map +1 -1
- package/dist/test/sortedSegmentSet.spec.js +21 -0
- package/dist/test/sortedSegmentSet.spec.js.map +1 -1
- package/dist/test/testClient.d.ts +1 -1
- package/dist/test/testClient.d.ts.map +1 -1
- package/dist/test/testClient.js +1 -0
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/testUtils.js +2 -2
- package/dist/test/testUtils.js.map +1 -1
- package/lib/attributionCollection.js +5 -7
- package/lib/attributionCollection.js.map +1 -1
- package/lib/localReference.js +6 -8
- package/lib/localReference.js.map +1 -1
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +69 -34
- package/lib/mergeTree.js.map +1 -1
- package/lib/mergeTreeNodes.d.ts +15 -4
- package/lib/mergeTreeNodes.d.ts.map +1 -1
- package/lib/mergeTreeNodes.js +1 -1
- package/lib/mergeTreeNodes.js.map +1 -1
- package/lib/partialLengths.d.ts +114 -144
- package/lib/partialLengths.d.ts.map +1 -1
- package/lib/partialLengths.js +432 -525
- package/lib/partialLengths.js.map +1 -1
- package/lib/perspective.d.ts +10 -1
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +10 -1
- package/lib/perspective.js.map +1 -1
- package/lib/properties.d.ts.map +1 -1
- package/lib/properties.js +2 -3
- package/lib/properties.js.map +1 -1
- package/lib/revertibles.js +3 -3
- package/lib/revertibles.js.map +1 -1
- package/lib/segmentInfos.d.ts +3 -0
- package/lib/segmentInfos.d.ts.map +1 -1
- package/lib/segmentInfos.js.map +1 -1
- package/lib/segmentPropertiesManager.js +3 -3
- package/lib/segmentPropertiesManager.js.map +1 -1
- package/lib/snapshotLoader.js +2 -2
- package/lib/snapshotLoader.js.map +1 -1
- package/lib/sortedSegmentSet.d.ts +5 -3
- package/lib/sortedSegmentSet.d.ts.map +1 -1
- package/lib/sortedSegmentSet.js +33 -41
- package/lib/sortedSegmentSet.js.map +1 -1
- package/lib/sortedSet.d.ts +20 -3
- package/lib/sortedSet.d.ts.map +1 -1
- package/lib/sortedSet.js +23 -14
- package/lib/sortedSet.js.map +1 -1
- package/lib/test/Snapshot.perf.spec.js +1 -1
- package/lib/test/Snapshot.perf.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +20 -0
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.js +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.js.map +1 -1
- package/lib/test/client.attributionFarm.spec.js +1 -1
- package/lib/test/client.attributionFarm.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +48 -0
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.obliterateFarm.spec.d.ts.map +1 -1
- package/lib/test/client.obliterateFarm.spec.js +28 -5
- package/lib/test/client.obliterateFarm.spec.js.map +1 -1
- package/lib/test/client.reconnectFarm.spec.js +1 -1
- package/lib/test/client.reconnectFarm.spec.js.map +1 -1
- package/lib/test/client.searchForMarker.spec.js +2 -2
- package/lib/test/client.searchForMarker.spec.js.map +1 -1
- package/lib/test/mergeTreeOperationRunner.d.ts +1 -1
- package/lib/test/mergeTreeOperationRunner.d.ts.map +1 -1
- package/lib/test/mergeTreeOperationRunner.js +23 -11
- package/lib/test/mergeTreeOperationRunner.js.map +1 -1
- package/lib/test/obliterate.concurrent.spec.js +45 -1
- package/lib/test/obliterate.concurrent.spec.js.map +1 -1
- package/lib/test/obliterate.rangeExpansion.spec.js +81 -5
- package/lib/test/obliterate.rangeExpansion.spec.js.map +1 -1
- package/lib/test/obliterate.spec.js +3 -3
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/obliterateOperations.d.ts +1 -0
- package/lib/test/obliterateOperations.d.ts.map +1 -1
- package/lib/test/obliterateOperations.js +55 -23
- package/lib/test/obliterateOperations.js.map +1 -1
- package/lib/test/partialSyncHelper.d.ts +42 -0
- package/lib/test/partialSyncHelper.d.ts.map +1 -0
- package/lib/test/partialSyncHelper.js +92 -0
- package/lib/test/partialSyncHelper.js.map +1 -0
- package/lib/test/revertibles.spec.js +3 -3
- package/lib/test/revertibles.spec.js.map +1 -1
- package/lib/test/sortedSegmentSet.spec.js +21 -0
- package/lib/test/sortedSegmentSet.spec.js.map +1 -1
- package/lib/test/testClient.d.ts +1 -1
- package/lib/test/testClient.d.ts.map +1 -1
- package/lib/test/testClient.js +1 -0
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/testUtils.js +2 -2
- package/lib/test/testUtils.js.map +1 -1
- package/package.json +20 -20
- package/src/mergeTree.ts +80 -28
- package/src/mergeTreeNodes.ts +15 -4
- package/src/partialLengths.ts +559 -776
- package/src/perspective.ts +10 -1
- package/src/properties.ts +2 -3
- package/src/segmentInfos.ts +3 -0
- package/src/snapshotLoader.ts +1 -1
- package/src/sortedSegmentSet.ts +41 -50
- package/src/sortedSet.ts +32 -16
package/dist/mergeTree.js
CHANGED
|
@@ -286,6 +286,8 @@ class MergeTree {
|
|
|
286
286
|
// for now assume only markers have ids and so point directly at the Segment
|
|
287
287
|
// if we need to have pointers to non-markers, we can change to point at local refs
|
|
288
288
|
this.idToMarker = new Map();
|
|
289
|
+
// TODO:AB#29553: This property doesn't seem to be adequately round-tripped through summarization.
|
|
290
|
+
// Specifically, it seems like we drop information about obliterates within the collab window for at least V1 summaries.
|
|
289
291
|
this.obliterates = new Obliterates(this);
|
|
290
292
|
this.splitLeafSegment = (segment, pos) => {
|
|
291
293
|
if (!(pos > 0 && segment)) {
|
|
@@ -294,11 +296,11 @@ class MergeTree {
|
|
|
294
296
|
const next = segment.splitAt(pos);
|
|
295
297
|
(0, mergeTreeNodes_js_1.assertSegmentLeaf)(next);
|
|
296
298
|
if (segment?.segmentGroups) {
|
|
297
|
-
next.segmentGroups
|
|
299
|
+
next.segmentGroups ??= new segmentGroupCollection_js_1.SegmentGroupCollection(next);
|
|
298
300
|
segment.segmentGroups.copyTo(next.segmentGroups);
|
|
299
301
|
}
|
|
300
|
-
if (segment.
|
|
301
|
-
next.
|
|
302
|
+
if (segment.obliteratePrecedingInsertion) {
|
|
303
|
+
next.obliteratePrecedingInsertion = segment.obliteratePrecedingInsertion;
|
|
302
304
|
}
|
|
303
305
|
(0, segmentPropertiesManager_js_1.copyPropertiesAndManager)(segment, next);
|
|
304
306
|
if (segment.localRefs) {
|
|
@@ -795,7 +797,7 @@ class MergeTree {
|
|
|
795
797
|
const overlappingRemoves = [];
|
|
796
798
|
pendingSegmentGroup.segments.map((pendingSegment) => {
|
|
797
799
|
const overlappingRemove = !ackSegment(pendingSegment, pendingSegmentGroup, opArgs);
|
|
798
|
-
overwrite
|
|
800
|
+
overwrite ||= overlappingRemove || (0, segmentInfos_js_1.toMoveInfo)(pendingSegment) !== undefined;
|
|
799
801
|
overlappingRemoves.push(overlappingRemove);
|
|
800
802
|
if (MergeTree.options.zamboniSegments) {
|
|
801
803
|
this.addToLRUSet(pendingSegment, seq);
|
|
@@ -851,7 +853,7 @@ class MergeTree {
|
|
|
851
853
|
if (previousProps) {
|
|
852
854
|
_segmentGroup.previousProps.push(previousProps);
|
|
853
855
|
}
|
|
854
|
-
const segmentGroups = (segment.segmentGroups
|
|
856
|
+
const segmentGroups = (segment.segmentGroups ??= new segmentGroupCollection_js_1.SegmentGroupCollection(segment));
|
|
855
857
|
segmentGroups.enqueue(_segmentGroup);
|
|
856
858
|
return _segmentGroup;
|
|
857
859
|
}
|
|
@@ -1036,15 +1038,21 @@ class MergeTree {
|
|
|
1036
1038
|
? Number.MAX_SAFE_INTEGER - this.collabWindow.localSeq + ob.localSeq
|
|
1037
1039
|
: ob.seq;
|
|
1038
1040
|
if (normalizedObSeq > refSeq) {
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1041
|
+
// Any obliterate from the same client that's inserting this segment cannot cause the segment to be marked as
|
|
1042
|
+
// obliterated (since that client must have performed the obliterate before this insertion).
|
|
1043
|
+
// We still need to consider such obliterates when determining the winning obliterate for the insertion point,
|
|
1044
|
+
// see `obliteratePrecedingInsertion` docs.
|
|
1045
|
+
if (clientId !== ob.clientId) {
|
|
1046
|
+
if (oldest === undefined || normalizedOldestSeq > normalizedObSeq) {
|
|
1047
|
+
normalizedOldestSeq = normalizedObSeq;
|
|
1048
|
+
oldest = ob;
|
|
1049
|
+
movedClientIds.unshift(ob.clientId);
|
|
1050
|
+
movedSeqs.unshift(ob.seq);
|
|
1051
|
+
}
|
|
1052
|
+
else {
|
|
1053
|
+
movedClientIds.push(ob.clientId);
|
|
1054
|
+
movedSeqs.push(ob.seq);
|
|
1055
|
+
}
|
|
1048
1056
|
}
|
|
1049
1057
|
if (newest === undefined || normalizedNewestSeq < normalizedObSeq) {
|
|
1050
1058
|
normalizedNewestSeq = normalizedObSeq;
|
|
@@ -1052,6 +1060,10 @@ class MergeTree {
|
|
|
1052
1060
|
}
|
|
1053
1061
|
}
|
|
1054
1062
|
}
|
|
1063
|
+
newSegment.obliteratePrecedingInsertion = newest;
|
|
1064
|
+
// See doc comment on obliteratePrecedingInsertion for more details: if the newest obliterate was performed
|
|
1065
|
+
// by the same client that's inserting this segment, we let them insert into this range and therefore don't
|
|
1066
|
+
// mark it obliterated.
|
|
1055
1067
|
if (oldest && newest?.clientId !== clientId) {
|
|
1056
1068
|
const moveInfo = {
|
|
1057
1069
|
movedClientIds,
|
|
@@ -1066,12 +1078,14 @@ class MergeTree {
|
|
|
1066
1078
|
this.addToPendingList(newSegment, oldest.segmentGroup);
|
|
1067
1079
|
}
|
|
1068
1080
|
if (newSegment.parent) {
|
|
1069
|
-
|
|
1081
|
+
// The incremental update codepath in theory can handle most cases where segments are obliterated upon insertion,
|
|
1082
|
+
// but it's not idempotent with respect to segment insertion in the first place. Since we already update partial
|
|
1083
|
+
// lengths inside the inserting walk, we'd be at risk of double-counting the insertion in any case if we allow
|
|
1084
|
+
// incremental updates here.
|
|
1085
|
+
const newStructure = true;
|
|
1086
|
+
this.blockUpdatePathLengths(newSegment.parent, moveInfo.movedSeq, clientId, newStructure);
|
|
1070
1087
|
}
|
|
1071
1088
|
}
|
|
1072
|
-
else if (oldest && newest?.clientId === clientId) {
|
|
1073
|
-
newSegment.prevObliterateByInserter = newest;
|
|
1074
|
-
}
|
|
1075
1089
|
saveIfLocal(newSegment);
|
|
1076
1090
|
}
|
|
1077
1091
|
}
|
|
@@ -1247,7 +1261,7 @@ class MergeTree {
|
|
|
1247
1261
|
(0, internal_1.assert)(!mergeTreeNodes_js_1.Marker.is(segment) ||
|
|
1248
1262
|
!(mergeTreeNodes_js_1.reservedMarkerIdKey in opObj) ||
|
|
1249
1263
|
opObj.markerId === segment.properties?.markerId, 0x5ad /* Cannot change the markerId of an existing marker */);
|
|
1250
|
-
const propertyManager = (segment.propertyManager
|
|
1264
|
+
const propertyManager = (segment.propertyManager ??= new segmentPropertiesManager_js_1.PropertiesManager());
|
|
1251
1265
|
const propertyDeltas = propertyManager.handleProperties(propsOrAdjust, segment, seq, this.collabWindow.minSeq, this.collabWindow.collaborating, rollback);
|
|
1252
1266
|
if (!isRemovedOrMoved(segment)) {
|
|
1253
1267
|
deltaSegments.push({ segment, propertyDeltas });
|
|
@@ -1323,40 +1337,53 @@ class MergeTree {
|
|
|
1323
1337
|
if ((start.side === sequencePlace_js_1.Side.After && startPos === pos + segment.cachedLength) || // exclusive start segment
|
|
1324
1338
|
(end.side === sequencePlace_js_1.Side.Before &&
|
|
1325
1339
|
endPos === pos &&
|
|
1326
|
-
|
|
1340
|
+
// TODO:AB#29765: The clientId check here should be handled by isSegmentPresent and/or PerspectiveImpl
|
|
1341
|
+
(segment.clientId === clientId || (0, perspective_js_1.isSegmentPresent)(segment, { refSeq, localSeq }))) // exclusive end segment
|
|
1327
1342
|
) {
|
|
1328
1343
|
// We walk these segments because we want to also walk any concurrently inserted segments between here and the obliterated segments.
|
|
1329
1344
|
// These segments are outside of the obliteration range though, so return true to keep walking.
|
|
1330
1345
|
return true;
|
|
1331
1346
|
}
|
|
1332
1347
|
const existingMoveInfo = (0, segmentInfos_js_1.toMoveInfo)(segment);
|
|
1333
|
-
|
|
1348
|
+
// The "last-to-obliterate-gets-to-insert" policy described by the doc comment on `obliteratePrecedingInsertion`
|
|
1349
|
+
// is mostly handled by logic at insertion time, but we need a small bit of handling here.
|
|
1350
|
+
// Specifically, we want to avoid marking a local-only segment as obliterated when we know one of our own local obliterates
|
|
1351
|
+
// will win against the obliterate we're processing, hence the early exit.
|
|
1352
|
+
if (segment.seq === constants_js_1.UnassignedSequenceNumber &&
|
|
1353
|
+
segment.obliteratePrecedingInsertion?.seq === constants_js_1.UnassignedSequenceNumber &&
|
|
1354
|
+
seq !== constants_js_1.UnassignedSequenceNumber) {
|
|
1334
1355
|
// We chose to not obliterate this segment because we are aware of an unacked local obliteration.
|
|
1335
1356
|
// The local obliterate has not been sequenced yet, so it is still the newest obliterate we are aware of.
|
|
1336
1357
|
// Other clients will also choose not to obliterate this segment because the most recent obliteration has the same clientId
|
|
1337
1358
|
return true;
|
|
1338
1359
|
}
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
seq !== constants_js_1.UnassignedSequenceNumber &&
|
|
1342
|
-
(refSeq < segment.seq || segment.seq === constants_js_1.UnassignedSequenceNumber);
|
|
1360
|
+
// Partial lengths incrementality is not supported for overlapping obliterate/removes.
|
|
1361
|
+
_overwrite ||= existingMoveInfo !== undefined || (0, segmentInfos_js_1.toRemovalInfo)(segment) !== undefined;
|
|
1343
1362
|
if (existingMoveInfo === undefined) {
|
|
1344
1363
|
const movedSeg = (0, segmentInfos_js_1.overwriteInfo)(segment, {
|
|
1345
1364
|
movedClientIds: [clientId],
|
|
1346
1365
|
movedSeq: seq,
|
|
1347
1366
|
localMovedSeq: localSeq,
|
|
1348
1367
|
movedSeqs: [seq],
|
|
1349
|
-
wasMovedOnInsert,
|
|
1368
|
+
wasMovedOnInsert: segment.seq === constants_js_1.UnassignedSequenceNumber && seq !== constants_js_1.UnassignedSequenceNumber,
|
|
1350
1369
|
});
|
|
1351
|
-
|
|
1370
|
+
const existingRemoval = (0, segmentInfos_js_1.toRemovalInfo)(movedSeg);
|
|
1371
|
+
if (existingRemoval === undefined) {
|
|
1352
1372
|
movedSegments.push(movedSeg);
|
|
1353
1373
|
}
|
|
1374
|
+
else if (existingRemoval.removedSeq === constants_js_1.UnassignedSequenceNumber &&
|
|
1375
|
+
segment.localRefs?.empty === false) {
|
|
1376
|
+
// We removed this locally already so we don't need to event it again, but it might have references
|
|
1377
|
+
// that need sliding now that a move may have been acked.
|
|
1378
|
+
localOverlapWithRefs.push(segment);
|
|
1379
|
+
}
|
|
1354
1380
|
}
|
|
1355
1381
|
else {
|
|
1356
|
-
_overwrite = true;
|
|
1357
|
-
// never move wasMovedOnInsert from true to false
|
|
1358
|
-
existingMoveInfo.wasMovedOnInsert || (existingMoveInfo.wasMovedOnInsert = wasMovedOnInsert);
|
|
1359
1382
|
if (existingMoveInfo.movedSeq === constants_js_1.UnassignedSequenceNumber) {
|
|
1383
|
+
// Should not need explicit set here, but this should be implied:
|
|
1384
|
+
(0, internal_1.assert)(!existingMoveInfo.wasMovedOnInsert, 0xab4 /* Local obliterate cannot have removed a segment as soon as it was inserted */);
|
|
1385
|
+
(0, internal_1.assert)(seq !== constants_js_1.UnassignedSequenceNumber, 0xab5 /* Cannot obliterate the same segment locally twice */);
|
|
1386
|
+
existingMoveInfo.wasMovedOnInsert = segment.seq === constants_js_1.UnassignedSequenceNumber;
|
|
1360
1387
|
// we moved this locally, but someone else moved it first
|
|
1361
1388
|
// so put them at the head of the list
|
|
1362
1389
|
// The list isn't ordered, but we keep the first move at the head
|
|
@@ -1441,18 +1468,26 @@ class MergeTree {
|
|
|
1441
1468
|
const localSeq = seq === constants_js_1.UnassignedSequenceNumber ? ++this.collabWindow.localSeq : undefined;
|
|
1442
1469
|
const markRemoved = (segment, pos, _start, _end) => {
|
|
1443
1470
|
const existingRemovalInfo = (0, segmentInfos_js_1.toRemovalInfo)(segment);
|
|
1471
|
+
// Partial lengths incrementality is not supported for overlapping obliterate/removes.
|
|
1472
|
+
_overwrite ||= existingRemovalInfo !== undefined || (0, segmentInfos_js_1.toMoveInfo)(segment) !== undefined;
|
|
1444
1473
|
if (existingRemovalInfo === undefined) {
|
|
1445
1474
|
const removed = (0, segmentInfos_js_1.overwriteInfo)(segment, {
|
|
1446
1475
|
removedClientIds: [clientId],
|
|
1447
1476
|
removedSeq: seq,
|
|
1448
1477
|
localRemovedSeq: localSeq,
|
|
1449
1478
|
});
|
|
1450
|
-
|
|
1479
|
+
const existingMoveInfo = (0, segmentInfos_js_1.toMoveInfo)(removed);
|
|
1480
|
+
if (existingMoveInfo === undefined) {
|
|
1451
1481
|
removedSegments.push(removed);
|
|
1452
1482
|
}
|
|
1483
|
+
else if (existingMoveInfo.movedSeq === constants_js_1.UnassignedSequenceNumber &&
|
|
1484
|
+
segment.localRefs?.empty === false) {
|
|
1485
|
+
// We moved this locally already so we don't need to event it again, but it might have references
|
|
1486
|
+
// that need sliding now that a remove may have been acked.
|
|
1487
|
+
localOverlapWithRefs.push(segment);
|
|
1488
|
+
}
|
|
1453
1489
|
}
|
|
1454
1490
|
else {
|
|
1455
|
-
_overwrite = true;
|
|
1456
1491
|
if (existingRemovalInfo.removedSeq === constants_js_1.UnassignedSequenceNumber) {
|
|
1457
1492
|
// we removed this locally, but someone else removed it first
|
|
1458
1493
|
// so put them at the head of the list
|
|
@@ -1771,7 +1806,7 @@ class MergeTree {
|
|
|
1771
1806
|
const node = block.children[i];
|
|
1772
1807
|
const nodeLength = nodeTotalLength(this, node);
|
|
1773
1808
|
if (nodeLength !== undefined) {
|
|
1774
|
-
len
|
|
1809
|
+
len ??= 0;
|
|
1775
1810
|
len += nodeLength;
|
|
1776
1811
|
}
|
|
1777
1812
|
if (node.isLeaf()) {
|
|
@@ -1791,7 +1826,7 @@ class MergeTree {
|
|
|
1791
1826
|
// The later, and right most children overwrite
|
|
1792
1827
|
// whereas early, and left most do not overwrite
|
|
1793
1828
|
rightmostTiles[tileLabel] = segment;
|
|
1794
|
-
leftmostTiles[tileLabel]
|
|
1829
|
+
leftmostTiles[tileLabel] ??= segment;
|
|
1795
1830
|
}
|
|
1796
1831
|
}
|
|
1797
1832
|
}
|