@fluidframework/sequence 2.0.0-dev.3.1.0.125672 → 2.0.0-dev.4.2.0.153917
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 +12 -0
- package/README.md +50 -11
- package/dist/intervalCollection.d.ts +40 -8
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +42 -13
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalTree.d.ts +8 -1
- package/dist/intervalTree.d.ts.map +1 -1
- package/dist/intervalTree.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/sequence.d.ts.map +1 -1
- package/dist/sequence.js +1 -8
- package/dist/sequence.js.map +1 -1
- package/lib/intervalCollection.d.ts +40 -8
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +42 -13
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalTree.d.ts +8 -1
- package/lib/intervalTree.d.ts.map +1 -1
- package/lib/intervalTree.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/sequence.d.ts.map +1 -1
- package/lib/sequence.js +2 -9
- package/lib/sequence.js.map +1 -1
- package/package.json +78 -68
- package/src/intervalCollection.ts +50 -16
- package/src/intervalTree.ts +8 -1
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +2 -15
- package/.editorconfig +0 -7
|
@@ -78,9 +78,9 @@ export interface ISerializedInterval {
|
|
|
78
78
|
* At the time of writing, it's not plumbed through to the reconnect/rebase code, however, which does need it.
|
|
79
79
|
*/
|
|
80
80
|
sequenceNumber: number;
|
|
81
|
-
/** Start position of the interval
|
|
81
|
+
/** Start position of the interval */
|
|
82
82
|
start: number;
|
|
83
|
-
/** End position of the interval
|
|
83
|
+
/** End position of the interval */
|
|
84
84
|
end: number;
|
|
85
85
|
/** Interval type to create */
|
|
86
86
|
intervalType: IntervalType;
|
|
@@ -209,6 +209,7 @@ export class Interval implements ISerializableInterval {
|
|
|
209
209
|
public auxProps: PropertySet[] | undefined;
|
|
210
210
|
/**
|
|
211
211
|
* {@inheritDoc ISerializableInterval.propertyManager}
|
|
212
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
212
213
|
*/
|
|
213
214
|
public propertyManager: PropertiesManager;
|
|
214
215
|
constructor(public start: number, public end: number, props?: PropertySet) {
|
|
@@ -223,11 +224,9 @@ export class Interval implements ISerializableInterval {
|
|
|
223
224
|
/**
|
|
224
225
|
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
225
226
|
*/
|
|
226
|
-
public getIntervalId(): string
|
|
227
|
+
public getIntervalId(): string {
|
|
227
228
|
const id = this.properties?.[reservedIntervalIdKey];
|
|
228
|
-
|
|
229
|
-
return undefined;
|
|
230
|
-
}
|
|
229
|
+
assert(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
|
|
231
230
|
return `${id}`;
|
|
232
231
|
}
|
|
233
232
|
|
|
@@ -326,6 +325,7 @@ export class Interval implements ISerializableInterval {
|
|
|
326
325
|
|
|
327
326
|
/**
|
|
328
327
|
* {@inheritDoc IInterval.union}
|
|
328
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
329
329
|
*/
|
|
330
330
|
public union(b: Interval) {
|
|
331
331
|
return new Interval(
|
|
@@ -341,6 +341,7 @@ export class Interval implements ISerializableInterval {
|
|
|
341
341
|
|
|
342
342
|
/**
|
|
343
343
|
* {@inheritDoc ISerializableInterval.addProperties}
|
|
344
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
344
345
|
*/
|
|
345
346
|
public addProperties(
|
|
346
347
|
newProps: PropertySet,
|
|
@@ -362,6 +363,7 @@ export class Interval implements ISerializableInterval {
|
|
|
362
363
|
|
|
363
364
|
/**
|
|
364
365
|
* {@inheritDoc IInterval.modify}
|
|
366
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
365
367
|
*/
|
|
366
368
|
public modify(label: string, start: number, end: number, op?: ISequencedDocumentMessage) {
|
|
367
369
|
const startPos = start ?? this.start;
|
|
@@ -396,6 +398,22 @@ export class Interval implements ISerializableInterval {
|
|
|
396
398
|
* Interval impelmentation whose ends are associated with positions in a mutatable sequence.
|
|
397
399
|
* As such, when content is inserted into the middle of the interval, the interval expands to
|
|
398
400
|
* include that content.
|
|
401
|
+
*
|
|
402
|
+
* @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
|
|
403
|
+
* an interval referring to "hello" in "hello world" should have a start position of 0 and an end
|
|
404
|
+
* position of 5.
|
|
405
|
+
*
|
|
406
|
+
* To see why, consider what happens if "llo wor" is removed from the string to make "held".
|
|
407
|
+
* The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
|
|
408
|
+
* slides forward to the next unremoved position, which is the "l" in "held".
|
|
409
|
+
* Users would generally expect the interval to now refer to "he" (as it is the subset of content
|
|
410
|
+
* remaining after the removal), hence the "l" should be excluded.
|
|
411
|
+
* If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
|
|
412
|
+
* is undesirable.
|
|
413
|
+
*
|
|
414
|
+
* Since the end of an interval is treated exclusively but cannot be greater than or equal to the
|
|
415
|
+
* length of the associated sequence, application models which leverage interval collections should
|
|
416
|
+
* consider inserting a marker at the end of the sequence to represent the end of the content.
|
|
399
417
|
*/
|
|
400
418
|
export class SequenceInterval implements ISerializableInterval {
|
|
401
419
|
/**
|
|
@@ -404,6 +422,7 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
404
422
|
public properties: PropertySet;
|
|
405
423
|
/**
|
|
406
424
|
* {@inheritDoc ISerializableInterval.propertyManager}
|
|
425
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
407
426
|
*/
|
|
408
427
|
public propertyManager: PropertiesManager;
|
|
409
428
|
|
|
@@ -551,16 +570,15 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
551
570
|
/**
|
|
552
571
|
* {@inheritDoc ISerializableInterval.getIntervalId}
|
|
553
572
|
*/
|
|
554
|
-
public getIntervalId(): string
|
|
573
|
+
public getIntervalId(): string {
|
|
555
574
|
const id = this.properties?.[reservedIntervalIdKey];
|
|
556
|
-
|
|
557
|
-
return undefined;
|
|
558
|
-
}
|
|
575
|
+
assert(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
|
|
559
576
|
return `${id}`;
|
|
560
577
|
}
|
|
561
578
|
|
|
562
579
|
/**
|
|
563
580
|
* {@inheritDoc IInterval.union}
|
|
581
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
564
582
|
*/
|
|
565
583
|
public union(b: SequenceInterval) {
|
|
566
584
|
return new SequenceInterval(
|
|
@@ -573,6 +591,7 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
573
591
|
|
|
574
592
|
/**
|
|
575
593
|
* {@inheritDoc ISerializableInterval.addProperties}
|
|
594
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
576
595
|
*/
|
|
577
596
|
public addProperties(
|
|
578
597
|
newProps: PropertySet,
|
|
@@ -586,7 +605,6 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
586
605
|
|
|
587
606
|
/**
|
|
588
607
|
* @returns whether this interval overlaps two numerical positions.
|
|
589
|
-
* @remarks - this is currently strict overlap, which doesn't align with the endpoint treatment of`.overlaps()`
|
|
590
608
|
*/
|
|
591
609
|
public overlapsPos(bstart: number, bend: number) {
|
|
592
610
|
const startPos = this.client.localReferencePositionToPosition(this.start);
|
|
@@ -596,6 +614,7 @@ export class SequenceInterval implements ISerializableInterval {
|
|
|
596
614
|
|
|
597
615
|
/**
|
|
598
616
|
* {@inheritDoc IInterval.modify}
|
|
617
|
+
* @deprecated - This API was never intended to be public and will be marked internal in a future release.
|
|
599
618
|
*/
|
|
600
619
|
public modify(
|
|
601
620
|
label: string,
|
|
@@ -671,6 +690,7 @@ function createPositionReferenceFromSegoff(
|
|
|
671
690
|
refType: ReferenceType,
|
|
672
691
|
op?: ISequencedDocumentMessage,
|
|
673
692
|
localSeq?: number,
|
|
693
|
+
fromSnapshot?: boolean,
|
|
674
694
|
): LocalReferencePosition {
|
|
675
695
|
if (segoff.segment) {
|
|
676
696
|
const ref = client.createLocalReferencePosition(
|
|
@@ -687,7 +707,12 @@ function createPositionReferenceFromSegoff(
|
|
|
687
707
|
// - References coming from a remote client (location may have been concurrently removed)
|
|
688
708
|
// - References being rebased to a new sequence number
|
|
689
709
|
// (segment they originally referred to may have been removed with no suitable replacement)
|
|
690
|
-
if (
|
|
710
|
+
if (
|
|
711
|
+
!op &&
|
|
712
|
+
!localSeq &&
|
|
713
|
+
!fromSnapshot &&
|
|
714
|
+
!refTypeIncludesFlag(refType, ReferenceType.Transient)
|
|
715
|
+
) {
|
|
691
716
|
throw new UsageError("Non-transient references need segment");
|
|
692
717
|
}
|
|
693
718
|
|
|
@@ -720,7 +745,7 @@ function createPositionReference(
|
|
|
720
745
|
);
|
|
721
746
|
segoff = client.getContainingSegment(pos, undefined, localSeq);
|
|
722
747
|
}
|
|
723
|
-
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq);
|
|
748
|
+
return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot);
|
|
724
749
|
}
|
|
725
750
|
|
|
726
751
|
export function createSequenceInterval(
|
|
@@ -945,7 +970,7 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
|
|
|
945
970
|
|
|
946
971
|
/**
|
|
947
972
|
* @returns an array of all intervals contained in this collection that overlap the range
|
|
948
|
-
* `[startPosition, endPosition
|
|
973
|
+
* `[startPosition, endPosition)`.
|
|
949
974
|
*/
|
|
950
975
|
public findOverlappingIntervals(startPosition: number, endPosition: number) {
|
|
951
976
|
if (endPosition < startPosition || this.intervalTree.intervals.isEmpty()) {
|
|
@@ -1626,11 +1651,13 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
|
|
|
1626
1651
|
|
|
1627
1652
|
/**
|
|
1628
1653
|
* Creates a new interval and add it to the collection.
|
|
1629
|
-
* @param start - interval start position
|
|
1630
|
-
* @param end - interval end position
|
|
1654
|
+
* @param start - interval start position (inclusive)
|
|
1655
|
+
* @param end - interval end position (exclusive)
|
|
1631
1656
|
* @param intervalType - type of the interval. All intervals are SlideOnRemove. Intervals may not be Transient.
|
|
1632
1657
|
* @param props - properties of the interval
|
|
1633
1658
|
* @returns - the created interval
|
|
1659
|
+
* @remarks - See documentation on {@link SequenceInterval} for comments on interval endpoint semantics: there are subtleties
|
|
1660
|
+
* with how the current half-open behavior is represented.
|
|
1634
1661
|
*/
|
|
1635
1662
|
public add(
|
|
1636
1663
|
start: number,
|
|
@@ -1931,6 +1958,13 @@ export class IntervalCollection<TInterval extends ISerializableInterval> extends
|
|
|
1931
1958
|
}
|
|
1932
1959
|
}
|
|
1933
1960
|
|
|
1961
|
+
/**
|
|
1962
|
+
* @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
|
|
1963
|
+
* in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
|
|
1964
|
+
* at the same location and gives each interval a unique id.
|
|
1965
|
+
*
|
|
1966
|
+
* As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
|
|
1967
|
+
*/
|
|
1934
1968
|
public addConflictResolver(conflictResolver: IntervalConflictResolver<TInterval>): void {
|
|
1935
1969
|
if (!this.localCollection) {
|
|
1936
1970
|
throw new LoggingError("attachSequence must be called");
|
package/src/intervalTree.ts
CHANGED
|
@@ -61,7 +61,7 @@ export interface IInterval {
|
|
|
61
61
|
): IInterval | undefined;
|
|
62
62
|
/**
|
|
63
63
|
* @returns whether this interval overlaps with `b`.
|
|
64
|
-
*
|
|
64
|
+
* Intervals are considered to overlap if their intersection is non-empty.
|
|
65
65
|
*/
|
|
66
66
|
overlaps(b: IInterval): boolean;
|
|
67
67
|
/**
|
|
@@ -77,6 +77,13 @@ const intervalComparer = (a: IInterval, b: IInterval) => a.compare(b);
|
|
|
77
77
|
|
|
78
78
|
export type IntervalNode<T extends IInterval> = RBNode<T, AugmentedIntervalNode>;
|
|
79
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
|
|
82
|
+
* in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
|
|
83
|
+
* at the same location and gives each interval a unique id.
|
|
84
|
+
*
|
|
85
|
+
* As such, conflict resolvers are never invoked and unnecessary. They will be removed in an upcoming release.
|
|
86
|
+
*/
|
|
80
87
|
export type IntervalConflictResolver<TInterval> = (a: TInterval, b: TInterval) => TInterval;
|
|
81
88
|
|
|
82
89
|
export class IntervalTree<T extends IInterval>
|
package/src/packageVersion.ts
CHANGED
package/src/sequence.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { Deferred, bufferToString, assert } from "@fluidframework/common-utils";
|
|
6
|
-
import { ChildLogger
|
|
6
|
+
import { ChildLogger } from "@fluidframework/telemetry-utils";
|
|
7
7
|
import { ISequencedDocumentMessage, MessageType } from "@fluidframework/protocol-definitions";
|
|
8
8
|
import {
|
|
9
9
|
IChannelAttributes,
|
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
IMergeTreeDeltaOp,
|
|
23
23
|
IMergeTreeGroupMsg,
|
|
24
24
|
IMergeTreeOp,
|
|
25
|
-
IMergeTreeOptions,
|
|
26
25
|
IMergeTreeRemoveMsg,
|
|
27
26
|
IRelativePosition,
|
|
28
27
|
ISegment,
|
|
@@ -197,22 +196,10 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
197
196
|
this.logger.sendErrorEvent({ eventName: "SequenceLoadFailed" }, error);
|
|
198
197
|
});
|
|
199
198
|
|
|
200
|
-
const mergeTreeOptions = {
|
|
201
|
-
...(dataStoreRuntime.options as IMergeTreeOptions),
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
const configSetAttribution = loggerToMonitoringContext(this.logger).config.getBoolean(
|
|
205
|
-
"Fluid.Attribution.EnableOnNewFile",
|
|
206
|
-
);
|
|
207
|
-
if (configSetAttribution !== undefined) {
|
|
208
|
-
mergeTreeOptions.attribution ??= {};
|
|
209
|
-
mergeTreeOptions.attribution.track = configSetAttribution;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
199
|
this.client = new Client(
|
|
213
200
|
segmentFromSpec,
|
|
214
201
|
ChildLogger.create(this.logger, "SharedSegmentSequence.MergeTreeClient"),
|
|
215
|
-
|
|
202
|
+
dataStoreRuntime.options,
|
|
216
203
|
);
|
|
217
204
|
|
|
218
205
|
this.client.on("delta", (opArgs, deltaArgs) => {
|