@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
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/* eslint-disable no-bitwise */
|
|
6
6
|
import { TypedEventEmitter } from "@fluid-internal/client-utils";
|
|
7
|
-
import { assert, unreachableCase } from "@fluidframework/core-utils/internal";
|
|
8
|
-
import { ReferenceType, getSlideToSegoff, refTypeIncludesFlag, reservedRangeLabelsKey, Side, endpointPosAndSide, createLocalReconnectingPerspective,
|
|
7
|
+
import { assert, DoublyLinkedList, unreachableCase, } from "@fluidframework/core-utils/internal";
|
|
8
|
+
import { ReferenceType, getSlideToSegoff, refTypeIncludesFlag, reservedRangeLabelsKey, Side, endpointPosAndSide, createLocalReconnectingPerspective, SlidingPreference, } from "@fluidframework/merge-tree/internal";
|
|
9
9
|
import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
|
|
10
10
|
import { v4 as uuid } from "uuid";
|
|
11
11
|
import { createIdIntervalIndex, EndpointIndex, OverlappingIntervalsIndex, } from "./intervalIndex/index.js";
|
|
@@ -99,7 +99,7 @@ export class LocalIntervalCollection {
|
|
|
99
99
|
this.removeIntervalFromIndexes(interval);
|
|
100
100
|
this.removeIntervalListeners(interval);
|
|
101
101
|
}
|
|
102
|
-
addInterval(id, start, end, props, op
|
|
102
|
+
addInterval(id, start, end, props, op) {
|
|
103
103
|
// This check is intended to prevent scenarios where a random interval is created and then
|
|
104
104
|
// inserted into a collection. The aim is to ensure that the collection is created first
|
|
105
105
|
// then the user can create/add intervals based on the collection
|
|
@@ -107,7 +107,7 @@ export class LocalIntervalCollection {
|
|
|
107
107
|
props[reservedRangeLabelsKey][0] !== this.label) {
|
|
108
108
|
throw new LoggingError("Adding an interval that belongs to another interval collection is not permitted");
|
|
109
109
|
}
|
|
110
|
-
const interval = createSequenceInterval(this.label, id, start, end, this.client, IntervalType.SlideOnRemove, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint, props,
|
|
110
|
+
const interval = createSequenceInterval(this.label, id, start, end, this.client, IntervalType.SlideOnRemove, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint, props, false);
|
|
111
111
|
this.add(interval);
|
|
112
112
|
return interval;
|
|
113
113
|
}
|
|
@@ -207,12 +207,12 @@ function removeMetadataFromPendingChanges(localOpMetadataNode) {
|
|
|
207
207
|
}
|
|
208
208
|
function clearEmptyPendingEntry(pendingChanges, id) {
|
|
209
209
|
const pending = pendingChanges[id];
|
|
210
|
-
|
|
211
|
-
if (pending.local.empty) {
|
|
210
|
+
if (pending !== undefined && pending.local.empty) {
|
|
212
211
|
assert(pending.endpointChanges?.empty !== false, 0xbc0 /* endpointChanges must be empty if not pending changes */);
|
|
213
212
|
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
214
213
|
delete pendingChanges[id];
|
|
215
214
|
}
|
|
215
|
+
return pending;
|
|
216
216
|
}
|
|
217
217
|
function hasEndpointChanges(serialized) {
|
|
218
218
|
return serialized.start !== undefined && serialized.end !== undefined;
|
|
@@ -228,15 +228,15 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
228
228
|
super();
|
|
229
229
|
this.options = options;
|
|
230
230
|
this.pending = {};
|
|
231
|
-
this.submitDelta = (op, md) => {
|
|
231
|
+
this.submitDelta = (op, md, consensus) => {
|
|
232
232
|
const { id } = getSerializedProperties(op.value);
|
|
233
233
|
const pending = (this.pending[id] ??= {
|
|
234
234
|
local: new DoublyLinkedList(),
|
|
235
|
+
consensus,
|
|
235
236
|
});
|
|
236
237
|
if (md.type === "add" || (md.type === "change" && hasEndpointChanges(op.value))) {
|
|
237
238
|
const endpointChanges = (pending.endpointChanges ??= new DoublyLinkedList());
|
|
238
239
|
md.endpointChangesNode = endpointChanges.push(md).last;
|
|
239
|
-
md.rebased = undefined;
|
|
240
240
|
}
|
|
241
241
|
submitDelta(op, pending.local.push(md).last);
|
|
242
242
|
};
|
|
@@ -276,57 +276,57 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
276
276
|
const localOpMetadata = removeMetadataFromPendingChanges(maybeMetadata);
|
|
277
277
|
const { value } = op;
|
|
278
278
|
const { id, properties } = getSerializedProperties(value);
|
|
279
|
-
const
|
|
279
|
+
const pending = clearEmptyPendingEntry(this.pending, id);
|
|
280
|
+
const previous = pending?.local.empty
|
|
281
|
+
? pending.consensus
|
|
282
|
+
: pending?.local.last?.data.interval;
|
|
283
|
+
const { type, interval } = localOpMetadata;
|
|
280
284
|
switch (type) {
|
|
281
285
|
case "add": {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
this.deleteExistingInterval({ interval, local: true, rollback: true });
|
|
285
|
-
}
|
|
286
|
+
this.deleteExistingInterval({ interval, local: true, rollback: true });
|
|
287
|
+
interval.dispose();
|
|
286
288
|
break;
|
|
287
289
|
}
|
|
288
290
|
case "change": {
|
|
289
|
-
const
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
? toOptionalSequencePlace(previous.start, previous.startSide)
|
|
293
|
-
: undefined;
|
|
294
|
-
const end = endpointsChanged
|
|
295
|
-
? toOptionalSequencePlace(previous.end, previous.endSide)
|
|
291
|
+
const changeProperties = Object.keys(properties).length > 0;
|
|
292
|
+
const deltaProps = changeProperties
|
|
293
|
+
? interval.changeProperties(properties, undefined, true)
|
|
296
294
|
: undefined;
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
}
|
|
295
|
+
if (localOpMetadata.endpointChangesNode !== undefined) {
|
|
296
|
+
this.localCollection?.removeExistingInterval(interval);
|
|
297
|
+
assert(previous !== undefined, 0xbd2 /* must have existed to change */);
|
|
298
|
+
this.localCollection?.add(previous);
|
|
299
|
+
this.emitChange(previous, interval, true, true);
|
|
300
|
+
}
|
|
301
|
+
if (previous !== interval) {
|
|
302
|
+
interval.dispose();
|
|
303
|
+
}
|
|
304
|
+
if (changeProperties) {
|
|
305
|
+
this.emit("propertyChanged", previous, deltaProps, true, undefined);
|
|
306
|
+
}
|
|
303
307
|
break;
|
|
304
308
|
}
|
|
305
309
|
case "delete": {
|
|
306
|
-
|
|
307
|
-
this.add(
|
|
308
|
-
|
|
309
|
-
start: toSequencePlace(previous.start, previous.startSide),
|
|
310
|
-
end: toSequencePlace(previous.end, previous.endSide),
|
|
311
|
-
props: Object.keys(properties).length > 0 ? properties : undefined,
|
|
312
|
-
rollback: true,
|
|
313
|
-
});
|
|
310
|
+
assert(previous !== undefined, 0xbd3 /* must have existed to delete */);
|
|
311
|
+
this.localCollection?.add(previous);
|
|
312
|
+
this.emit("addInterval", previous, true, undefined);
|
|
314
313
|
break;
|
|
315
314
|
}
|
|
316
315
|
default:
|
|
317
316
|
unreachableCase(type);
|
|
318
317
|
}
|
|
319
|
-
clearEmptyPendingEntry(this.pending, id);
|
|
320
318
|
}
|
|
321
319
|
process(op, local, message, maybeMetadata) {
|
|
322
320
|
const localOpMetadata = local
|
|
323
321
|
? removeMetadataFromPendingChanges(maybeMetadata)
|
|
324
322
|
: undefined;
|
|
325
323
|
const { opName, value } = op;
|
|
324
|
+
const { id } = getSerializedProperties(value);
|
|
326
325
|
assert((local === false && localOpMetadata === undefined) || opName === localOpMetadata?.type, 0xbc1 /* must be same type */);
|
|
326
|
+
let newConsensus = localOpMetadata?.interval;
|
|
327
327
|
switch (opName) {
|
|
328
328
|
case "add": {
|
|
329
|
-
this.ackAdd(value, local, message,
|
|
329
|
+
newConsensus = this.ackAdd(value, local, message,
|
|
330
330
|
// this cast is safe because of the above assert which
|
|
331
331
|
// validates the op and metadata types match for local changes
|
|
332
332
|
localOpMetadata);
|
|
@@ -337,15 +337,17 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
337
337
|
break;
|
|
338
338
|
}
|
|
339
339
|
case "change": {
|
|
340
|
-
this.ackChange(value, local, message
|
|
340
|
+
newConsensus = this.ackChange(value, local, message, // this cast is safe because of the above assert which
|
|
341
|
+
// validates the op and metadata types match for local changes
|
|
342
|
+
localOpMetadata);
|
|
341
343
|
break;
|
|
342
344
|
}
|
|
343
345
|
default:
|
|
344
346
|
unreachableCase(opName);
|
|
345
347
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
348
|
+
const pending = clearEmptyPendingEntry(this.pending, id);
|
|
349
|
+
if (pending !== undefined) {
|
|
350
|
+
pending.consensus = newConsensus;
|
|
349
351
|
}
|
|
350
352
|
}
|
|
351
353
|
resubmitMessage(op, maybeMetadata, squash) {
|
|
@@ -443,7 +445,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
443
445
|
for (const pending of Object.values(this.pending)) {
|
|
444
446
|
if (pending?.endpointChanges !== undefined) {
|
|
445
447
|
for (const local of pending.endpointChanges) {
|
|
446
|
-
local.data.
|
|
448
|
+
this.rebaseLocalInterval(local.data.interval.serialize(), local.data, squash);
|
|
447
449
|
}
|
|
448
450
|
}
|
|
449
451
|
}
|
|
@@ -506,7 +508,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
506
508
|
/**
|
|
507
509
|
* {@inheritdoc IIntervalCollection.add}
|
|
508
510
|
*/
|
|
509
|
-
add({ id, start, end, props,
|
|
511
|
+
add({ id, start, end, props, }) {
|
|
510
512
|
if (!this.localCollection) {
|
|
511
513
|
throw new LoggingError("attach must be called prior to adding intervals");
|
|
512
514
|
}
|
|
@@ -517,7 +519,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
517
519
|
endSide !== undefined, 0x793 /* start and end cannot be undefined because they were not passed in as undefined */);
|
|
518
520
|
this.assertStickinessEnabled(start, end);
|
|
519
521
|
const intervalId = id ?? uuid();
|
|
520
|
-
const interval = this.localCollection.addInterval(intervalId, toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), props, undefined
|
|
522
|
+
const interval = this.localCollection.addInterval(intervalId, toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), props, undefined);
|
|
521
523
|
if (interval) {
|
|
522
524
|
if (!this.isCollaborating) {
|
|
523
525
|
setSlideOnRemove(interval.start);
|
|
@@ -525,7 +527,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
525
527
|
}
|
|
526
528
|
const serializedInterval = interval.serialize();
|
|
527
529
|
const localSeq = this.getNextLocalSeq();
|
|
528
|
-
if (this.isCollaborating
|
|
530
|
+
if (this.isCollaborating) {
|
|
529
531
|
this.submitDelta({
|
|
530
532
|
opName: "add",
|
|
531
533
|
value: serializedInterval,
|
|
@@ -555,8 +557,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
555
557
|
}, {
|
|
556
558
|
type: "delete",
|
|
557
559
|
localSeq: this.getNextLocalSeq(),
|
|
558
|
-
|
|
559
|
-
});
|
|
560
|
+
}, interval);
|
|
560
561
|
}
|
|
561
562
|
else {
|
|
562
563
|
if (this.onDeserialize) {
|
|
@@ -573,7 +574,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
573
574
|
if (!this.localCollection) {
|
|
574
575
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
575
576
|
}
|
|
576
|
-
const interval = this.
|
|
577
|
+
const interval = this.getIntervalById(id);
|
|
577
578
|
if (interval) {
|
|
578
579
|
this.deleteExistingInterval({ interval, local: true });
|
|
579
580
|
}
|
|
@@ -621,13 +622,12 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
621
622
|
const metadata = {
|
|
622
623
|
type: "change",
|
|
623
624
|
localSeq,
|
|
624
|
-
previous: interval.serialize(),
|
|
625
625
|
interval: newInterval ?? interval,
|
|
626
626
|
};
|
|
627
627
|
this.submitDelta({
|
|
628
628
|
opName: "change",
|
|
629
629
|
value: serializedInterval,
|
|
630
|
-
}, metadata);
|
|
630
|
+
}, metadata, interval);
|
|
631
631
|
}
|
|
632
632
|
if (deltaProps !== undefined) {
|
|
633
633
|
this.emit("propertyChanged", interval, deltaProps, true, undefined);
|
|
@@ -651,7 +651,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
651
651
|
hasPendingEndpointChanges(id) {
|
|
652
652
|
return this.pending[id]?.endpointChanges?.empty === false;
|
|
653
653
|
}
|
|
654
|
-
ackChange(serializedInterval, local, op) {
|
|
654
|
+
ackChange(serializedInterval, local, op, localOpMetadata) {
|
|
655
655
|
if (!this.localCollection) {
|
|
656
656
|
throw new LoggingError("Attach must be called before accessing intervals");
|
|
657
657
|
}
|
|
@@ -660,44 +660,39 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
660
660
|
// strip it out of the properties here.
|
|
661
661
|
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
662
662
|
assert(id !== undefined, 0x3fe /* id must exist on the interval */);
|
|
663
|
-
const interval = this.getIntervalById(id);
|
|
664
|
-
if (!interval) {
|
|
665
|
-
// The interval has been removed locally; no-op.
|
|
666
|
-
return;
|
|
667
|
-
}
|
|
668
663
|
if (local) {
|
|
664
|
+
assert(localOpMetadata !== undefined, 0xbd4 /* local must have metadata */);
|
|
665
|
+
const { interval } = localOpMetadata;
|
|
669
666
|
interval.ackPropertiesChange(properties, op);
|
|
670
667
|
this.ackInterval(interval, op);
|
|
668
|
+
return interval;
|
|
671
669
|
}
|
|
672
670
|
else {
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
this.
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
}
|
|
693
|
-
if (newInterval !== interval) {
|
|
694
|
-
this.emitChange(newInterval, interval, local, false, op);
|
|
671
|
+
const latestInterval = this.getIntervalById(id);
|
|
672
|
+
const intervalToChange = this.pending[id]?.consensus ?? latestInterval;
|
|
673
|
+
const isLatestInterval = intervalToChange === latestInterval;
|
|
674
|
+
if (!intervalToChange) {
|
|
675
|
+
return intervalToChange;
|
|
676
|
+
}
|
|
677
|
+
const deltaProps = intervalToChange.changeProperties(properties, op);
|
|
678
|
+
let newInterval = intervalToChange;
|
|
679
|
+
if (hasEndpointChanges(serializedInterval)) {
|
|
680
|
+
const { start, end, startSide, endSide } = serializedInterval;
|
|
681
|
+
newInterval = intervalToChange.modify("", toOptionalSequencePlace(start, startSide ?? Side.Before), toOptionalSequencePlace(end, endSide ?? Side.Before), op);
|
|
682
|
+
if (isLatestInterval) {
|
|
683
|
+
this.localCollection.removeExistingInterval(intervalToChange);
|
|
684
|
+
this.localCollection.add(newInterval);
|
|
685
|
+
this.emitChange(newInterval, intervalToChange, local, false, op);
|
|
686
|
+
if (this.onDeserialize) {
|
|
687
|
+
this.onDeserialize(newInterval);
|
|
688
|
+
}
|
|
689
|
+
}
|
|
695
690
|
}
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
this.emit("
|
|
699
|
-
this.emit("changed", interval, deltaProps, undefined, local, false);
|
|
691
|
+
if (deltaProps !== undefined && Object.keys(deltaProps).length > 0) {
|
|
692
|
+
this.emit("propertyChanged", latestInterval, deltaProps, local, op);
|
|
693
|
+
this.emit("changed", latestInterval, deltaProps, undefined, local, false);
|
|
700
694
|
}
|
|
695
|
+
return newInterval;
|
|
701
696
|
}
|
|
702
697
|
}
|
|
703
698
|
/**
|
|
@@ -731,8 +726,8 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
731
726
|
}
|
|
732
727
|
const { localSeq, interval } = localOpMetadata;
|
|
733
728
|
const { id } = getSerializedProperties(original);
|
|
734
|
-
const rebasedEndpoint =
|
|
735
|
-
const localInterval = this.
|
|
729
|
+
const rebasedEndpoint = this.computeRebasedPositions(localOpMetadata, squash);
|
|
730
|
+
const localInterval = this.getIntervalById(id);
|
|
736
731
|
// if the interval slid off the string, rebase the op to be a noop and delete the interval.
|
|
737
732
|
if (rebasedEndpoint === "detached") {
|
|
738
733
|
if (localInterval !== undefined &&
|
|
@@ -755,8 +750,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
755
750
|
this.localCollection.add(interval);
|
|
756
751
|
this.emitChange(interval, old, true, true);
|
|
757
752
|
}
|
|
758
|
-
|
|
759
|
-
this.client.removeLocalReferencePosition(old.end);
|
|
753
|
+
old.dispose();
|
|
760
754
|
}
|
|
761
755
|
return {
|
|
762
756
|
...original,
|
|
@@ -805,10 +799,13 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
805
799
|
}
|
|
806
800
|
// `interval`'s endpoints will get modified in-place, so clone it prior to doing so for event emission.
|
|
807
801
|
const oldInterval = interval.clone();
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
802
|
+
const isLatestInterval = this.getIntervalById(id) === interval;
|
|
803
|
+
if (isLatestInterval) {
|
|
804
|
+
// In this case, where we change the start or end of an interval,
|
|
805
|
+
// it is necessary to remove and re-add the interval listeners.
|
|
806
|
+
// This ensures that the correct listeners are added to the LocalReferencePosition.
|
|
807
|
+
this.localCollection.removeExistingInterval(interval);
|
|
808
|
+
}
|
|
812
809
|
if (!this.client) {
|
|
813
810
|
throw new LoggingError("client does not exist");
|
|
814
811
|
}
|
|
@@ -850,19 +847,18 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
850
847
|
oldInterval.end.refType = ReferenceType.Transient;
|
|
851
848
|
oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
|
|
852
849
|
}
|
|
853
|
-
|
|
854
|
-
|
|
850
|
+
if (isLatestInterval) {
|
|
851
|
+
this.localCollection.add(interval);
|
|
852
|
+
this.emitChange(interval, oldInterval, true, true, op);
|
|
853
|
+
}
|
|
855
854
|
}
|
|
856
855
|
}
|
|
857
856
|
ackAdd(serializedInterval, local, op, localOpMetadata) {
|
|
858
857
|
const { id, properties } = getSerializedProperties(serializedInterval);
|
|
859
858
|
if (local) {
|
|
860
859
|
assert(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
this.ackInterval(localInterval, op);
|
|
864
|
-
}
|
|
865
|
-
return;
|
|
860
|
+
this.ackInterval(localOpMetadata.interval, op);
|
|
861
|
+
return localOpMetadata.interval;
|
|
866
862
|
}
|
|
867
863
|
if (!this.localCollection) {
|
|
868
864
|
throw new LoggingError("attachSequence must be called");
|
|
@@ -887,7 +883,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
887
883
|
throw new LoggingError("attach must be called prior to deleting intervals");
|
|
888
884
|
}
|
|
889
885
|
const { id } = getSerializedProperties(serializedInterval);
|
|
890
|
-
const interval = this.
|
|
886
|
+
const interval = this.getIntervalById(id);
|
|
891
887
|
if (interval) {
|
|
892
888
|
this.deleteExistingInterval({ interval, local, op });
|
|
893
889
|
}
|