@fluidframework/merge-tree 2.41.0 → 2.43.0-343119
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/dist/client.d.ts +9 -6
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +79 -36
- package/dist/client.js.map +1 -1
- package/dist/collections/list.d.ts +95 -5
- package/dist/collections/list.d.ts.map +1 -1
- package/dist/collections/list.js +67 -5
- package/dist/collections/list.js.map +1 -1
- package/dist/constants.d.ts +5 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +6 -1
- package/dist/constants.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/mergeTree.d.ts +9 -9
- package/dist/mergeTree.d.ts.map +1 -1
- package/dist/mergeTree.js +15 -7
- package/dist/mergeTree.js.map +1 -1
- package/dist/perspective.d.ts +15 -0
- package/dist/perspective.d.ts.map +1 -1
- package/dist/perspective.js +25 -1
- package/dist/perspective.js.map +1 -1
- package/dist/revertibles.js +1 -1
- package/dist/revertibles.js.map +1 -1
- package/dist/stamps.d.ts +1 -0
- package/dist/stamps.d.ts.map +1 -1
- package/dist/stamps.js +5 -1
- package/dist/stamps.js.map +1 -1
- package/dist/test/beastTest.spec.js +1 -1
- package/dist/test/beastTest.spec.js.map +1 -1
- package/dist/test/client.annotateMarker.spec.js +1 -1
- package/dist/test/client.annotateMarker.spec.js.map +1 -1
- package/dist/test/client.applyMsg.spec.js +25 -25
- package/dist/test/client.applyMsg.spec.js.map +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
- package/dist/test/client.applyStashedOpFarm.spec.js +3 -3
- 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.getPosition.spec.js +1 -0
- package/dist/test/client.getPosition.spec.js.map +1 -1
- package/dist/test/client.localReference.spec.js +62 -48
- package/dist/test/client.localReference.spec.js.map +1 -1
- package/dist/test/client.localReferenceFarm.spec.js +1 -0
- package/dist/test/client.localReferenceFarm.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.rollback.spec.js +8 -6
- package/dist/test/client.rollback.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/clientTestHelper.js +1 -1
- package/dist/test/clientTestHelper.js.map +1 -1
- package/dist/test/mergeTree.annotate.spec.js +25 -25
- package/dist/test/mergeTree.annotate.spec.js.map +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js +1 -1
- package/dist/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/dist/test/obliterate.spec.js +4 -4
- package/dist/test/obliterate.spec.js.map +1 -1
- package/dist/test/resetPendingSegmentsToOp.spec.js +14 -14
- package/dist/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/dist/test/snapshot.utils.js +1 -1
- package/dist/test/snapshot.utils.js.map +1 -1
- package/dist/test/sortedSegmentSet.spec.js +3 -3
- package/dist/test/sortedSegmentSet.spec.js.map +1 -1
- package/dist/test/testClient.js +3 -3
- package/dist/test/testClient.js.map +1 -1
- package/dist/test/tracking.spec.js +7 -7
- package/dist/test/tracking.spec.js.map +1 -1
- package/dist/test/wordUnitTests.spec.js.map +1 -1
- package/lib/client.d.ts +9 -6
- package/lib/client.d.ts.map +1 -1
- package/lib/client.js +81 -38
- package/lib/client.js.map +1 -1
- package/lib/collections/list.d.ts +95 -5
- package/lib/collections/list.d.ts.map +1 -1
- package/lib/collections/list.js +67 -5
- package/lib/collections/list.js.map +1 -1
- package/lib/constants.d.ts +5 -0
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +5 -0
- package/lib/constants.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/mergeTree.d.ts +9 -9
- package/lib/mergeTree.d.ts.map +1 -1
- package/lib/mergeTree.js +15 -7
- package/lib/mergeTree.js.map +1 -1
- package/lib/perspective.d.ts +15 -0
- package/lib/perspective.d.ts.map +1 -1
- package/lib/perspective.js +23 -0
- package/lib/perspective.js.map +1 -1
- package/lib/revertibles.js +1 -1
- package/lib/revertibles.js.map +1 -1
- package/lib/stamps.d.ts +1 -0
- package/lib/stamps.d.ts.map +1 -1
- package/lib/stamps.js +4 -1
- package/lib/stamps.js.map +1 -1
- package/lib/test/beastTest.spec.js +1 -1
- package/lib/test/beastTest.spec.js.map +1 -1
- package/lib/test/client.annotateMarker.spec.js +1 -1
- package/lib/test/client.annotateMarker.spec.js.map +1 -1
- package/lib/test/client.applyMsg.spec.js +25 -25
- package/lib/test/client.applyMsg.spec.js.map +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.d.ts.map +1 -1
- package/lib/test/client.applyStashedOpFarm.spec.js +3 -3
- 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.getPosition.spec.js +1 -0
- package/lib/test/client.getPosition.spec.js.map +1 -1
- package/lib/test/client.localReference.spec.js +62 -48
- package/lib/test/client.localReference.spec.js.map +1 -1
- package/lib/test/client.localReferenceFarm.spec.js +1 -0
- package/lib/test/client.localReferenceFarm.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.rollback.spec.js +8 -6
- package/lib/test/client.rollback.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/clientTestHelper.js +1 -1
- package/lib/test/clientTestHelper.js.map +1 -1
- package/lib/test/mergeTree.annotate.spec.js +25 -25
- package/lib/test/mergeTree.annotate.spec.js.map +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js +1 -1
- package/lib/test/mergeTree.markRangeRemoved.spec.js.map +1 -1
- package/lib/test/obliterate.spec.js +4 -4
- package/lib/test/obliterate.spec.js.map +1 -1
- package/lib/test/resetPendingSegmentsToOp.spec.js +14 -14
- package/lib/test/resetPendingSegmentsToOp.spec.js.map +1 -1
- package/lib/test/snapshot.utils.js +1 -1
- package/lib/test/snapshot.utils.js.map +1 -1
- package/lib/test/sortedSegmentSet.spec.js +3 -3
- package/lib/test/sortedSegmentSet.spec.js.map +1 -1
- package/lib/test/testClient.js +3 -3
- package/lib/test/testClient.js.map +1 -1
- package/lib/test/tracking.spec.js +7 -7
- package/lib/test/tracking.spec.js.map +1 -1
- package/lib/test/wordUnitTests.spec.js.map +1 -1
- package/package.json +16 -16
- package/src/client.ts +117 -50
- package/src/collections/list.ts +101 -5
- package/src/constants.ts +6 -0
- package/src/index.ts +3 -0
- package/src/mergeTree.ts +30 -24
- package/src/perspective.ts +26 -0
- package/src/revertibles.ts +1 -1
- package/src/stamps.ts +9 -1
package/lib/client.js
CHANGED
|
@@ -10,14 +10,14 @@ import { toDeltaManagerInternal } from "@fluidframework/runtime-utils/internal";
|
|
|
10
10
|
import { LoggingError, UsageError, } from "@fluidframework/telemetry-utils/internal";
|
|
11
11
|
import { MergeTreeTextHelper } from "./MergeTreeTextHelper.js";
|
|
12
12
|
import { RedBlackTree } from "./collections/index.js";
|
|
13
|
-
import { NonCollabClient, UniversalSequenceNumber } from "./constants.js";
|
|
13
|
+
import { NonCollabClient, SquashClient, UniversalSequenceNumber } from "./constants.js";
|
|
14
14
|
import { SlidingPreference } from "./localReference.js";
|
|
15
15
|
import { MergeTree, errorIfOptionNotTrue, getSlideToSegoff, isRemovedAndAcked, } from "./mergeTree.js";
|
|
16
16
|
import { walkAllChildSegments } from "./mergeTreeNodeWalk.js";
|
|
17
17
|
import { compareStrings, isSegmentLeaf, } from "./mergeTreeNodes.js";
|
|
18
18
|
import { createAdjustRangeOp, createAnnotateMarkerOp, createAnnotateRangeOp, createGroupOp, createInsertSegmentOp, createObliterateRangeOp, createObliterateRangeOpSided, createRemoveRangeOp, } from "./opBuilder.js";
|
|
19
19
|
import { MergeTreeDeltaType, ReferenceType, } from "./ops.js";
|
|
20
|
-
import { LocalReconnectingPerspective, PriorPerspective, } from "./perspective.js";
|
|
20
|
+
import { LocalReconnectingPerspective, LocalSquashPerspective, PriorPerspective, } from "./perspective.js";
|
|
21
21
|
import { DetachedReferencePosition } from "./referencePositions.js";
|
|
22
22
|
import { isInserted, isRemoved, overwriteInfo, toRemovalInfo, } from "./segmentInfos.js";
|
|
23
23
|
import { Side } from "./sequencePlace.js";
|
|
@@ -186,8 +186,10 @@ export class Client extends TypedEventEmitter {
|
|
|
186
186
|
}
|
|
187
187
|
return this.insertSegmentLocal(pos, segment);
|
|
188
188
|
}
|
|
189
|
-
walkSegments(handler, start, end, accum, splitRange = false) {
|
|
190
|
-
this._mergeTree.mapRange(handler,
|
|
189
|
+
walkSegments(handler, start, end, accum, splitRange = false, perspective) {
|
|
190
|
+
this._mergeTree.mapRange(handler, perspective === undefined
|
|
191
|
+
? this.getCollabWindow().localPerspective
|
|
192
|
+
: this.getOperationPerspective(perspective), accum, start, end, splitRange);
|
|
191
193
|
}
|
|
192
194
|
walkAllSegments(action, accum) {
|
|
193
195
|
return walkAllChildSegments(this._mergeTree.root, accum === undefined ? action : (seg) => action(seg, accum));
|
|
@@ -551,11 +553,13 @@ export class Client extends TypedEventEmitter {
|
|
|
551
553
|
const useNewSlidingBehavior = true;
|
|
552
554
|
// Destructuring segment + offset is convenient and segment is reassigned
|
|
553
555
|
// eslint-disable-next-line prefer-const
|
|
554
|
-
|
|
555
|
-
newSegment
|
|
556
|
-
slidePreference === SlidingPreference.FORWARD
|
|
556
|
+
const segOff = getSlideToSegoff({ segment: oldSegment, offset: oldOffset }, slidePreference, reconnectingPerspective, useNewSlidingBehavior);
|
|
557
|
+
const { segment: newSegment, offset: newOffset } = segOff ?? {
|
|
558
|
+
segment: slidePreference === SlidingPreference.FORWARD
|
|
557
559
|
? this._mergeTree.endOfTree
|
|
558
|
-
: this._mergeTree.startOfTree
|
|
560
|
+
: this._mergeTree.startOfTree,
|
|
561
|
+
offset: 0,
|
|
562
|
+
};
|
|
559
563
|
assert(isSegmentLeaf(newSegment) && newOffset !== undefined, 0xb62 /* Invalid new segment on rebase */);
|
|
560
564
|
const newSide = newSegment === oldSegment
|
|
561
565
|
? side
|
|
@@ -566,9 +570,9 @@ export class Client extends TypedEventEmitter {
|
|
|
566
570
|
: Side.After;
|
|
567
571
|
return { segment: newSegment, offset: newOffset, side: newSide };
|
|
568
572
|
}
|
|
569
|
-
computeNewObliterateEndpoints(obliterateInfo) {
|
|
573
|
+
computeNewObliterateEndpoints(obliterateInfo, squash) {
|
|
570
574
|
const { currentSeq, clientId } = this.getCollabWindow();
|
|
571
|
-
const reconnectingPerspective = new LocalReconnectingPerspective(currentSeq, clientId, obliterateInfo.stamp.localSeq - 1);
|
|
575
|
+
const reconnectingPerspective = new (squash ? LocalSquashPerspective : LocalReconnectingPerspective)(currentSeq, clientId, obliterateInfo.stamp.localSeq - 1);
|
|
572
576
|
const newStart = this.rebaseSidedLocalReference(obliterateInfo.start, obliterateInfo.startSide, reconnectingPerspective, SlidingPreference.FORWARD);
|
|
573
577
|
const newEnd = this.rebaseSidedLocalReference(obliterateInfo.end, obliterateInfo.endSide, reconnectingPerspective, SlidingPreference.BACKWARD);
|
|
574
578
|
return {
|
|
@@ -576,7 +580,7 @@ export class Client extends TypedEventEmitter {
|
|
|
576
580
|
end: newEnd,
|
|
577
581
|
};
|
|
578
582
|
}
|
|
579
|
-
resetPendingDeltaToOps(resetOp, segmentGroup) {
|
|
583
|
+
resetPendingDeltaToOps(resetOp, segmentGroup, squash) {
|
|
580
584
|
assert(!!segmentGroup, 0x033 /* "Segment group undefined" */);
|
|
581
585
|
const NACKedSegmentGroup = this.pendingRebase?.shift()?.data;
|
|
582
586
|
assert(segmentGroup === NACKedSegmentGroup, 0x034 /* "Segment group not at head of pending rebase queue" */);
|
|
@@ -603,11 +607,17 @@ export class Client extends TypedEventEmitter {
|
|
|
603
607
|
for (const segment of segmentGroup.segments) {
|
|
604
608
|
assert(isRemovedAndAcked(segment), 0xb66 /* On reconnect, obliterate applied to new segments even though original ones were not removed. */);
|
|
605
609
|
const lastRemove = segment.removes[segment.removes.length - 1];
|
|
606
|
-
assert(lastRemove.type === "sliceRemove" &&
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
//
|
|
610
|
-
segment
|
|
610
|
+
assert((lastRemove.type === "sliceRemove" &&
|
|
611
|
+
lastRemove.localSeq === segmentGroup.localSeq) ||
|
|
612
|
+
opstampUtils.isSquashedOp(lastRemove), 0xbad /* Last remove should be the obliterate that is being resubmitted. */);
|
|
613
|
+
// The original obliterate affected this segment, but it has since been removed.
|
|
614
|
+
// This can happen when a concurrent obliterate also removed the segment, as well as when the segment was
|
|
615
|
+
// only locally inserted and its insertion was squashed upon reconnecting.
|
|
616
|
+
// In the concurrent removal case (where we didn't avoid sending the segment's insertion in the first place due
|
|
617
|
+
// to squashing), we adjust the metadata on that segment to reflect the fact that this obliterate no longer removes it.
|
|
618
|
+
if (!opstampUtils.isSquashedOp(lastRemove)) {
|
|
619
|
+
segment.removes.pop();
|
|
620
|
+
}
|
|
611
621
|
}
|
|
612
622
|
this._mergeTree.rebaseObliterateTo(obliterateInfo, undefined);
|
|
613
623
|
return [];
|
|
@@ -636,19 +646,24 @@ export class Client extends TypedEventEmitter {
|
|
|
636
646
|
};
|
|
637
647
|
for (const segment of segmentGroup.segments) {
|
|
638
648
|
assert(segment.segmentGroups?.remove(segmentGroup) === true, 0x035 /* "Segment group not in segment pending queue" */);
|
|
639
|
-
if ((segment
|
|
640
|
-
segment.ordinal
|
|
641
|
-
|
|
642
|
-
|
|
649
|
+
if (!isRemovedAndAcked(segment) &&
|
|
650
|
+
((segment.ordinal > newStartSegment.ordinal &&
|
|
651
|
+
segment.ordinal < newEndSegment.ordinal) ||
|
|
652
|
+
(segment === newStartSegment && newStartSide === Side.Before) ||
|
|
653
|
+
(segment === newEndSegment && newEndSide === Side.After))) {
|
|
643
654
|
segment.segmentGroups.enqueue(newObliterate.segmentGroup);
|
|
644
655
|
}
|
|
645
656
|
else {
|
|
646
657
|
assert(isRemovedAndAcked(segment), 0xb69 /* On reconnect, obliterate applied to new segments even though original ones were not removed. */);
|
|
647
658
|
const lastRemove = segment.removes[segment.removes.length - 1];
|
|
648
|
-
assert(lastRemove.type === "sliceRemove" &&
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
659
|
+
assert((lastRemove.type === "sliceRemove" &&
|
|
660
|
+
lastRemove.localSeq === segmentGroup.localSeq) ||
|
|
661
|
+
opstampUtils.isSquashedOp(lastRemove), 0xbae /* Last remove should be the obliterate that is being resubmitted. */);
|
|
662
|
+
if (!opstampUtils.isSquashedOp(lastRemove)) {
|
|
663
|
+
// The original obliterate affected this segment, but it has since been removed and it's impossible to apply the
|
|
664
|
+
// local obliterate so that is so. We adjust the metadata on that segment now.
|
|
665
|
+
segment.removes.pop();
|
|
666
|
+
}
|
|
652
667
|
}
|
|
653
668
|
}
|
|
654
669
|
this._mergeTree.rebaseObliterateTo(obliterateInfo, newObliterate);
|
|
@@ -701,9 +716,19 @@ export class Client extends TypedEventEmitter {
|
|
|
701
716
|
break;
|
|
702
717
|
}
|
|
703
718
|
case MergeTreeDeltaType.INSERT: {
|
|
719
|
+
if (isInserted(segment) && opstampUtils.isSquashedOp(segment.insert)) {
|
|
720
|
+
break;
|
|
721
|
+
}
|
|
704
722
|
assert(isInserted(segment) && opstampUtils.isLocal(segment.insert), 0x037 /* "Segment already has assigned sequence number" */);
|
|
705
723
|
const removeInfo = toRemovalInfo(segment);
|
|
706
|
-
|
|
724
|
+
const unusedStamp = { seq: 0, clientId: 0 };
|
|
725
|
+
if (removeInfo !== undefined && squash) {
|
|
726
|
+
assert(removeInfo.removes.length === 1 ||
|
|
727
|
+
opstampUtils.isAcked(removeInfo.removes[removeInfo.removes.length - 2]), 0xbaf /* Expected only one local remove */);
|
|
728
|
+
this.squashInsertion(segment);
|
|
729
|
+
break;
|
|
730
|
+
}
|
|
731
|
+
else if (removeInfo !== undefined && opstampUtils.isAcked(removeInfo.removes[0])) {
|
|
707
732
|
assert(removeInfo.removes[0].type === "sliceRemove", 0xb5c /* Remove on insertion must be caused by obliterate. */);
|
|
708
733
|
errorIfOptionNotTrue(this._mergeTree.options, "mergeTreeEnableObliterateReconnect");
|
|
709
734
|
// the segment was remotely obliterated, so is considered removed
|
|
@@ -718,6 +743,7 @@ export class Client extends TypedEventEmitter {
|
|
|
718
743
|
clientId: NonCollabClient,
|
|
719
744
|
},
|
|
720
745
|
});
|
|
746
|
+
this._mergeTree.blockUpdatePathLengths(segment.parent, unusedStamp, true);
|
|
721
747
|
break;
|
|
722
748
|
}
|
|
723
749
|
const segInsertOp = segment.clone();
|
|
@@ -857,13 +883,34 @@ export class Client extends TypedEventEmitter {
|
|
|
857
883
|
const shortRemoteClientId = this.getOrAddShortClientId(remoteClientId);
|
|
858
884
|
return this._mergeTree.resolveRemoteClientPosition(remoteClientPosition, remoteClientRefSeq, shortRemoteClientId);
|
|
859
885
|
}
|
|
886
|
+
squashInsertion(segment) {
|
|
887
|
+
overwriteInfo(segment, {
|
|
888
|
+
insert: {
|
|
889
|
+
type: "insert",
|
|
890
|
+
seq: UniversalSequenceNumber,
|
|
891
|
+
localSeq: undefined,
|
|
892
|
+
clientId: SquashClient,
|
|
893
|
+
},
|
|
894
|
+
removes: [
|
|
895
|
+
{
|
|
896
|
+
type: "setRemove",
|
|
897
|
+
seq: UniversalSequenceNumber,
|
|
898
|
+
localSeq: undefined,
|
|
899
|
+
clientId: SquashClient,
|
|
900
|
+
},
|
|
901
|
+
],
|
|
902
|
+
});
|
|
903
|
+
this._mergeTree.blockUpdatePathLengths(segment.parent, { seq: 0, clientId: 0 }, true);
|
|
904
|
+
}
|
|
860
905
|
/**
|
|
861
906
|
* Given a pending operation and segment group, regenerate the op, so it
|
|
862
907
|
* can be resubmitted
|
|
863
908
|
* @param resetOp - The op to reset
|
|
864
909
|
* @param segmentGroup - The segment group associated with the op
|
|
910
|
+
* @param squash - whether intermediate states should be squashed. See `IDeltaHandler.reSubmit`'s squash parameter
|
|
911
|
+
* documentation for more details.
|
|
865
912
|
*/
|
|
866
|
-
regeneratePendingOp(resetOp, localOpMetadata) {
|
|
913
|
+
regeneratePendingOp(resetOp, localOpMetadata, squash) {
|
|
867
914
|
const segmentGroup = localOpMetadata;
|
|
868
915
|
if (this.pendingRebase === undefined || this.pendingRebase.empty) {
|
|
869
916
|
let firstGroup;
|
|
@@ -885,13 +932,14 @@ export class Client extends TypedEventEmitter {
|
|
|
885
932
|
if (this.lastNormalization === undefined ||
|
|
886
933
|
collabWindow.currentSeq !== this.lastNormalization.refSeq ||
|
|
887
934
|
collabWindow.localSeq !== this.lastNormalization.localRefSeq) {
|
|
935
|
+
const allPendingSegments = [...this._mergeTree.pendingSegments, ...this.pendingRebase];
|
|
888
936
|
// Compute obliterate endpoint destinations before segments are normalized.
|
|
889
937
|
// Segment normalization can affect what should be the semantically correct segments for the endpoints to be placed on.
|
|
890
938
|
this.cachedObliterateRebases.clear();
|
|
891
|
-
for (const group of
|
|
939
|
+
for (const group of allPendingSegments) {
|
|
892
940
|
const { obliterateInfo } = group.data;
|
|
893
941
|
if (obliterateInfo !== undefined) {
|
|
894
|
-
const { start, end } = this.computeNewObliterateEndpoints(obliterateInfo);
|
|
942
|
+
const { start, end } = this.computeNewObliterateEndpoints(obliterateInfo, squash);
|
|
895
943
|
const { localSeq } = obliterateInfo.stamp;
|
|
896
944
|
assert(localSeq !== undefined, 0xb6d /* Local seq must be defined */);
|
|
897
945
|
this.cachedObliterateRebases.set(localSeq, { start, end });
|
|
@@ -909,20 +957,20 @@ export class Client extends TypedEventEmitter {
|
|
|
909
957
|
if (Array.isArray(segmentGroup)) {
|
|
910
958
|
assert(resetOp.ops.length === segmentGroup.length, 0x03a /* "Number of ops in 'resetOp' must match the number of segment groups provided." */);
|
|
911
959
|
for (let i = 0; i < resetOp.ops.length; i++) {
|
|
912
|
-
opList.push(...this.resetPendingDeltaToOps(resetOp.ops[i], segmentGroup[i]));
|
|
960
|
+
opList.push(...this.resetPendingDeltaToOps(resetOp.ops[i], segmentGroup[i], squash));
|
|
913
961
|
}
|
|
914
962
|
}
|
|
915
963
|
else {
|
|
916
964
|
// A group op containing a single op will pass a direct reference to 'segmentGroup'
|
|
917
965
|
// rather than an array of segment groups. (See 'peekPendingSegmentGroups()')
|
|
918
966
|
assert(resetOp.ops.length === 1, 0x03b /* "Number of ops in 'resetOp' must match the number of segment groups provided." */);
|
|
919
|
-
opList.push(...this.resetPendingDeltaToOps(resetOp.ops[0], segmentGroup));
|
|
967
|
+
opList.push(...this.resetPendingDeltaToOps(resetOp.ops[0], segmentGroup, squash));
|
|
920
968
|
}
|
|
921
969
|
}
|
|
922
970
|
else {
|
|
923
971
|
assert(resetOp.type !== MergeTreeDeltaType.GROUP, 0x03c /* "Reset op has 'group' delta type!" */);
|
|
924
972
|
assert(!Array.isArray(segmentGroup), 0x03d /* "segmentGroup is array rather than singleton!" */);
|
|
925
|
-
opList.push(...this.resetPendingDeltaToOps(resetOp, segmentGroup));
|
|
973
|
+
opList.push(...this.resetPendingDeltaToOps(resetOp, segmentGroup, squash));
|
|
926
974
|
}
|
|
927
975
|
return opList.length === 1 ? opList[0] : createGroupOp(...opList);
|
|
928
976
|
}
|
|
@@ -1009,19 +1057,14 @@ export class Client extends TypedEventEmitter {
|
|
|
1009
1057
|
return this._mergeTree.getContainingSegment(pos, perspective);
|
|
1010
1058
|
}
|
|
1011
1059
|
getPropertiesAtPosition(pos) {
|
|
1012
|
-
let propertiesAtPosition;
|
|
1013
1060
|
const segoff = this.getContainingSegment(pos);
|
|
1014
|
-
|
|
1015
|
-
if (seg) {
|
|
1016
|
-
propertiesAtPosition = seg.properties;
|
|
1017
|
-
}
|
|
1018
|
-
return propertiesAtPosition;
|
|
1061
|
+
return segoff?.segment?.properties;
|
|
1019
1062
|
}
|
|
1020
1063
|
getRangeExtentsOfPosition(pos) {
|
|
1021
1064
|
let posStart;
|
|
1022
1065
|
let posAfterEnd;
|
|
1023
1066
|
const segoff = this.getContainingSegment(pos);
|
|
1024
|
-
const seg = segoff
|
|
1067
|
+
const seg = segoff?.segment;
|
|
1025
1068
|
if (seg) {
|
|
1026
1069
|
posStart = this.getPosition(seg);
|
|
1027
1070
|
posAfterEnd = posStart + seg.cachedLength;
|