@fluidframework/sequence 2.0.0-dev.4.1.0.148229 → 2.0.0-dev.4.3.0.157531

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.
@@ -15,7 +15,7 @@ var __rest = (this && this.__rest) || function (s, e) {
15
15
  return t;
16
16
  };
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
- exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.IntervalCollectionIterator = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.compareSequenceIntervalEnds = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.defaultIntervalConflictResolver = exports.createSequenceInterval = exports.SequenceInterval = exports.Interval = exports.IntervalType = void 0;
18
+ exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.IntervalCollectionIterator = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.compareSequenceIntervalEnds = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.createSequenceInterval = exports.SequenceInterval = exports.Interval = exports.IntervalType = void 0;
19
19
  /* eslint-disable no-bitwise */
20
20
  const common_utils_1 = require("@fluidframework/common-utils");
21
21
  const container_utils_1 = require("@fluidframework/container-utils");
@@ -87,9 +87,7 @@ class Interval {
87
87
  getIntervalId() {
88
88
  var _a;
89
89
  const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
90
- if (id === undefined) {
91
- return undefined;
92
- }
90
+ (0, common_utils_1.assert)(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
93
91
  return `${id}`;
94
92
  }
95
93
  /**
@@ -232,6 +230,22 @@ exports.Interval = Interval;
232
230
  * Interval impelmentation whose ends are associated with positions in a mutatable sequence.
233
231
  * As such, when content is inserted into the middle of the interval, the interval expands to
234
232
  * include that content.
233
+ *
234
+ * @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
235
+ * an interval referring to "hello" in "hello world" should have a start position of 0 and an end
236
+ * position of 5.
237
+ *
238
+ * To see why, consider what happens if "llo wor" is removed from the string to make "held".
239
+ * The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
240
+ * slides forward to the next unremoved position, which is the "l" in "held".
241
+ * Users would generally expect the interval to now refer to "he" (as it is the subset of content
242
+ * remaining after the removal), hence the "l" should be excluded.
243
+ * If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
244
+ * is undesirable.
245
+ *
246
+ * Since the end of an interval is treated exclusively but cannot be greater than or equal to the
247
+ * length of the associated sequence, application models which leverage interval collections should
248
+ * consider inserting a marker at the end of the sequence to represent the end of the content.
235
249
  */
236
250
  class SequenceInterval {
237
251
  constructor(client,
@@ -360,9 +374,7 @@ class SequenceInterval {
360
374
  getIntervalId() {
361
375
  var _a;
362
376
  const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
363
- if (id === undefined) {
364
- return undefined;
365
- }
377
+ (0, common_utils_1.assert)(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
366
378
  return `${id}`;
367
379
  }
368
380
  /**
@@ -382,7 +394,6 @@ class SequenceInterval {
382
394
  }
383
395
  /**
384
396
  * @returns whether this interval overlaps two numerical positions.
385
- * @remarks - this is currently strict overlap, which doesn't align with the endpoint treatment of`.overlaps()`
386
397
  */
387
398
  overlapsPos(bstart, bend) {
388
399
  const startPos = this.client.localReferencePositionToPosition(this.start);
@@ -433,7 +444,7 @@ class SequenceInterval {
433
444
  }
434
445
  }
435
446
  exports.SequenceInterval = SequenceInterval;
436
- function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq) {
447
+ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot) {
437
448
  if (segoff.segment) {
438
449
  const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
439
450
  return ref;
@@ -443,7 +454,10 @@ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq
443
454
  // - References coming from a remote client (location may have been concurrently removed)
444
455
  // - References being rebased to a new sequence number
445
456
  // (segment they originally referred to may have been removed with no suitable replacement)
446
- if (!op && !localSeq && !(0, merge_tree_1.refTypeIncludesFlag)(refType, merge_tree_1.ReferenceType.Transient)) {
457
+ if (!op &&
458
+ !localSeq &&
459
+ !fromSnapshot &&
460
+ !(0, merge_tree_1.refTypeIncludesFlag)(refType, merge_tree_1.ReferenceType.Transient)) {
447
461
  throw new container_utils_1.UsageError("Non-transient references need segment");
448
462
  }
449
463
  return (0, merge_tree_1.createDetachedLocalReferencePosition)(refType);
@@ -462,7 +476,7 @@ function createPositionReference(client, pos, refType, op, fromSnapshot, localSe
462
476
  (0, common_utils_1.assert)((refType & merge_tree_1.ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
463
477
  segoff = client.getContainingSegment(pos, undefined, localSeq);
464
478
  }
465
- return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq);
479
+ return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot);
466
480
  }
467
481
  function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot) {
468
482
  let beginRefType = merge_tree_1.ReferenceType.RangeBegin;
@@ -499,84 +513,24 @@ function createSequenceInterval(label, start, end, client, intervalType, op, fro
499
513
  return ival;
500
514
  }
501
515
  exports.createSequenceInterval = createSequenceInterval;
502
- function defaultIntervalConflictResolver(a, b) {
503
- a.addPropertySet(b.properties);
504
- return a;
505
- }
506
- exports.defaultIntervalConflictResolver = defaultIntervalConflictResolver;
507
- function createIntervalIndex(conflict) {
516
+ function createIntervalIndex() {
508
517
  const helpers = {
509
518
  compareEnds: compareIntervalEnds,
510
519
  create: createInterval,
511
520
  };
512
521
  const lc = new LocalIntervalCollection(undefined, "", helpers);
513
- if (conflict) {
514
- lc.addConflictResolver(conflict);
515
- }
516
- else {
517
- lc.addConflictResolver(defaultIntervalConflictResolver);
518
- }
519
522
  return lc;
520
523
  }
521
524
  exports.createIntervalIndex = createIntervalIndex;
522
- class LocalIntervalCollection {
523
- constructor(client, label, helpers,
524
- /** Callback invoked each time one of the endpoints of an interval slides. */
525
- onPositionChange) {
525
+ class OverlappingIntervalsIndex {
526
+ constructor(client, helpers) {
526
527
  this.client = client;
527
- this.label = label;
528
528
  this.helpers = helpers;
529
- this.onPositionChange = onPositionChange;
530
529
  this.intervalTree = new intervalTree_1.IntervalTree();
531
- this.intervalIdMap = new Map();
532
- // eslint-disable-next-line @typescript-eslint/unbound-method
533
- this.endIntervalTree = new merge_tree_1.RedBlackTree(helpers.compareEnds);
534
- }
535
- addConflictResolver(conflictResolver) {
536
- this.conflictResolver = conflictResolver;
537
- this.endConflictResolver = (key, currentKey) => {
538
- const ival = conflictResolver(key, currentKey);
539
- return {
540
- data: ival,
541
- key: ival,
542
- };
543
- };
544
530
  }
545
531
  map(fn) {
546
532
  this.intervalTree.map(fn);
547
533
  }
548
- createLegacyId(start, end) {
549
- // Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
550
- // without ID's.
551
- return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
552
- }
553
- /**
554
- * Validates that a serialized interval has the ID property. Creates an ID
555
- * if one does not already exist
556
- *
557
- * @param serializedInterval - The interval to be checked
558
- * @returns The interval's existing or newly created id
559
- */
560
- ensureSerializedId(serializedInterval) {
561
- var _a;
562
- let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
563
- if (id === undefined) {
564
- // An interval came over the wire without an ID, so create a non-unique one based on start/end.
565
- // This will allow all clients to refer to this interval consistently.
566
- id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
567
- const newProps = {
568
- [reservedIntervalIdKey]: id,
569
- };
570
- serializedInterval.properties = (0, merge_tree_1.addProperties)(serializedInterval.properties, newProps);
571
- }
572
- // Make the ID immutable for safety's sake.
573
- Object.defineProperty(serializedInterval.properties, reservedIntervalIdKey, {
574
- configurable: false,
575
- enumerable: true,
576
- writable: false,
577
- });
578
- return id;
579
- }
580
534
  mapUntil(fn) {
581
535
  this.intervalTree.mapUntil(fn);
582
536
  }
@@ -643,7 +597,7 @@ class LocalIntervalCollection {
643
597
  }
644
598
  /**
645
599
  * @returns an array of all intervals contained in this collection that overlap the range
646
- * `[startPosition, endPosition]`.
600
+ * `[startPosition, endPosition)`.
647
601
  */
648
602
  findOverlappingIntervals(startPosition, endPosition) {
649
603
  if (endPosition < startPosition || this.intervalTree.intervals.isEmpty()) {
@@ -653,6 +607,47 @@ class LocalIntervalCollection {
653
607
  const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
654
608
  return overlappingIntervalNodes.map((node) => node.key);
655
609
  }
610
+ remove(interval) {
611
+ this.intervalTree.removeExisting(interval);
612
+ }
613
+ add(interval) {
614
+ this.intervalTree.put(interval);
615
+ }
616
+ }
617
+ class IdIntervalIndex {
618
+ constructor() {
619
+ this.intervalIdMap = new Map();
620
+ }
621
+ add(interval) {
622
+ const id = interval.getIntervalId();
623
+ (0, common_utils_1.assert)(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
624
+ // Make the ID immutable.
625
+ Object.defineProperty(interval.properties, reservedIntervalIdKey, {
626
+ configurable: false,
627
+ enumerable: true,
628
+ writable: false,
629
+ });
630
+ this.intervalIdMap.set(id, interval);
631
+ }
632
+ remove(interval) {
633
+ const id = interval.getIntervalId();
634
+ (0, common_utils_1.assert)(id !== undefined, 0x311 /* expected id to exist on interval */);
635
+ this.intervalIdMap.delete(id);
636
+ }
637
+ getIntervalById(id) {
638
+ return this.intervalIdMap.get(id);
639
+ }
640
+ [Symbol.iterator]() {
641
+ return this.intervalIdMap.values();
642
+ }
643
+ }
644
+ class EndpointIndex {
645
+ constructor(client, helpers) {
646
+ this.client = client;
647
+ this.helpers = helpers;
648
+ // eslint-disable-next-line @typescript-eslint/unbound-method
649
+ this.endIntervalTree = new merge_tree_1.RedBlackTree(helpers.compareEnds);
650
+ }
656
651
  previousInterval(pos) {
657
652
  const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
658
653
  const rbNode = this.endIntervalTree.floor(transientInterval);
@@ -667,21 +662,70 @@ class LocalIntervalCollection {
667
662
  return rbNode.data;
668
663
  }
669
664
  }
670
- removeInterval(startPosition, endPosition) {
671
- const transientInterval = this.helpers.create("transient", startPosition, endPosition, this.client, IntervalType.Transient);
672
- this.intervalTree.remove(transientInterval);
673
- this.endIntervalTree.remove(transientInterval);
674
- return transientInterval;
665
+ add(interval) {
666
+ this.endIntervalTree.put(interval, interval);
675
667
  }
676
- removeIntervalFromIndex(interval) {
677
- this.intervalTree.removeExisting(interval);
668
+ remove(interval) {
678
669
  this.endIntervalTree.remove(interval);
679
- const id = interval.getIntervalId();
680
- (0, common_utils_1.assert)(id !== undefined, 0x311 /* expected id to exist on interval */);
681
- this.intervalIdMap.delete(id);
670
+ }
671
+ }
672
+ class LocalIntervalCollection {
673
+ constructor(client, label, helpers,
674
+ /** Callback invoked each time one of the endpoints of an interval slides. */
675
+ onPositionChange) {
676
+ this.client = client;
677
+ this.label = label;
678
+ this.helpers = helpers;
679
+ this.onPositionChange = onPositionChange;
680
+ this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
681
+ this.idIntervalIndex = new IdIntervalIndex();
682
+ this.endIntervalIndex = new EndpointIndex(client, helpers);
683
+ this.indexes = [
684
+ this.overlappingIntervalsIndex,
685
+ this.idIntervalIndex,
686
+ this.endIntervalIndex,
687
+ ];
688
+ }
689
+ createLegacyId(start, end) {
690
+ // Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
691
+ // without ID's.
692
+ return `${LocalIntervalCollection.legacyIdPrefix}${start}-${end}`;
693
+ }
694
+ /**
695
+ * Validates that a serialized interval has the ID property. Creates an ID
696
+ * if one does not already exist
697
+ *
698
+ * @param serializedInterval - The interval to be checked
699
+ * @returns The interval's existing or newly created id
700
+ */
701
+ ensureSerializedId(serializedInterval) {
702
+ var _a;
703
+ let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
704
+ if (id === undefined) {
705
+ // Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
706
+ // comes over the wire, create a non-unique one based on start/end.
707
+ // This will allow all clients to refer to this interval consistently.
708
+ id = this.createLegacyId(serializedInterval.start, serializedInterval.end);
709
+ const newProps = {
710
+ [reservedIntervalIdKey]: id,
711
+ };
712
+ serializedInterval.properties = (0, merge_tree_1.addProperties)(serializedInterval.properties, newProps);
713
+ }
714
+ // Make the ID immutable for safety's sake.
715
+ Object.defineProperty(serializedInterval.properties, reservedIntervalIdKey, {
716
+ configurable: false,
717
+ enumerable: true,
718
+ writable: false,
719
+ });
720
+ return id;
721
+ }
722
+ removeIntervalFromIndexes(interval) {
723
+ for (const index of this.indexes) {
724
+ index.remove(interval);
725
+ }
682
726
  }
683
727
  removeExistingInterval(interval) {
684
- this.removeIntervalFromIndex(interval);
728
+ this.removeIntervalFromIndexes(interval);
685
729
  this.removeIntervalListeners(interval);
686
730
  }
687
731
  createInterval(start, end, intervalType, op) {
@@ -709,27 +753,16 @@ class LocalIntervalCollection {
709
753
  interval.end.addProperties({ interval });
710
754
  }
711
755
  }
712
- addIntervalToIndex(interval) {
713
- const id = interval.getIntervalId();
714
- (0, common_utils_1.assert)(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
715
- // Make the ID immutable.
716
- Object.defineProperty(interval.properties, reservedIntervalIdKey, {
717
- configurable: false,
718
- enumerable: true,
719
- writable: false,
720
- });
721
- this.intervalTree.put(interval, this.conflictResolver);
722
- this.endIntervalTree.put(interval, interval, this.endConflictResolver);
723
- this.intervalIdMap.set(id, interval);
756
+ addIntervalToIndexes(interval) {
757
+ for (const index of this.indexes) {
758
+ index.add(interval);
759
+ }
724
760
  }
725
761
  add(interval) {
726
762
  this.linkEndpointsToInterval(interval);
727
- this.addIntervalToIndex(interval);
763
+ this.addIntervalToIndexes(interval);
728
764
  this.addIntervalListeners(interval);
729
765
  }
730
- getIntervalById(id) {
731
- return this.intervalIdMap.get(id);
732
- }
733
766
  changeInterval(interval, start, end, op, localSeq) {
734
767
  const newInterval = interval.modify(this.label, start, end, op, localSeq);
735
768
  if (newInterval) {
@@ -739,10 +772,9 @@ class LocalIntervalCollection {
739
772
  return newInterval;
740
773
  }
741
774
  serialize() {
742
- const intervals = this.intervalTree.intervals.keys();
743
775
  return {
744
776
  label: this.label,
745
- intervals: intervals.map((interval) => compressInterval(interval.serialize())),
777
+ intervals: Array.from(this.idIntervalIndex, (interval) => compressInterval(interval.serialize())),
746
778
  version: 2,
747
779
  };
748
780
  }
@@ -767,14 +799,14 @@ class LocalIntervalCollection {
767
799
  previousInterval = interval.clone();
768
800
  previousInterval.start = cloneRef(previousInterval.start);
769
801
  previousInterval.end = cloneRef(previousInterval.end);
770
- this.removeIntervalFromIndex(interval);
802
+ this.removeIntervalFromIndexes(interval);
771
803
  }
772
804
  }, () => {
773
805
  var _a;
774
806
  (0, common_utils_1.assert)(previousInterval !== undefined, 0x3fa /* Invalid interleaving of before/after slide */);
775
807
  pendingChanges--;
776
808
  if (pendingChanges === 0) {
777
- this.addIntervalToIndex(interval);
809
+ this.addIntervalToIndexes(interval);
778
810
  (_a = this.onPositionChange) === null || _a === void 0 ? void 0 : _a.call(this, interval, previousInterval);
779
811
  previousInterval = undefined;
780
812
  }
@@ -1055,15 +1087,17 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1055
1087
  if (!this.localCollection) {
1056
1088
  throw new telemetry_utils_1.LoggingError("attach must be called before accessing intervals");
1057
1089
  }
1058
- return this.localCollection.getIntervalById(id);
1090
+ return this.localCollection.idIntervalIndex.getIntervalById(id);
1059
1091
  }
1060
1092
  /**
1061
1093
  * Creates a new interval and add it to the collection.
1062
- * @param start - interval start position
1063
- * @param end - interval end position
1094
+ * @param start - interval start position (inclusive)
1095
+ * @param end - interval end position (exclusive)
1064
1096
  * @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
1065
1097
  * @param props - properties of the interval
1066
1098
  * @returns - the created interval
1099
+ * @remarks - See documentation on {@link SequenceInterval} for comments on interval endpoint semantics: there are subtleties
1100
+ * with how the current half-open behavior is represented.
1067
1101
  */
1068
1102
  add(start, end, intervalType, props) {
1069
1103
  var _a, _b;
@@ -1120,7 +1154,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1120
1154
  if (!this.localCollection) {
1121
1155
  throw new telemetry_utils_1.LoggingError("Attach must be called before accessing intervals");
1122
1156
  }
1123
- const interval = this.localCollection.getIntervalById(id);
1157
+ const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
1124
1158
  if (interval) {
1125
1159
  this.deleteExistingInterval(interval, true, undefined);
1126
1160
  }
@@ -1307,14 +1341,19 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1307
1341
  }
1308
1342
  }
1309
1343
  }
1310
- addConflictResolver(conflictResolver) {
1344
+ /**
1345
+ * @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
1346
+ * in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
1347
+ * at the same location and gives each interval a unique id.
1348
+ *
1349
+ * As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
1350
+ */
1351
+ addConflictResolver(_) {
1311
1352
  if (!this.localCollection) {
1312
1353
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
1313
1354
  }
1314
- this.localCollection.addConflictResolver(conflictResolver);
1315
1355
  }
1316
1356
  attachDeserializer(onDeserialize) {
1317
- var _a;
1318
1357
  // If no deserializer is specified can skip all processing work
1319
1358
  if (!onDeserialize) {
1320
1359
  return;
@@ -1322,9 +1361,9 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1322
1361
  // Start by storing the callbacks so that any subsequent modifications make use of them
1323
1362
  this.onDeserialize = onDeserialize;
1324
1363
  // Trigger the async prepare work across all values in the collection
1325
- (_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.map((interval) => {
1326
- onDeserialize(interval);
1327
- });
1364
+ if (this.attached) {
1365
+ this.map(onDeserialize);
1366
+ }
1328
1367
  }
1329
1368
  /**
1330
1369
  * Returns new interval after rebasing. If undefined, the interval was
@@ -1345,7 +1384,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1345
1384
  const { intervalType, properties } = serializedInterval;
1346
1385
  const { start: startRebased, end: endRebased } = (_a = this.localSeqToRebasedInterval.get(localSeq)) !== null && _a !== void 0 ? _a : this.computeRebasedPositions(localSeq);
1347
1386
  const intervalId = properties === null || properties === void 0 ? void 0 : properties[reservedIntervalIdKey];
1348
- const localInterval = (_b = this.localCollection) === null || _b === void 0 ? void 0 : _b.getIntervalById(intervalId);
1387
+ const localInterval = (_b = this.localCollection) === null || _b === void 0 ? void 0 : _b.idIntervalIndex.getIntervalById(intervalId);
1349
1388
  const rebased = {
1350
1389
  start: startRebased,
1351
1390
  end: endRebased,
@@ -1498,7 +1537,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1498
1537
  throw new telemetry_utils_1.LoggingError("attach must be called prior to deleting intervals");
1499
1538
  }
1500
1539
  const id = this.localCollection.ensureSerializedId(serializedInterval);
1501
- const interval = this.localCollection.getIntervalById(id);
1540
+ const interval = this.localCollection.idIntervalIndex.getIntervalById(id);
1502
1541
  if (interval) {
1503
1542
  this.deleteExistingInterval(interval, local, op);
1504
1543
  }
@@ -1559,7 +1598,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1559
1598
  if (!this.localCollection) {
1560
1599
  return;
1561
1600
  }
1562
- this.localCollection.gatherIterationResults(results, iteratesForward, start, end);
1601
+ this.localCollection.overlappingIntervalsIndex.gatherIterationResults(results, iteratesForward, start, end);
1563
1602
  }
1564
1603
  /**
1565
1604
  * @returns an array of all intervals in this collection that overlap with the interval
@@ -1569,7 +1608,7 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1569
1608
  if (!this.localCollection) {
1570
1609
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
1571
1610
  }
1572
- return this.localCollection.findOverlappingIntervals(startPosition, endPosition);
1611
+ return this.localCollection.overlappingIntervalsIndex.findOverlappingIntervals(startPosition, endPosition);
1573
1612
  }
1574
1613
  /**
1575
1614
  * Applies a function to each interval in this collection.
@@ -1578,19 +1617,21 @@ class IntervalCollection extends common_utils_1.TypedEventEmitter {
1578
1617
  if (!this.localCollection) {
1579
1618
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
1580
1619
  }
1581
- this.localCollection.map(fn);
1620
+ for (const interval of this.localCollection.idIntervalIndex) {
1621
+ fn(interval);
1622
+ }
1582
1623
  }
1583
1624
  previousInterval(pos) {
1584
1625
  if (!this.localCollection) {
1585
1626
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
1586
1627
  }
1587
- return this.localCollection.previousInterval(pos);
1628
+ return this.localCollection.endIntervalIndex.previousInterval(pos);
1588
1629
  }
1589
1630
  nextInterval(pos) {
1590
1631
  if (!this.localCollection) {
1591
1632
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
1592
1633
  }
1593
- return this.localCollection.nextInterval(pos);
1634
+ return this.localCollection.endIntervalIndex.nextInterval(pos);
1594
1635
  }
1595
1636
  }
1596
1637
  exports.IntervalCollection = IntervalCollection;