@fluidframework/sequence 2.0.0-dev.4.4.0.162574 → 2.0.0-dev.5.2.0.169897
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 +20 -0
- package/dist/defaultMap.d.ts +3 -2
- package/dist/defaultMap.d.ts.map +1 -1
- package/dist/defaultMap.js +4 -3
- package/dist/defaultMap.js.map +1 -1
- package/dist/defaultMapInterfaces.d.ts +12 -1
- package/dist/defaultMapInterfaces.d.ts.map +1 -1
- package/dist/defaultMapInterfaces.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/intervalCollection.d.ts +231 -59
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +288 -86
- package/dist/intervalCollection.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/dist/revertibles.d.ts +104 -0
- package/dist/revertibles.d.ts.map +1 -0
- package/dist/revertibles.js +374 -0
- package/dist/revertibles.js.map +1 -0
- package/dist/sequence.d.ts +4 -4
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +3 -3
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +3 -3
- package/dist/sharedIntervalCollection.d.ts.map +1 -1
- package/dist/sharedIntervalCollection.js +1 -1
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/tsdoc-metadata.json +11 -0
- package/lib/defaultMap.d.ts +3 -2
- package/lib/defaultMap.d.ts.map +1 -1
- package/lib/defaultMap.js +4 -3
- package/lib/defaultMap.js.map +1 -1
- package/lib/defaultMapInterfaces.d.ts +12 -1
- package/lib/defaultMapInterfaces.d.ts.map +1 -1
- package/lib/defaultMapInterfaces.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/intervalCollection.d.ts +231 -59
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +286 -86
- package/lib/intervalCollection.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/lib/revertibles.d.ts +104 -0
- package/lib/revertibles.d.ts.map +1 -0
- package/lib/revertibles.js +364 -0
- package/lib/revertibles.js.map +1 -0
- package/lib/sequence.d.ts +4 -4
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +3 -3
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +3 -3
- package/lib/sharedIntervalCollection.d.ts.map +1 -1
- package/lib/sharedIntervalCollection.js +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/package.json +20 -22
- package/src/defaultMap.ts +4 -1
- package/src/defaultMapInterfaces.ts +13 -1
- package/src/index.ts +21 -5
- package/src/intervalCollection.ts +619 -73
- package/src/packageVersion.ts +1 -1
- package/src/revertibles.ts +572 -0
- package/src/sequence.ts +12 -2
- package/src/sharedIntervalCollection.ts +4 -2
|
@@ -16,11 +16,22 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
16
16
|
/* eslint-disable no-bitwise */
|
|
17
17
|
import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
|
|
18
18
|
import { UsageError } from "@fluidframework/container-utils";
|
|
19
|
-
import { addProperties, compareReferencePositions, createMap, MergeTreeDeltaType, minReferencePosition, PropertiesManager, RedBlackTree, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, maxReferencePosition, createDetachedLocalReferencePosition, DetachedReferencePosition, } from "@fluidframework/merge-tree";
|
|
19
|
+
import { addProperties, compareReferencePositions, createMap, MergeTreeDeltaType, minReferencePosition, PropertiesManager, RedBlackTree, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, maxReferencePosition, createDetachedLocalReferencePosition, DetachedReferencePosition, SlidingPreference, } from "@fluidframework/merge-tree";
|
|
20
20
|
import { LoggingError } from "@fluidframework/telemetry-utils";
|
|
21
21
|
import { v4 as uuid } from "uuid";
|
|
22
22
|
import { IntervalTree } from "./intervalTree";
|
|
23
23
|
const reservedIntervalIdKey = "intervalId";
|
|
24
|
+
/**
|
|
25
|
+
* Values are used in persisted formats (ops) and revertibles.
|
|
26
|
+
* @alpha
|
|
27
|
+
*/
|
|
28
|
+
export const IntervalOpType = {
|
|
29
|
+
ADD: "add",
|
|
30
|
+
DELETE: "delete",
|
|
31
|
+
CHANGE: "change",
|
|
32
|
+
PROPERTY_CHANGED: "propertyChanged",
|
|
33
|
+
POSITION_REMOVE: "positionRemove",
|
|
34
|
+
};
|
|
24
35
|
export var IntervalType;
|
|
25
36
|
(function (IntervalType) {
|
|
26
37
|
IntervalType[IntervalType["Simple"] = 0] = "Simple";
|
|
@@ -28,7 +39,7 @@ export var IntervalType;
|
|
|
28
39
|
/**
|
|
29
40
|
* SlideOnRemove indicates that the ends of the interval will slide if the segment
|
|
30
41
|
* they reference is removed and acked.
|
|
31
|
-
* See `packages\dds\merge-tree\REFERENCEPOSITIONS.md` for details
|
|
42
|
+
* See `packages\dds\merge-tree\docs\REFERENCEPOSITIONS.md` for details
|
|
32
43
|
* SlideOnRemove is the default interval behavior and does not need to be specified.
|
|
33
44
|
*/
|
|
34
45
|
IntervalType[IntervalType["SlideOnRemove"] = 2] = "SlideOnRemove";
|
|
@@ -49,6 +60,7 @@ function decompressInterval(interval, label) {
|
|
|
49
60
|
sequenceNumber: interval[2],
|
|
50
61
|
intervalType: interval[3],
|
|
51
62
|
properties: Object.assign(Object.assign({}, interval[4]), { [reservedRangeLabelsKey]: [label] }),
|
|
63
|
+
stickiness: interval[5],
|
|
52
64
|
};
|
|
53
65
|
}
|
|
54
66
|
/**
|
|
@@ -57,14 +69,57 @@ function decompressInterval(interval, label) {
|
|
|
57
69
|
*/
|
|
58
70
|
function compressInterval(interval) {
|
|
59
71
|
const { start, end, sequenceNumber, intervalType, properties } = interval;
|
|
60
|
-
|
|
72
|
+
const base = [
|
|
61
73
|
start,
|
|
62
74
|
end,
|
|
63
75
|
sequenceNumber,
|
|
64
76
|
intervalType,
|
|
65
77
|
Object.assign(Object.assign({}, properties), { [reservedRangeLabelsKey]: undefined }),
|
|
66
78
|
];
|
|
79
|
+
if (interval.stickiness !== undefined && interval.stickiness !== IntervalStickiness.END) {
|
|
80
|
+
base.push(interval.stickiness);
|
|
81
|
+
}
|
|
82
|
+
return base;
|
|
83
|
+
}
|
|
84
|
+
function startReferenceSlidingPreference(stickiness) {
|
|
85
|
+
// if any start stickiness, prefer sliding backwards
|
|
86
|
+
return (stickiness & IntervalStickiness.START) !== 0
|
|
87
|
+
? SlidingPreference.BACKWARD
|
|
88
|
+
: SlidingPreference.FORWARD;
|
|
89
|
+
}
|
|
90
|
+
function endReferenceSlidingPreference(stickiness) {
|
|
91
|
+
// if any end stickiness, prefer sliding forwards
|
|
92
|
+
return (stickiness & IntervalStickiness.END) !== 0
|
|
93
|
+
? SlidingPreference.FORWARD
|
|
94
|
+
: SlidingPreference.BACKWARD;
|
|
67
95
|
}
|
|
96
|
+
/**
|
|
97
|
+
* Determines how an interval should expand when segments are inserted adjacent
|
|
98
|
+
* to the range it spans
|
|
99
|
+
*
|
|
100
|
+
* Note that interval stickiness is currently an experimental feature and must
|
|
101
|
+
* be explicitly enabled with the `intervalStickinessEnabled` flag
|
|
102
|
+
*/
|
|
103
|
+
export const IntervalStickiness = {
|
|
104
|
+
/**
|
|
105
|
+
* Interval does not expand to include adjacent segments
|
|
106
|
+
*/
|
|
107
|
+
NONE: 0b00,
|
|
108
|
+
/**
|
|
109
|
+
* Interval expands to include segments inserted adjacent to the start
|
|
110
|
+
*/
|
|
111
|
+
START: 0b01,
|
|
112
|
+
/**
|
|
113
|
+
* Interval expands to include segments inserted adjacent to the end
|
|
114
|
+
*
|
|
115
|
+
* This is the default stickiness
|
|
116
|
+
*/
|
|
117
|
+
END: 0b10,
|
|
118
|
+
/**
|
|
119
|
+
* Interval expands to include all segments inserted adjacent to it
|
|
120
|
+
*/
|
|
121
|
+
FULL: 0b11,
|
|
122
|
+
};
|
|
68
123
|
/**
|
|
69
124
|
* Serializable interval whose endpoints are plain-old numbers.
|
|
70
125
|
*/
|
|
@@ -98,7 +153,7 @@ export class Interval {
|
|
|
98
153
|
* Adds an auxiliary set of properties to this interval.
|
|
99
154
|
* These properties can be recovered using `getAdditionalPropertySets`
|
|
100
155
|
* @param props - set of properties to add
|
|
101
|
-
* @remarks - This gets called as part of the default conflict resolver for `
|
|
156
|
+
* @remarks - This gets called as part of the default conflict resolver for `IIntervalCollection<Interval>`
|
|
102
157
|
* (i.e. non-sequence-based interval collections). However, the additional properties don't get serialized.
|
|
103
158
|
* This functionality seems half-baked.
|
|
104
159
|
*/
|
|
@@ -223,7 +278,7 @@ export class Interval {
|
|
|
223
278
|
}
|
|
224
279
|
}
|
|
225
280
|
/**
|
|
226
|
-
* Interval
|
|
281
|
+
* Interval implementation whose ends are associated with positions in a mutatable sequence.
|
|
227
282
|
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
228
283
|
* include that content.
|
|
229
284
|
*
|
|
@@ -254,11 +309,12 @@ export class SequenceInterval {
|
|
|
254
309
|
* End endpoint of this interval.
|
|
255
310
|
* @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
|
|
256
311
|
*/
|
|
257
|
-
end, intervalType, props) {
|
|
312
|
+
end, intervalType, props, stickiness = IntervalStickiness.END) {
|
|
258
313
|
this.client = client;
|
|
259
314
|
this.start = start;
|
|
260
315
|
this.end = end;
|
|
261
316
|
this.intervalType = intervalType;
|
|
317
|
+
this.stickiness = stickiness;
|
|
262
318
|
this.propertyManager = new PropertiesManager();
|
|
263
319
|
this.properties = {};
|
|
264
320
|
if (props) {
|
|
@@ -310,13 +366,16 @@ export class SequenceInterval {
|
|
|
310
366
|
if (this.properties) {
|
|
311
367
|
serializedInterval.properties = this.properties;
|
|
312
368
|
}
|
|
369
|
+
if (this.stickiness !== IntervalStickiness.END) {
|
|
370
|
+
serializedInterval.stickiness = this.stickiness;
|
|
371
|
+
}
|
|
313
372
|
return serializedInterval;
|
|
314
373
|
}
|
|
315
374
|
/**
|
|
316
375
|
* {@inheritDoc IInterval.clone}
|
|
317
376
|
*/
|
|
318
377
|
clone() {
|
|
319
|
-
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties);
|
|
378
|
+
return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
|
|
320
379
|
}
|
|
321
380
|
/**
|
|
322
381
|
* {@inheritDoc IInterval.compare}
|
|
@@ -400,7 +459,7 @@ export class SequenceInterval {
|
|
|
400
459
|
* {@inheritDoc IInterval.modify}
|
|
401
460
|
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
402
461
|
*/
|
|
403
|
-
modify(label, start, end, op, localSeq) {
|
|
462
|
+
modify(label, start, end, op, localSeq, stickiness = IntervalStickiness.END) {
|
|
404
463
|
const getRefType = (baseType) => {
|
|
405
464
|
let refType = baseType;
|
|
406
465
|
if (op === undefined) {
|
|
@@ -411,14 +470,14 @@ export class SequenceInterval {
|
|
|
411
470
|
};
|
|
412
471
|
let startRef = this.start;
|
|
413
472
|
if (start !== undefined) {
|
|
414
|
-
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq);
|
|
473
|
+
startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
|
|
415
474
|
if (this.start.properties) {
|
|
416
475
|
startRef.addProperties(this.start.properties);
|
|
417
476
|
}
|
|
418
477
|
}
|
|
419
478
|
let endRef = this.end;
|
|
420
479
|
if (end !== undefined) {
|
|
421
|
-
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq);
|
|
480
|
+
endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
|
|
422
481
|
if (this.end.properties) {
|
|
423
482
|
endRef.addProperties(this.end.properties);
|
|
424
483
|
}
|
|
@@ -439,9 +498,9 @@ export class SequenceInterval {
|
|
|
439
498
|
}
|
|
440
499
|
}
|
|
441
500
|
}
|
|
442
|
-
function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot) {
|
|
501
|
+
function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
|
|
443
502
|
if (segoff.segment) {
|
|
444
|
-
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
|
|
503
|
+
const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
|
|
445
504
|
return ref;
|
|
446
505
|
}
|
|
447
506
|
// Creating references on detached segments is allowed for:
|
|
@@ -457,7 +516,7 @@ function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq
|
|
|
457
516
|
}
|
|
458
517
|
return createDetachedLocalReferencePosition(refType);
|
|
459
518
|
}
|
|
460
|
-
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq) {
|
|
519
|
+
function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
|
|
461
520
|
let segoff;
|
|
462
521
|
if (op) {
|
|
463
522
|
assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
|
|
@@ -471,9 +530,9 @@ function createPositionReference(client, pos, refType, op, fromSnapshot, localSe
|
|
|
471
530
|
assert((refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
|
|
472
531
|
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
473
532
|
}
|
|
474
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot);
|
|
533
|
+
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
|
|
475
534
|
}
|
|
476
|
-
export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
535
|
+
export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = IntervalStickiness.END) {
|
|
477
536
|
let beginRefType = ReferenceType.RangeBegin;
|
|
478
537
|
let endRefType = ReferenceType.RangeEnd;
|
|
479
538
|
if (intervalType === IntervalType.Transient) {
|
|
@@ -497,14 +556,14 @@ export function createSequenceInterval(label, start, end, client, intervalType,
|
|
|
497
556
|
endRefType |= ReferenceType.StayOnRemove;
|
|
498
557
|
}
|
|
499
558
|
}
|
|
500
|
-
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot);
|
|
501
|
-
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot);
|
|
559
|
+
const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
|
|
560
|
+
const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
|
|
502
561
|
const rangeProp = {
|
|
503
562
|
[reservedRangeLabelsKey]: [label],
|
|
504
563
|
};
|
|
505
564
|
startLref.addProperties(rangeProp);
|
|
506
565
|
endLref.addProperties(rangeProp);
|
|
507
|
-
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp);
|
|
566
|
+
const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
|
|
508
567
|
return ival;
|
|
509
568
|
}
|
|
510
569
|
export function createIntervalIndex() {
|
|
@@ -662,6 +721,117 @@ class EndpointIndex {
|
|
|
662
721
|
this.endIntervalTree.remove(interval);
|
|
663
722
|
}
|
|
664
723
|
}
|
|
724
|
+
/**
|
|
725
|
+
* Interface for intervals that have comparison override properties.
|
|
726
|
+
*/
|
|
727
|
+
const forceCompare = Symbol();
|
|
728
|
+
/**
|
|
729
|
+
* Compares two objects based on their comparison override properties.
|
|
730
|
+
* @returns A number indicating the order of the intervals (negative for a is lower than b, 0 for tie, positive for a is greater than b).
|
|
731
|
+
*/
|
|
732
|
+
function compareOverrideables(a, b) {
|
|
733
|
+
var _a, _b;
|
|
734
|
+
const forceCompareA = (_a = a[forceCompare]) !== null && _a !== void 0 ? _a : 0;
|
|
735
|
+
const forceCompareB = (_b = b[forceCompare]) !== null && _b !== void 0 ? _b : 0;
|
|
736
|
+
return forceCompareA - forceCompareB;
|
|
737
|
+
}
|
|
738
|
+
class EndpointInRangeIndex {
|
|
739
|
+
constructor(helpers, client) {
|
|
740
|
+
this.helpers = helpers;
|
|
741
|
+
this.client = client;
|
|
742
|
+
this.intervalTree = new RedBlackTree((a, b) => {
|
|
743
|
+
const compareEndsResult = helpers.compareEnds(a, b);
|
|
744
|
+
if (compareEndsResult !== 0) {
|
|
745
|
+
return compareEndsResult;
|
|
746
|
+
}
|
|
747
|
+
const overrideablesComparison = compareOverrideables(a, b);
|
|
748
|
+
if (overrideablesComparison !== 0) {
|
|
749
|
+
return overrideablesComparison;
|
|
750
|
+
}
|
|
751
|
+
const aId = a.getIntervalId();
|
|
752
|
+
const bId = b.getIntervalId();
|
|
753
|
+
if (aId !== undefined && bId !== undefined) {
|
|
754
|
+
return aId.localeCompare(bId);
|
|
755
|
+
}
|
|
756
|
+
return 0;
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
add(interval) {
|
|
760
|
+
this.intervalTree.put(interval, interval);
|
|
761
|
+
}
|
|
762
|
+
remove(interval) {
|
|
763
|
+
this.intervalTree.remove(interval);
|
|
764
|
+
}
|
|
765
|
+
findIntervalsWithEndpointInRange(start, end) {
|
|
766
|
+
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
767
|
+
return [];
|
|
768
|
+
}
|
|
769
|
+
const results = [];
|
|
770
|
+
const action = (node) => {
|
|
771
|
+
results.push(node.data);
|
|
772
|
+
return true;
|
|
773
|
+
};
|
|
774
|
+
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
775
|
+
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
776
|
+
// Add comparison overrides to the transient intervals
|
|
777
|
+
transientStartInterval[forceCompare] = -1;
|
|
778
|
+
transientEndInterval[forceCompare] = 1;
|
|
779
|
+
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
780
|
+
return results;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
class StartpointInRangeIndex {
|
|
784
|
+
constructor(helpers, client) {
|
|
785
|
+
this.helpers = helpers;
|
|
786
|
+
this.client = client;
|
|
787
|
+
this.intervalTree = new RedBlackTree((a, b) => {
|
|
788
|
+
assert(typeof helpers.compareStarts === "function", 0x6d1 /* compareStarts does not exist in the helpers */);
|
|
789
|
+
const compareStartsResult = helpers.compareStarts(a, b);
|
|
790
|
+
if (compareStartsResult !== 0) {
|
|
791
|
+
return compareStartsResult;
|
|
792
|
+
}
|
|
793
|
+
const overrideablesComparison = compareOverrideables(a, b);
|
|
794
|
+
if (overrideablesComparison !== 0) {
|
|
795
|
+
return overrideablesComparison;
|
|
796
|
+
}
|
|
797
|
+
const aId = a.getIntervalId();
|
|
798
|
+
const bId = b.getIntervalId();
|
|
799
|
+
if (aId !== undefined && bId !== undefined) {
|
|
800
|
+
return aId.localeCompare(bId);
|
|
801
|
+
}
|
|
802
|
+
return 0;
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
add(interval) {
|
|
806
|
+
this.intervalTree.put(interval, interval);
|
|
807
|
+
}
|
|
808
|
+
remove(interval) {
|
|
809
|
+
this.intervalTree.remove(interval);
|
|
810
|
+
}
|
|
811
|
+
findIntervalsWithStartpointInRange(start, end) {
|
|
812
|
+
if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
|
|
813
|
+
return [];
|
|
814
|
+
}
|
|
815
|
+
const results = [];
|
|
816
|
+
const action = (node) => {
|
|
817
|
+
results.push(node.data);
|
|
818
|
+
return true;
|
|
819
|
+
};
|
|
820
|
+
const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
|
|
821
|
+
const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
|
|
822
|
+
// Add comparison overrides to the transient intervals
|
|
823
|
+
transientStartInterval[forceCompare] = -1;
|
|
824
|
+
transientEndInterval[forceCompare] = 1;
|
|
825
|
+
this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
|
|
826
|
+
return results;
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
export function createEndpointInRangeIndex(helpers, client) {
|
|
830
|
+
return new EndpointInRangeIndex(helpers, client);
|
|
831
|
+
}
|
|
832
|
+
export function createStartpointInRangeIndex(helpers, client) {
|
|
833
|
+
return new StartpointInRangeIndex(helpers, client);
|
|
834
|
+
}
|
|
665
835
|
export class LocalIntervalCollection {
|
|
666
836
|
constructor(client, label, helpers,
|
|
667
837
|
/** Callback invoked each time one of the endpoints of an interval slides. */
|
|
@@ -673,11 +843,11 @@ export class LocalIntervalCollection {
|
|
|
673
843
|
this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
|
|
674
844
|
this.idIntervalIndex = new IdIntervalIndex();
|
|
675
845
|
this.endIntervalIndex = new EndpointIndex(client, helpers);
|
|
676
|
-
this.indexes = [
|
|
846
|
+
this.indexes = new Set([
|
|
677
847
|
this.overlappingIntervalsIndex,
|
|
678
848
|
this.idIntervalIndex,
|
|
679
849
|
this.endIntervalIndex,
|
|
680
|
-
];
|
|
850
|
+
]);
|
|
681
851
|
}
|
|
682
852
|
createLegacyId(start, end) {
|
|
683
853
|
// Create a non-unique ID based on start and end to be used on intervals that come from legacy clients
|
|
@@ -717,17 +887,23 @@ export class LocalIntervalCollection {
|
|
|
717
887
|
index.remove(interval);
|
|
718
888
|
}
|
|
719
889
|
}
|
|
890
|
+
appendIndex(index) {
|
|
891
|
+
this.indexes.add(index);
|
|
892
|
+
}
|
|
893
|
+
removeIndex(index) {
|
|
894
|
+
return this.indexes.delete(index);
|
|
895
|
+
}
|
|
720
896
|
removeExistingInterval(interval) {
|
|
721
897
|
this.removeIntervalFromIndexes(interval);
|
|
722
898
|
this.removeIntervalListeners(interval);
|
|
723
899
|
}
|
|
724
|
-
createInterval(start, end, intervalType, op) {
|
|
725
|
-
return this.helpers.create(this.label, start, end, this.client, intervalType, op);
|
|
900
|
+
createInterval(start, end, intervalType, op, stickiness = IntervalStickiness.END) {
|
|
901
|
+
return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
|
|
726
902
|
}
|
|
727
|
-
addInterval(start, end, intervalType, props, op) {
|
|
903
|
+
addInterval(start, end, intervalType, props, op, stickiness = IntervalStickiness.END) {
|
|
728
904
|
var _a;
|
|
729
905
|
var _b;
|
|
730
|
-
const interval = this.createInterval(start, end, intervalType, op);
|
|
906
|
+
const interval = this.createInterval(start, end, intervalType, op, stickiness);
|
|
731
907
|
if (interval) {
|
|
732
908
|
if (!interval.properties) {
|
|
733
909
|
interval.properties = createMap();
|
|
@@ -780,7 +956,7 @@ export class LocalIntervalCollection {
|
|
|
780
956
|
// either, so this must be special-cased.
|
|
781
957
|
return ref;
|
|
782
958
|
}
|
|
783
|
-
return this.client.createLocalReferencePosition(segment, ref.getOffset(), ReferenceType.Transient, ref.properties);
|
|
959
|
+
return this.client.createLocalReferencePosition(segment, ref.getOffset(), ReferenceType.Transient, ref.properties, ref.slidingPreference);
|
|
784
960
|
};
|
|
785
961
|
if (interval instanceof SequenceInterval) {
|
|
786
962
|
let previousInterval;
|
|
@@ -814,13 +990,20 @@ export class LocalIntervalCollection {
|
|
|
814
990
|
}
|
|
815
991
|
LocalIntervalCollection.legacyIdPrefix = "legacy";
|
|
816
992
|
export const compareSequenceIntervalEnds = (a, b) => compareReferencePositions(a.end, b.end);
|
|
993
|
+
export const compareSequenceIntervalStarts = (a, b) => compareReferencePositions(a.start, b.start);
|
|
994
|
+
export const sequenceIntervalHelpers = {
|
|
995
|
+
compareEnds: compareSequenceIntervalEnds,
|
|
996
|
+
compareStarts: compareSequenceIntervalStarts,
|
|
997
|
+
create: createSequenceInterval,
|
|
998
|
+
};
|
|
999
|
+
export const intervalHelpers = {
|
|
1000
|
+
compareEnds: (a, b) => a.end - b.end,
|
|
1001
|
+
compareStarts: (a, b) => a.start - b.start,
|
|
1002
|
+
create: createInterval,
|
|
1003
|
+
};
|
|
817
1004
|
class SequenceIntervalCollectionFactory {
|
|
818
|
-
load(emitter, raw = []) {
|
|
819
|
-
|
|
820
|
-
compareEnds: compareSequenceIntervalEnds,
|
|
821
|
-
create: createSequenceInterval,
|
|
822
|
-
};
|
|
823
|
-
return new IntervalCollection(helpers, true, emitter, raw);
|
|
1005
|
+
load(emitter, raw = [], options) {
|
|
1006
|
+
return new IntervalCollection(sequenceIntervalHelpers, true, emitter, raw, options);
|
|
824
1007
|
}
|
|
825
1008
|
store(value) {
|
|
826
1009
|
return value.serializeInternal();
|
|
@@ -841,7 +1024,7 @@ SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
|
|
|
841
1024
|
SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
|
|
842
1025
|
SequenceIntervalCollectionValueType._ops = makeOpsMap();
|
|
843
1026
|
const compareIntervalEnds = (a, b) => a.end - b.end;
|
|
844
|
-
function createInterval(label, start, end, client) {
|
|
1027
|
+
function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
|
|
845
1028
|
const rangeProp = {};
|
|
846
1029
|
if (label && label.length > 0) {
|
|
847
1030
|
rangeProp[reservedRangeLabelsKey] = [label];
|
|
@@ -849,12 +1032,12 @@ function createInterval(label, start, end, client) {
|
|
|
849
1032
|
return new Interval(start, end, rangeProp);
|
|
850
1033
|
}
|
|
851
1034
|
class IntervalCollectionFactory {
|
|
852
|
-
load(emitter, raw = []) {
|
|
1035
|
+
load(emitter, raw = [], options) {
|
|
853
1036
|
const helpers = {
|
|
854
1037
|
compareEnds: compareIntervalEnds,
|
|
855
1038
|
create: createInterval,
|
|
856
1039
|
};
|
|
857
|
-
const collection = new IntervalCollection(helpers, false, emitter, raw);
|
|
1040
|
+
const collection = new IntervalCollection(helpers, false, emitter, raw, options);
|
|
858
1041
|
collection.attachGraph(undefined, "");
|
|
859
1042
|
return collection;
|
|
860
1043
|
}
|
|
@@ -885,7 +1068,7 @@ export function makeOpsMap() {
|
|
|
885
1068
|
};
|
|
886
1069
|
return new Map([
|
|
887
1070
|
[
|
|
888
|
-
|
|
1071
|
+
IntervalOpType.ADD,
|
|
889
1072
|
{
|
|
890
1073
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
891
1074
|
// if params is undefined, the interval was deleted during
|
|
@@ -900,7 +1083,7 @@ export function makeOpsMap() {
|
|
|
900
1083
|
},
|
|
901
1084
|
],
|
|
902
1085
|
[
|
|
903
|
-
|
|
1086
|
+
IntervalOpType.DELETE,
|
|
904
1087
|
{
|
|
905
1088
|
process: (collection, params, local, op) => {
|
|
906
1089
|
assert(op !== undefined, 0x3fc /* op should exist here */);
|
|
@@ -913,7 +1096,7 @@ export function makeOpsMap() {
|
|
|
913
1096
|
},
|
|
914
1097
|
],
|
|
915
1098
|
[
|
|
916
|
-
|
|
1099
|
+
IntervalOpType.CHANGE,
|
|
917
1100
|
{
|
|
918
1101
|
process: (collection, params, local, op, localOpMetadata) => {
|
|
919
1102
|
// if params is undefined, the interval was deleted during
|
|
@@ -929,7 +1112,7 @@ export function makeOpsMap() {
|
|
|
929
1112
|
],
|
|
930
1113
|
]);
|
|
931
1114
|
}
|
|
932
|
-
|
|
1115
|
+
class IntervalCollectionIterator {
|
|
933
1116
|
constructor(collection, iteratesForward = true, start, end) {
|
|
934
1117
|
this.results = [];
|
|
935
1118
|
this.index = 0;
|
|
@@ -949,19 +1132,16 @@ export class IntervalCollectionIterator {
|
|
|
949
1132
|
}
|
|
950
1133
|
}
|
|
951
1134
|
/**
|
|
952
|
-
*
|
|
953
|
-
* This class is not a DDS in its own right, but emits events on mutating operations such that it's possible to
|
|
954
|
-
* integrate into a DDS.
|
|
955
|
-
* This aligns with its usage in `SharedSegmentSequence`, which allows associating intervals to positions in the
|
|
956
|
-
* sequence DDS which are broadcast to all other clients in an eventually consistent fashion.
|
|
1135
|
+
* {@inheritdoc IIntervalCollection}
|
|
957
1136
|
*/
|
|
958
1137
|
export class IntervalCollection extends TypedEventEmitter {
|
|
959
1138
|
/** @internal */
|
|
960
|
-
constructor(helpers, requiresClient, emitter, serializedIntervals) {
|
|
1139
|
+
constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
|
|
961
1140
|
super();
|
|
962
1141
|
this.helpers = helpers;
|
|
963
1142
|
this.requiresClient = requiresClient;
|
|
964
1143
|
this.emitter = emitter;
|
|
1144
|
+
this.options = options;
|
|
965
1145
|
this.localSeqToSerializedInterval = new Map();
|
|
966
1146
|
this.localSeqToRebasedInterval = new Map();
|
|
967
1147
|
this.pendingChangesStart = new Map();
|
|
@@ -973,6 +1153,36 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
973
1153
|
get attached() {
|
|
974
1154
|
return !!this.localCollection;
|
|
975
1155
|
}
|
|
1156
|
+
/**
|
|
1157
|
+
* {@inheritdoc IIntervalCollection.attachIndex}
|
|
1158
|
+
*/
|
|
1159
|
+
attachIndex(index) {
|
|
1160
|
+
var _a;
|
|
1161
|
+
if (!this.attached) {
|
|
1162
|
+
throw new LoggingError("The local interval collection must exist");
|
|
1163
|
+
}
|
|
1164
|
+
for (const interval of this) {
|
|
1165
|
+
index.add(interval);
|
|
1166
|
+
}
|
|
1167
|
+
(_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.appendIndex(index);
|
|
1168
|
+
}
|
|
1169
|
+
/**
|
|
1170
|
+
* {@inheritdoc IIntervalCollection.detachIndex}
|
|
1171
|
+
*/
|
|
1172
|
+
detachIndex(index) {
|
|
1173
|
+
var _a;
|
|
1174
|
+
if (!this.attached) {
|
|
1175
|
+
throw new LoggingError("The local interval collection must exist");
|
|
1176
|
+
}
|
|
1177
|
+
// Avoid removing intervals if the index does not exist
|
|
1178
|
+
if (!((_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.removeIndex(index))) {
|
|
1179
|
+
return false;
|
|
1180
|
+
}
|
|
1181
|
+
for (const interval of this) {
|
|
1182
|
+
index.remove(interval);
|
|
1183
|
+
}
|
|
1184
|
+
return true;
|
|
1185
|
+
}
|
|
976
1186
|
rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
|
|
977
1187
|
var _a;
|
|
978
1188
|
if (!this.client) {
|
|
@@ -1028,8 +1238,8 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1028
1238
|
if (this.savedSerializedIntervals) {
|
|
1029
1239
|
for (const serializedInterval of this.savedSerializedIntervals) {
|
|
1030
1240
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1031
|
-
const { start, end, intervalType, properties } = serializedInterval;
|
|
1032
|
-
const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true);
|
|
1241
|
+
const { start, end, intervalType, properties, stickiness } = serializedInterval;
|
|
1242
|
+
const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, stickiness);
|
|
1033
1243
|
if (properties) {
|
|
1034
1244
|
interval.addProperties(properties);
|
|
1035
1245
|
}
|
|
@@ -1067,8 +1277,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1067
1277
|
}
|
|
1068
1278
|
}
|
|
1069
1279
|
/**
|
|
1070
|
-
* @
|
|
1071
|
-
* If no interval in the collection has this `id`, returns `undefined`.
|
|
1280
|
+
* {@inheritdoc IIntervalCollection.getIntervalById}
|
|
1072
1281
|
*/
|
|
1073
1282
|
getIntervalById(id) {
|
|
1074
1283
|
if (!this.localCollection) {
|
|
@@ -1077,16 +1286,9 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1077
1286
|
return this.localCollection.idIntervalIndex.getIntervalById(id);
|
|
1078
1287
|
}
|
|
1079
1288
|
/**
|
|
1080
|
-
*
|
|
1081
|
-
* @param start - interval start position (inclusive)
|
|
1082
|
-
* @param end - interval end position (exclusive)
|
|
1083
|
-
* @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
|
|
1084
|
-
* @param props - properties of the interval
|
|
1085
|
-
* @returns - the created interval
|
|
1086
|
-
* @remarks - See documentation on {@link SequenceInterval} for comments on interval endpoint semantics: there are subtleties
|
|
1087
|
-
* with how the current half-open behavior is represented.
|
|
1289
|
+
* {@inheritdoc IIntervalCollection.add}
|
|
1088
1290
|
*/
|
|
1089
|
-
add(start, end, intervalType, props) {
|
|
1291
|
+
add(start, end, intervalType, props, stickiness = IntervalStickiness.END) {
|
|
1090
1292
|
var _a, _b;
|
|
1091
1293
|
if (!this.localCollection) {
|
|
1092
1294
|
throw new LoggingError("attach must be called prior to adding intervals");
|
|
@@ -1094,7 +1296,10 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1094
1296
|
if (intervalType & IntervalType.Transient) {
|
|
1095
1297
|
throw new LoggingError("Can not add transient intervals");
|
|
1096
1298
|
}
|
|
1097
|
-
|
|
1299
|
+
if (stickiness !== IntervalStickiness.END && !this.options.intervalStickinessEnabled) {
|
|
1300
|
+
throw new UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
|
|
1301
|
+
}
|
|
1302
|
+
const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
|
|
1098
1303
|
if (interval) {
|
|
1099
1304
|
const serializedInterval = {
|
|
1100
1305
|
end,
|
|
@@ -1102,6 +1307,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1102
1307
|
properties: interval.properties,
|
|
1103
1308
|
sequenceNumber: (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.getCurrentSeq()) !== null && _b !== void 0 ? _b : 0,
|
|
1104
1309
|
start,
|
|
1310
|
+
stickiness,
|
|
1105
1311
|
};
|
|
1106
1312
|
const localSeq = this.getNextLocalSeq();
|
|
1107
1313
|
this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
|
|
@@ -1133,9 +1339,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1133
1339
|
this.emit("deleteInterval", interval, local, op);
|
|
1134
1340
|
}
|
|
1135
1341
|
/**
|
|
1136
|
-
*
|
|
1137
|
-
* @param id - Id of the interval to remove
|
|
1138
|
-
* @returns the removed interval
|
|
1342
|
+
* {@inheritdoc IIntervalCollection.removeIntervalById}
|
|
1139
1343
|
*/
|
|
1140
1344
|
removeIntervalById(id) {
|
|
1141
1345
|
if (!this.localCollection) {
|
|
@@ -1148,10 +1352,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1148
1352
|
return interval;
|
|
1149
1353
|
}
|
|
1150
1354
|
/**
|
|
1151
|
-
*
|
|
1152
|
-
* @param id - Id of the interval whose properties should be changed
|
|
1153
|
-
* @param props - Property set to apply to the interval. Shallow merging is used between any existing properties
|
|
1154
|
-
* and `prop`, i.e. the interval will end up with a property object equivalent to `{ ...oldProps, ...props }`.
|
|
1355
|
+
* {@inheritdoc IIntervalCollection.changeProperties}
|
|
1155
1356
|
*/
|
|
1156
1357
|
changeProperties(id, props) {
|
|
1157
1358
|
if (!this.attached) {
|
|
@@ -1181,11 +1382,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1181
1382
|
}
|
|
1182
1383
|
}
|
|
1183
1384
|
/**
|
|
1184
|
-
*
|
|
1185
|
-
* @param id - Id of the interval to change
|
|
1186
|
-
* @param start - New start value, if defined. `undefined` signifies this endpoint should be left unchanged.
|
|
1187
|
-
* @param end - New end value, if defined. `undefined` signifies this endpoint should be left unchanged.
|
|
1188
|
-
* @returns the interval that was changed, if it existed in the collection.
|
|
1385
|
+
* {@inheritdoc IIntervalCollection.change}
|
|
1189
1386
|
*/
|
|
1190
1387
|
change(id, start, end) {
|
|
1191
1388
|
if (!this.localCollection) {
|
|
@@ -1340,6 +1537,9 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1340
1537
|
throw new LoggingError("attachSequence must be called");
|
|
1341
1538
|
}
|
|
1342
1539
|
}
|
|
1540
|
+
/**
|
|
1541
|
+
* {@inheritdoc IIntervalCollection.attachDeserializer}
|
|
1542
|
+
*/
|
|
1343
1543
|
attachDeserializer(onDeserialize) {
|
|
1344
1544
|
// If no deserializer is specified can skip all processing work
|
|
1345
1545
|
if (!onDeserialize) {
|
|
@@ -1460,7 +1660,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1460
1660
|
}
|
|
1461
1661
|
if (needsStartUpdate) {
|
|
1462
1662
|
const props = interval.start.properties;
|
|
1463
|
-
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op);
|
|
1663
|
+
interval.start = createPositionReferenceFromSegoff(this.client, newStart, interval.start.refType, op, startReferenceSlidingPreference(interval.stickiness));
|
|
1464
1664
|
if (props) {
|
|
1465
1665
|
interval.start.addProperties(props);
|
|
1466
1666
|
}
|
|
@@ -1472,7 +1672,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1472
1672
|
}
|
|
1473
1673
|
if (needsEndUpdate) {
|
|
1474
1674
|
const props = interval.end.properties;
|
|
1475
|
-
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op);
|
|
1675
|
+
interval.end = createPositionReferenceFromSegoff(this.client, newEnd, interval.end.refType, op, endReferenceSlidingPreference(interval.stickiness));
|
|
1476
1676
|
if (props) {
|
|
1477
1677
|
interval.end.addProperties(props);
|
|
1478
1678
|
}
|
|
@@ -1503,7 +1703,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1503
1703
|
throw new LoggingError("attachSequence must be called");
|
|
1504
1704
|
}
|
|
1505
1705
|
this.localCollection.ensureSerializedId(serializedInterval);
|
|
1506
|
-
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op);
|
|
1706
|
+
const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op, serializedInterval.stickiness);
|
|
1507
1707
|
if (interval) {
|
|
1508
1708
|
if (this.onDeserialize) {
|
|
1509
1709
|
this.onDeserialize(interval);
|
|
@@ -1546,40 +1746,35 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1546
1746
|
return iterator;
|
|
1547
1747
|
}
|
|
1548
1748
|
/**
|
|
1549
|
-
* @
|
|
1749
|
+
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithStartPosition}
|
|
1550
1750
|
*/
|
|
1551
1751
|
CreateForwardIteratorWithStartPosition(startPosition) {
|
|
1552
1752
|
const iterator = new IntervalCollectionIterator(this, true, startPosition);
|
|
1553
1753
|
return iterator;
|
|
1554
1754
|
}
|
|
1555
1755
|
/**
|
|
1556
|
-
* @
|
|
1756
|
+
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithStartPosition}
|
|
1557
1757
|
*/
|
|
1558
1758
|
CreateBackwardIteratorWithStartPosition(startPosition) {
|
|
1559
1759
|
const iterator = new IntervalCollectionIterator(this, false, startPosition);
|
|
1560
1760
|
return iterator;
|
|
1561
1761
|
}
|
|
1562
1762
|
/**
|
|
1563
|
-
* @
|
|
1763
|
+
* {@inheritdoc IIntervalCollection.CreateForwardIteratorWithEndPosition}
|
|
1564
1764
|
*/
|
|
1565
1765
|
CreateForwardIteratorWithEndPosition(endPosition) {
|
|
1566
1766
|
const iterator = new IntervalCollectionIterator(this, true, undefined, endPosition);
|
|
1567
1767
|
return iterator;
|
|
1568
1768
|
}
|
|
1569
1769
|
/**
|
|
1570
|
-
* @
|
|
1770
|
+
* {@inheritdoc IIntervalCollection.CreateBackwardIteratorWithEndPosition}
|
|
1571
1771
|
*/
|
|
1572
1772
|
CreateBackwardIteratorWithEndPosition(endPosition) {
|
|
1573
1773
|
const iterator = new IntervalCollectionIterator(this, false, undefined, endPosition);
|
|
1574
1774
|
return iterator;
|
|
1575
1775
|
}
|
|
1576
1776
|
/**
|
|
1577
|
-
*
|
|
1578
|
-
* @param results - Array to gather the results into. In lieu of a return value, this array will be populated with
|
|
1579
|
-
* intervals matching the query upon edit.
|
|
1580
|
-
* @param iteratesForward - whether or not iteration should be in the forward direction
|
|
1581
|
-
* @param start - If provided, only match intervals whose start point is equal to `start`.
|
|
1582
|
-
* @param end - If provided, only match intervals whose end point is equal to `end`.
|
|
1777
|
+
* {@inheritdoc IIntervalCollection.gatherIterationResults}
|
|
1583
1778
|
*/
|
|
1584
1779
|
gatherIterationResults(results, iteratesForward, start, end) {
|
|
1585
1780
|
if (!this.localCollection) {
|
|
@@ -1588,8 +1783,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1588
1783
|
this.localCollection.overlappingIntervalsIndex.gatherIterationResults(results, iteratesForward, start, end);
|
|
1589
1784
|
}
|
|
1590
1785
|
/**
|
|
1591
|
-
* @
|
|
1592
|
-
* `[startPosition, endPosition]`.
|
|
1786
|
+
* {@inheritdoc IIntervalCollection.findOverlappingIntervals}
|
|
1593
1787
|
*/
|
|
1594
1788
|
findOverlappingIntervals(startPosition, endPosition) {
|
|
1595
1789
|
if (!this.localCollection) {
|
|
@@ -1598,7 +1792,7 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1598
1792
|
return this.localCollection.overlappingIntervalsIndex.findOverlappingIntervals(startPosition, endPosition);
|
|
1599
1793
|
}
|
|
1600
1794
|
/**
|
|
1601
|
-
*
|
|
1795
|
+
* {@inheritdoc IIntervalCollection.map}
|
|
1602
1796
|
*/
|
|
1603
1797
|
map(fn) {
|
|
1604
1798
|
if (!this.localCollection) {
|
|
@@ -1608,12 +1802,18 @@ export class IntervalCollection extends TypedEventEmitter {
|
|
|
1608
1802
|
fn(interval);
|
|
1609
1803
|
}
|
|
1610
1804
|
}
|
|
1805
|
+
/**
|
|
1806
|
+
* {@inheritdoc IIntervalCollection.previousInterval}
|
|
1807
|
+
*/
|
|
1611
1808
|
previousInterval(pos) {
|
|
1612
1809
|
if (!this.localCollection) {
|
|
1613
1810
|
throw new LoggingError("attachSequence must be called");
|
|
1614
1811
|
}
|
|
1615
1812
|
return this.localCollection.endIntervalIndex.previousInterval(pos);
|
|
1616
1813
|
}
|
|
1814
|
+
/**
|
|
1815
|
+
* {@inheritdoc IIntervalCollection.nextInterval}
|
|
1816
|
+
*/
|
|
1617
1817
|
nextInterval(pos) {
|
|
1618
1818
|
if (!this.localCollection) {
|
|
1619
1819
|
throw new LoggingError("attachSequence must be called");
|