@fluidframework/sequence 2.43.0 → 2.50.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 +4 -0
- package/dist/intervalCollection.d.ts +4 -5
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +93 -97
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalCollectionMapInterfaces.d.ts +2 -11
- package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/dist/intervalCollectionMapInterfaces.js.map +1 -1
- package/dist/intervals/sequenceInterval.d.ts +7 -3
- package/dist/intervals/sequenceInterval.d.ts.map +1 -1
- package/dist/intervals/sequenceInterval.js +72 -30
- package/dist/intervals/sequenceInterval.js.map +1 -1
- package/dist/packageVersion.d.ts +1 -1
- package/dist/packageVersion.js +1 -1
- package/dist/packageVersion.js.map +1 -1
- package/lib/intervalCollection.d.ts +4 -5
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +93 -97
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalCollectionMapInterfaces.d.ts +2 -11
- package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/lib/intervalCollectionMapInterfaces.js.map +1 -1
- package/lib/intervals/sequenceInterval.d.ts +7 -3
- package/lib/intervals/sequenceInterval.d.ts.map +1 -1
- package/lib/intervals/sequenceInterval.js +74 -32
- package/lib/intervals/sequenceInterval.js.map +1 -1
- package/lib/packageVersion.d.ts +1 -1
- package/lib/packageVersion.js +1 -1
- package/lib/packageVersion.js.map +1 -1
- package/package.json +17 -17
- package/src/intervalCollection.ts +109 -106
- package/src/intervalCollectionMapInterfaces.ts +2 -13
- package/src/intervals/sequenceInterval.ts +88 -32
- package/src/packageVersion.ts +1 -1
|
@@ -7,7 +7,12 @@
|
|
|
7
7
|
|
|
8
8
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
9
9
|
import { IEvent } from "@fluidframework/core-interfaces";
|
|
10
|
-
import {
|
|
10
|
+
import {
|
|
11
|
+
assert,
|
|
12
|
+
DoublyLinkedList,
|
|
13
|
+
unreachableCase,
|
|
14
|
+
type ListNode,
|
|
15
|
+
} from "@fluidframework/core-utils/internal";
|
|
11
16
|
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
12
17
|
import {
|
|
13
18
|
Client,
|
|
@@ -23,8 +28,6 @@ import {
|
|
|
23
28
|
endpointPosAndSide,
|
|
24
29
|
type ISegmentInternal,
|
|
25
30
|
createLocalReconnectingPerspective,
|
|
26
|
-
DoublyLinkedList,
|
|
27
|
-
type ListNode,
|
|
28
31
|
SlidingPreference,
|
|
29
32
|
} from "@fluidframework/merge-tree/internal";
|
|
30
33
|
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
@@ -194,7 +197,6 @@ export class LocalIntervalCollection {
|
|
|
194
197
|
end: SequencePlace,
|
|
195
198
|
props?: PropertySet,
|
|
196
199
|
op?: ISequencedDocumentMessage,
|
|
197
|
-
rollback?: boolean,
|
|
198
200
|
) {
|
|
199
201
|
// This check is intended to prevent scenarios where a random interval is created and then
|
|
200
202
|
// inserted into a collection. The aim is to ensure that the collection is created first
|
|
@@ -218,7 +220,7 @@ export class LocalIntervalCollection {
|
|
|
218
220
|
undefined,
|
|
219
221
|
this.options.mergeTreeReferencesCanSlideToEndpoint,
|
|
220
222
|
props,
|
|
221
|
-
|
|
223
|
+
false,
|
|
222
224
|
);
|
|
223
225
|
|
|
224
226
|
this.add(interval);
|
|
@@ -690,6 +692,7 @@ type PendingChanges = Partial<
|
|
|
690
692
|
endpointChanges?: DoublyLinkedList<
|
|
691
693
|
IntervalAddLocalMetadata | IntervalChangeLocalMetadata
|
|
692
694
|
>;
|
|
695
|
+
consensus: SequenceIntervalClass | undefined;
|
|
693
696
|
}
|
|
694
697
|
>
|
|
695
698
|
>;
|
|
@@ -706,8 +709,7 @@ function removeMetadataFromPendingChanges(
|
|
|
706
709
|
|
|
707
710
|
function clearEmptyPendingEntry(pendingChanges: PendingChanges, id: string) {
|
|
708
711
|
const pending = pendingChanges[id];
|
|
709
|
-
|
|
710
|
-
if (pending.local.empty) {
|
|
712
|
+
if (pending !== undefined && pending.local.empty) {
|
|
711
713
|
assert(
|
|
712
714
|
pending.endpointChanges?.empty !== false,
|
|
713
715
|
0xbc0 /* endpointChanges must be empty if not pending changes */,
|
|
@@ -715,6 +717,7 @@ function clearEmptyPendingEntry(pendingChanges: PendingChanges, id: string) {
|
|
|
715
717
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
716
718
|
delete pendingChanges[id];
|
|
717
719
|
}
|
|
720
|
+
return pending;
|
|
718
721
|
}
|
|
719
722
|
|
|
720
723
|
function hasEndpointChanges(
|
|
@@ -744,6 +747,7 @@ export class IntervalCollection
|
|
|
744
747
|
private readonly submitDelta: (
|
|
745
748
|
op: IIntervalCollectionTypeOperationValue,
|
|
746
749
|
md: IntervalMessageLocalMetadata,
|
|
750
|
+
consensus?: SequenceIntervalClass,
|
|
747
751
|
) => void;
|
|
748
752
|
|
|
749
753
|
constructor(
|
|
@@ -753,15 +757,15 @@ export class IntervalCollection
|
|
|
753
757
|
) {
|
|
754
758
|
super();
|
|
755
759
|
|
|
756
|
-
this.submitDelta = (op, md) => {
|
|
760
|
+
this.submitDelta = (op, md, consensus) => {
|
|
757
761
|
const { id } = getSerializedProperties(op.value);
|
|
758
762
|
const pending = (this.pending[id] ??= {
|
|
759
763
|
local: new DoublyLinkedList(),
|
|
764
|
+
consensus,
|
|
760
765
|
});
|
|
761
766
|
if (md.type === "add" || (md.type === "change" && hasEndpointChanges(op.value))) {
|
|
762
767
|
const endpointChanges = (pending.endpointChanges ??= new DoublyLinkedList());
|
|
763
768
|
md.endpointChangesNode = endpointChanges.push(md).last;
|
|
764
|
-
md.rebased = undefined;
|
|
765
769
|
}
|
|
766
770
|
submitDelta(op, pending.local.push(md).last);
|
|
767
771
|
};
|
|
@@ -811,48 +815,45 @@ export class IntervalCollection
|
|
|
811
815
|
const localOpMetadata = removeMetadataFromPendingChanges(maybeMetadata);
|
|
812
816
|
const { value } = op;
|
|
813
817
|
const { id, properties } = getSerializedProperties(value);
|
|
814
|
-
const
|
|
818
|
+
const pending = clearEmptyPendingEntry(this.pending, id);
|
|
819
|
+
const previous = pending?.local.empty
|
|
820
|
+
? pending.consensus
|
|
821
|
+
: pending?.local.last?.data.interval;
|
|
822
|
+
const { type, interval } = localOpMetadata;
|
|
815
823
|
switch (type) {
|
|
816
824
|
case "add": {
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
this.deleteExistingInterval({ interval, local: true, rollback: true });
|
|
820
|
-
}
|
|
825
|
+
this.deleteExistingInterval({ interval, local: true, rollback: true });
|
|
826
|
+
interval.dispose();
|
|
821
827
|
break;
|
|
822
828
|
}
|
|
823
829
|
case "change": {
|
|
824
|
-
const
|
|
825
|
-
const
|
|
826
|
-
|
|
827
|
-
? toOptionalSequencePlace(previous.start, previous.startSide)
|
|
830
|
+
const changeProperties = Object.keys(properties).length > 0;
|
|
831
|
+
const deltaProps = changeProperties
|
|
832
|
+
? interval.changeProperties(properties, undefined, true)
|
|
828
833
|
: undefined;
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
}
|
|
834
|
+
if (localOpMetadata.endpointChangesNode !== undefined) {
|
|
835
|
+
this.localCollection?.removeExistingInterval(interval);
|
|
836
|
+
assert(previous !== undefined, 0xbd2 /* must have existed to change */);
|
|
837
|
+
this.localCollection?.add(previous);
|
|
838
|
+
this.emitChange(previous, interval, true, true);
|
|
839
|
+
}
|
|
840
|
+
if (previous !== interval) {
|
|
841
|
+
interval.dispose();
|
|
842
|
+
}
|
|
843
|
+
if (changeProperties) {
|
|
844
|
+
this.emit("propertyChanged", previous, deltaProps, true, undefined);
|
|
845
|
+
}
|
|
838
846
|
break;
|
|
839
847
|
}
|
|
840
848
|
case "delete": {
|
|
841
|
-
|
|
842
|
-
this.add(
|
|
843
|
-
|
|
844
|
-
start: toSequencePlace(previous.start, previous.startSide),
|
|
845
|
-
end: toSequencePlace(previous.end, previous.endSide),
|
|
846
|
-
props: Object.keys(properties).length > 0 ? properties : undefined,
|
|
847
|
-
rollback: true,
|
|
848
|
-
});
|
|
849
|
+
assert(previous !== undefined, 0xbd3 /* must have existed to delete */);
|
|
850
|
+
this.localCollection?.add(previous);
|
|
851
|
+
this.emit("addInterval", previous, true, undefined);
|
|
849
852
|
break;
|
|
850
853
|
}
|
|
851
854
|
default:
|
|
852
855
|
unreachableCase(type);
|
|
853
856
|
}
|
|
854
|
-
|
|
855
|
-
clearEmptyPendingEntry(this.pending, id);
|
|
856
857
|
}
|
|
857
858
|
|
|
858
859
|
public process(
|
|
@@ -866,13 +867,15 @@ export class IntervalCollection
|
|
|
866
867
|
: undefined;
|
|
867
868
|
|
|
868
869
|
const { opName, value } = op;
|
|
870
|
+
const { id } = getSerializedProperties(value);
|
|
869
871
|
assert(
|
|
870
872
|
(local === false && localOpMetadata === undefined) || opName === localOpMetadata?.type,
|
|
871
873
|
0xbc1 /* must be same type */,
|
|
872
874
|
);
|
|
875
|
+
let newConsensus = localOpMetadata?.interval;
|
|
873
876
|
switch (opName) {
|
|
874
877
|
case "add": {
|
|
875
|
-
this.ackAdd(
|
|
878
|
+
newConsensus = this.ackAdd(
|
|
876
879
|
value,
|
|
877
880
|
local,
|
|
878
881
|
message,
|
|
@@ -889,16 +892,22 @@ export class IntervalCollection
|
|
|
889
892
|
}
|
|
890
893
|
|
|
891
894
|
case "change": {
|
|
892
|
-
this.ackChange(
|
|
895
|
+
newConsensus = this.ackChange(
|
|
896
|
+
value,
|
|
897
|
+
local,
|
|
898
|
+
message, // this cast is safe because of the above assert which
|
|
899
|
+
// validates the op and metadata types match for local changes
|
|
900
|
+
localOpMetadata as IntervalChangeLocalMetadata | undefined,
|
|
901
|
+
);
|
|
893
902
|
break;
|
|
894
903
|
}
|
|
895
904
|
default:
|
|
896
905
|
unreachableCase(opName);
|
|
897
906
|
}
|
|
907
|
+
const pending = clearEmptyPendingEntry(this.pending, id);
|
|
898
908
|
|
|
899
|
-
if (
|
|
900
|
-
|
|
901
|
-
clearEmptyPendingEntry(this.pending, id);
|
|
909
|
+
if (pending !== undefined) {
|
|
910
|
+
pending.consensus = newConsensus;
|
|
902
911
|
}
|
|
903
912
|
}
|
|
904
913
|
|
|
@@ -1037,7 +1046,7 @@ export class IntervalCollection
|
|
|
1037
1046
|
for (const pending of Object.values(this.pending)) {
|
|
1038
1047
|
if (pending?.endpointChanges !== undefined) {
|
|
1039
1048
|
for (const local of pending.endpointChanges) {
|
|
1040
|
-
local.data.
|
|
1049
|
+
this.rebaseLocalInterval(local.data.interval.serialize(), local.data, squash);
|
|
1041
1050
|
}
|
|
1042
1051
|
}
|
|
1043
1052
|
}
|
|
@@ -1147,13 +1156,11 @@ export class IntervalCollection
|
|
|
1147
1156
|
start,
|
|
1148
1157
|
end,
|
|
1149
1158
|
props,
|
|
1150
|
-
rollback,
|
|
1151
1159
|
}: {
|
|
1152
1160
|
id?: string;
|
|
1153
1161
|
start: SequencePlace;
|
|
1154
1162
|
end: SequencePlace;
|
|
1155
1163
|
props?: PropertySet;
|
|
1156
|
-
rollback?: boolean;
|
|
1157
1164
|
}): SequenceIntervalClass {
|
|
1158
1165
|
if (!this.localCollection) {
|
|
1159
1166
|
throw new LoggingError("attach must be called prior to adding intervals");
|
|
@@ -1179,7 +1186,6 @@ export class IntervalCollection
|
|
|
1179
1186
|
toSequencePlace(endPos, endSide),
|
|
1180
1187
|
props,
|
|
1181
1188
|
undefined,
|
|
1182
|
-
rollback,
|
|
1183
1189
|
);
|
|
1184
1190
|
|
|
1185
1191
|
if (interval) {
|
|
@@ -1189,7 +1195,7 @@ export class IntervalCollection
|
|
|
1189
1195
|
}
|
|
1190
1196
|
const serializedInterval: ISerializedInterval = interval.serialize();
|
|
1191
1197
|
const localSeq = this.getNextLocalSeq();
|
|
1192
|
-
if (this.isCollaborating
|
|
1198
|
+
if (this.isCollaborating) {
|
|
1193
1199
|
this.submitDelta(
|
|
1194
1200
|
{
|
|
1195
1201
|
opName: "add",
|
|
@@ -1238,8 +1244,8 @@ export class IntervalCollection
|
|
|
1238
1244
|
{
|
|
1239
1245
|
type: "delete",
|
|
1240
1246
|
localSeq: this.getNextLocalSeq(),
|
|
1241
|
-
previous: value,
|
|
1242
1247
|
},
|
|
1248
|
+
interval,
|
|
1243
1249
|
);
|
|
1244
1250
|
} else {
|
|
1245
1251
|
if (this.onDeserialize) {
|
|
@@ -1258,7 +1264,7 @@ export class IntervalCollection
|
|
|
1258
1264
|
if (!this.localCollection) {
|
|
1259
1265
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
1260
1266
|
}
|
|
1261
|
-
const interval = this.
|
|
1267
|
+
const interval = this.getIntervalById(id);
|
|
1262
1268
|
if (interval) {
|
|
1263
1269
|
this.deleteExistingInterval({ interval, local: true });
|
|
1264
1270
|
}
|
|
@@ -1326,7 +1332,6 @@ export class IntervalCollection
|
|
|
1326
1332
|
const metadata: IntervalChangeLocalMetadata = {
|
|
1327
1333
|
type: "change",
|
|
1328
1334
|
localSeq,
|
|
1329
|
-
previous: interval.serialize(),
|
|
1330
1335
|
interval: newInterval ?? interval,
|
|
1331
1336
|
};
|
|
1332
1337
|
|
|
@@ -1336,6 +1341,7 @@ export class IntervalCollection
|
|
|
1336
1341
|
value: serializedInterval,
|
|
1337
1342
|
},
|
|
1338
1343
|
metadata,
|
|
1344
|
+
interval,
|
|
1339
1345
|
);
|
|
1340
1346
|
}
|
|
1341
1347
|
if (deltaProps !== undefined) {
|
|
@@ -1374,6 +1380,7 @@ export class IntervalCollection
|
|
|
1374
1380
|
serializedInterval: SerializedIntervalDelta,
|
|
1375
1381
|
local: boolean,
|
|
1376
1382
|
op: ISequencedDocumentMessage,
|
|
1383
|
+
localOpMetadata: IntervalChangeLocalMetadata | undefined,
|
|
1377
1384
|
) {
|
|
1378
1385
|
if (!this.localCollection) {
|
|
1379
1386
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
@@ -1384,55 +1391,51 @@ export class IntervalCollection
|
|
|
1384
1391
|
// strip it out of the properties here.
|
|
1385
1392
|
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
1386
1393
|
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
1387
|
-
const interval: SequenceIntervalClass | undefined = this.getIntervalById(id);
|
|
1388
|
-
|
|
1389
|
-
if (!interval) {
|
|
1390
|
-
// The interval has been removed locally; no-op.
|
|
1391
|
-
return;
|
|
1392
|
-
}
|
|
1393
1394
|
|
|
1394
1395
|
if (local) {
|
|
1396
|
+
assert(localOpMetadata !== undefined, 0xbd4 /* local must have metadata */);
|
|
1397
|
+
const { interval } = localOpMetadata;
|
|
1395
1398
|
interval.ackPropertiesChange(properties, op);
|
|
1396
1399
|
|
|
1397
1400
|
this.ackInterval(interval, op);
|
|
1401
|
+
return interval;
|
|
1398
1402
|
} else {
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
let end: number | "start" | "end" | undefined;
|
|
1403
|
-
// Track pending start/end independently of one another.
|
|
1404
|
-
if (!this.hasPendingEndpointChanges(id)) {
|
|
1405
|
-
start = serializedInterval.start;
|
|
1406
|
-
end = serializedInterval.end;
|
|
1407
|
-
}
|
|
1403
|
+
const latestInterval = this.getIntervalById(id);
|
|
1404
|
+
const intervalToChange: SequenceIntervalClass | undefined =
|
|
1405
|
+
this.pending[id]?.consensus ?? latestInterval;
|
|
1408
1406
|
|
|
1409
|
-
|
|
1410
|
-
if (start !== undefined || end !== undefined) {
|
|
1411
|
-
// If changeInterval gives us a new interval, work with that one. Otherwise keep working with
|
|
1412
|
-
// the one we originally found in the tree.
|
|
1413
|
-
newInterval =
|
|
1414
|
-
this.localCollection.changeInterval(
|
|
1415
|
-
interval,
|
|
1416
|
-
toOptionalSequencePlace(start, serializedInterval.startSide ?? Side.Before),
|
|
1417
|
-
toOptionalSequencePlace(end, serializedInterval.endSide ?? Side.Before),
|
|
1418
|
-
op,
|
|
1419
|
-
) ?? interval;
|
|
1420
|
-
}
|
|
1421
|
-
const deltaProps = newInterval.changeProperties(properties, op);
|
|
1407
|
+
const isLatestInterval = intervalToChange === latestInterval;
|
|
1422
1408
|
|
|
1423
|
-
if (
|
|
1424
|
-
|
|
1409
|
+
if (!intervalToChange) {
|
|
1410
|
+
return intervalToChange;
|
|
1425
1411
|
}
|
|
1426
1412
|
|
|
1427
|
-
|
|
1428
|
-
|
|
1413
|
+
const deltaProps = intervalToChange.changeProperties(properties, op);
|
|
1414
|
+
|
|
1415
|
+
let newInterval = intervalToChange;
|
|
1416
|
+
if (hasEndpointChanges(serializedInterval)) {
|
|
1417
|
+
const { start, end, startSide, endSide } = serializedInterval;
|
|
1418
|
+
newInterval = intervalToChange.modify(
|
|
1419
|
+
"",
|
|
1420
|
+
toOptionalSequencePlace(start, startSide ?? Side.Before),
|
|
1421
|
+
toOptionalSequencePlace(end, endSide ?? Side.Before),
|
|
1422
|
+
op,
|
|
1423
|
+
);
|
|
1424
|
+
if (isLatestInterval) {
|
|
1425
|
+
this.localCollection.removeExistingInterval(intervalToChange);
|
|
1426
|
+
this.localCollection.add(newInterval);
|
|
1427
|
+
this.emitChange(newInterval, intervalToChange, local, false, op);
|
|
1428
|
+
if (this.onDeserialize) {
|
|
1429
|
+
this.onDeserialize(newInterval);
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1429
1432
|
}
|
|
1430
1433
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
this.emit("
|
|
1434
|
-
this.emit("changed", interval, deltaProps, undefined, local, false);
|
|
1434
|
+
if (deltaProps !== undefined && Object.keys(deltaProps).length > 0) {
|
|
1435
|
+
this.emit("propertyChanged", latestInterval, deltaProps, local, op);
|
|
1436
|
+
this.emit("changed", latestInterval, deltaProps, undefined, local, false);
|
|
1435
1437
|
}
|
|
1438
|
+
return newInterval;
|
|
1436
1439
|
}
|
|
1437
1440
|
}
|
|
1438
1441
|
|
|
@@ -1475,11 +1478,9 @@ export class IntervalCollection
|
|
|
1475
1478
|
|
|
1476
1479
|
const { localSeq, interval } = localOpMetadata;
|
|
1477
1480
|
const { id } = getSerializedProperties(original);
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
));
|
|
1482
|
-
const localInterval = this.localCollection.idIntervalIndex.getIntervalById(id);
|
|
1481
|
+
|
|
1482
|
+
const rebasedEndpoint = this.computeRebasedPositions(localOpMetadata, squash);
|
|
1483
|
+
const localInterval = this.getIntervalById(id);
|
|
1483
1484
|
|
|
1484
1485
|
// if the interval slid off the string, rebase the op to be a noop and delete the interval.
|
|
1485
1486
|
if (rebasedEndpoint === "detached") {
|
|
@@ -1508,8 +1509,7 @@ export class IntervalCollection
|
|
|
1508
1509
|
this.localCollection.add(interval);
|
|
1509
1510
|
this.emitChange(interval, old, true, true);
|
|
1510
1511
|
}
|
|
1511
|
-
|
|
1512
|
-
this.client.removeLocalReferencePosition(old.end);
|
|
1512
|
+
old.dispose();
|
|
1513
1513
|
}
|
|
1514
1514
|
|
|
1515
1515
|
return {
|
|
@@ -1580,10 +1580,14 @@ export class IntervalCollection
|
|
|
1580
1580
|
// `interval`'s endpoints will get modified in-place, so clone it prior to doing so for event emission.
|
|
1581
1581
|
const oldInterval = interval.clone();
|
|
1582
1582
|
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1583
|
+
const isLatestInterval = this.getIntervalById(id) === interval;
|
|
1584
|
+
|
|
1585
|
+
if (isLatestInterval) {
|
|
1586
|
+
// In this case, where we change the start or end of an interval,
|
|
1587
|
+
// it is necessary to remove and re-add the interval listeners.
|
|
1588
|
+
// This ensures that the correct listeners are added to the LocalReferencePosition.
|
|
1589
|
+
this.localCollection.removeExistingInterval(interval);
|
|
1590
|
+
}
|
|
1587
1591
|
if (!this.client) {
|
|
1588
1592
|
throw new LoggingError("client does not exist");
|
|
1589
1593
|
}
|
|
@@ -1626,8 +1630,10 @@ export class IntervalCollection
|
|
|
1626
1630
|
oldInterval.end.refType = ReferenceType.Transient;
|
|
1627
1631
|
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
1628
1632
|
}
|
|
1629
|
-
|
|
1630
|
-
|
|
1633
|
+
if (isLatestInterval) {
|
|
1634
|
+
this.localCollection.add(interval);
|
|
1635
|
+
this.emitChange(interval, oldInterval, true, true, op);
|
|
1636
|
+
}
|
|
1631
1637
|
}
|
|
1632
1638
|
}
|
|
1633
1639
|
|
|
@@ -1636,7 +1642,7 @@ export class IntervalCollection
|
|
|
1636
1642
|
local: boolean,
|
|
1637
1643
|
op: ISequencedDocumentMessage,
|
|
1638
1644
|
localOpMetadata: IntervalAddLocalMetadata | undefined,
|
|
1639
|
-
) {
|
|
1645
|
+
): SequenceIntervalClass {
|
|
1640
1646
|
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
1641
1647
|
|
|
1642
1648
|
if (local) {
|
|
@@ -1644,11 +1650,8 @@ export class IntervalCollection
|
|
|
1644
1650
|
localOpMetadata !== undefined,
|
|
1645
1651
|
0x553 /* op metadata should be defined for local op */,
|
|
1646
1652
|
);
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
this.ackInterval(localInterval, op);
|
|
1650
|
-
}
|
|
1651
|
-
return;
|
|
1653
|
+
this.ackInterval(localOpMetadata.interval, op);
|
|
1654
|
+
return localOpMetadata.interval;
|
|
1652
1655
|
}
|
|
1653
1656
|
|
|
1654
1657
|
if (!this.localCollection) {
|
|
@@ -1691,7 +1694,7 @@ export class IntervalCollection
|
|
|
1691
1694
|
}
|
|
1692
1695
|
|
|
1693
1696
|
const { id } = getSerializedProperties(serializedInterval);
|
|
1694
|
-
const interval = this.
|
|
1697
|
+
const interval = this.getIntervalById(id);
|
|
1695
1698
|
if (interval) {
|
|
1696
1699
|
this.deleteExistingInterval({ interval, local, op });
|
|
1697
1700
|
}
|
|
@@ -3,12 +3,9 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import type { ListNode } from "@fluidframework/core-utils/internal";
|
|
6
7
|
import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
|
|
7
|
-
import {
|
|
8
|
-
IMergeTreeOptions,
|
|
9
|
-
ListNode,
|
|
10
|
-
type ISegmentInternal,
|
|
11
|
-
} from "@fluidframework/merge-tree/internal";
|
|
8
|
+
import { IMergeTreeOptions } from "@fluidframework/merge-tree/internal";
|
|
12
9
|
|
|
13
10
|
import type {
|
|
14
11
|
IntervalCollection,
|
|
@@ -26,25 +23,17 @@ export interface IntervalAddLocalMetadata {
|
|
|
26
23
|
type: typeof IntervalDeltaOpType.ADD;
|
|
27
24
|
localSeq: number;
|
|
28
25
|
endpointChangesNode?: ListNode<IntervalAddLocalMetadata | IntervalChangeLocalMetadata>;
|
|
29
|
-
rebased?:
|
|
30
|
-
| Record<"start" | "end", { segment: ISegmentInternal; offset: number }>
|
|
31
|
-
| "detached";
|
|
32
26
|
interval: SequenceIntervalClass;
|
|
33
27
|
}
|
|
34
28
|
export interface IntervalChangeLocalMetadata {
|
|
35
29
|
type: typeof IntervalDeltaOpType.CHANGE;
|
|
36
30
|
localSeq: number;
|
|
37
|
-
previous: ISerializedInterval;
|
|
38
31
|
endpointChangesNode?: ListNode<IntervalChangeLocalMetadata | IntervalChangeLocalMetadata>;
|
|
39
|
-
rebased?:
|
|
40
|
-
| Record<"start" | "end", { segment: ISegmentInternal; offset: number }>
|
|
41
|
-
| "detached";
|
|
42
32
|
interval: SequenceIntervalClass;
|
|
43
33
|
}
|
|
44
34
|
export interface IntervalDeleteLocalMetadata {
|
|
45
35
|
type: typeof IntervalDeltaOpType.DELETE;
|
|
46
36
|
localSeq: number;
|
|
47
|
-
previous: ISerializedInterval;
|
|
48
37
|
endpointChangesNode?: undefined;
|
|
49
38
|
interval?: undefined;
|
|
50
39
|
}
|