@fluidframework/sequence 2.32.0 → 2.33.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 +16 -0
- package/api-report/sequence.legacy.alpha.api.md +39 -39
- package/dist/intervalCollection.d.ts +14 -9
- package/dist/intervalCollection.d.ts.map +1 -1
- package/dist/intervalCollection.js +137 -77
- package/dist/intervalCollection.js.map +1 -1
- package/dist/intervalCollectionMap.d.ts +5 -4
- package/dist/intervalCollectionMap.d.ts.map +1 -1
- package/dist/intervalCollectionMap.js +25 -50
- package/dist/intervalCollectionMap.js.map +1 -1
- package/dist/intervalCollectionMapInterfaces.d.ts +22 -15
- package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/dist/intervalCollectionMapInterfaces.js.map +1 -1
- package/dist/intervalIndex/intervalIndex.d.ts +1 -1
- package/dist/intervalIndex/intervalIndex.js.map +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +1 -1
- package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/dist/intervals/sequenceInterval.d.ts +3 -3
- package/dist/intervals/sequenceInterval.d.ts.map +1 -1
- package/dist/intervals/sequenceInterval.js +10 -9
- 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/dist/sequence.d.ts +4 -0
- package/dist/sequence.d.ts.map +1 -1
- package/dist/sequence.js +10 -0
- package/dist/sequence.js.map +1 -1
- package/dist/sharedIntervalCollection.d.ts +1 -1
- package/dist/sharedIntervalCollection.js.map +1 -1
- package/dist/sharedString.d.ts +0 -4
- package/dist/sharedString.d.ts.map +1 -1
- package/dist/sharedString.js +0 -11
- package/dist/sharedString.js.map +1 -1
- package/lib/intervalCollection.d.ts +14 -9
- package/lib/intervalCollection.d.ts.map +1 -1
- package/lib/intervalCollection.js +138 -78
- package/lib/intervalCollection.js.map +1 -1
- package/lib/intervalCollectionMap.d.ts +5 -4
- package/lib/intervalCollectionMap.d.ts.map +1 -1
- package/lib/intervalCollectionMap.js +26 -51
- package/lib/intervalCollectionMap.js.map +1 -1
- package/lib/intervalCollectionMapInterfaces.d.ts +22 -15
- package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
- package/lib/intervalCollectionMapInterfaces.js.map +1 -1
- package/lib/intervalIndex/intervalIndex.d.ts +1 -1
- package/lib/intervalIndex/intervalIndex.js.map +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +1 -1
- package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
- package/lib/intervals/sequenceInterval.d.ts +3 -3
- package/lib/intervals/sequenceInterval.d.ts.map +1 -1
- package/lib/intervals/sequenceInterval.js +10 -9
- 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/lib/sequence.d.ts +4 -0
- package/lib/sequence.d.ts.map +1 -1
- package/lib/sequence.js +10 -0
- package/lib/sequence.js.map +1 -1
- package/lib/sharedIntervalCollection.d.ts +1 -1
- package/lib/sharedIntervalCollection.js.map +1 -1
- package/lib/sharedString.d.ts +0 -4
- package/lib/sharedString.d.ts.map +1 -1
- package/lib/sharedString.js +0 -11
- package/lib/sharedString.js.map +1 -1
- package/lib/tsdoc-metadata.json +1 -1
- package/package.json +18 -20
- package/src/intervalCollection.ts +188 -96
- package/src/intervalCollectionMap.ts +31 -60
- package/src/intervalCollectionMapInterfaces.ts +34 -29
- package/src/intervalIndex/intervalIndex.ts +1 -1
- package/src/intervalIndex/overlappingIntervalsIndex.ts +1 -1
- package/src/intervals/sequenceInterval.ts +14 -2
- package/src/packageVersion.ts +1 -1
- package/src/sequence.ts +15 -0
- package/src/sharedIntervalCollection.ts +1 -1
- package/src/sharedString.ts +0 -11
|
@@ -13,9 +13,6 @@ import { ValueType, IFluidSerializer } from "@fluidframework/shared-object-base/
|
|
|
13
13
|
import { makeSerializable } from "./IntervalCollectionValues.js";
|
|
14
14
|
import {
|
|
15
15
|
IntervalCollection,
|
|
16
|
-
opsMap,
|
|
17
|
-
toOptionalSequencePlace,
|
|
18
|
-
toSequencePlace,
|
|
19
16
|
type ISerializedIntervalCollectionV1,
|
|
20
17
|
type ISerializedIntervalCollectionV2,
|
|
21
18
|
} from "./intervalCollection.js";
|
|
@@ -25,7 +22,6 @@ import {
|
|
|
25
22
|
ISerializableIntervalCollection,
|
|
26
23
|
SequenceOptions,
|
|
27
24
|
} from "./intervalCollectionMapInterfaces.js";
|
|
28
|
-
import { getSerializedProperties } from "./intervals/index.js";
|
|
29
25
|
|
|
30
26
|
function isMapOperation(op: unknown): op is IMapOperation {
|
|
31
27
|
return typeof op === "object" && op !== null && "type" in op && op.type === "act";
|
|
@@ -190,63 +186,46 @@ export class IntervalCollectionMap {
|
|
|
190
186
|
|
|
191
187
|
/**
|
|
192
188
|
* Submit the given op if a handler is registered.
|
|
193
|
-
* @param
|
|
189
|
+
* @param content - The operation to attempt to submit
|
|
194
190
|
* @param localOpMetadata - The local metadata associated with the op. This is kept locally by the runtime
|
|
195
191
|
* and not sent to the server. This will be sent back when this message is received back from the server. This is
|
|
196
192
|
* also sent if we are asked to resubmit the message.
|
|
197
193
|
* @returns True if the operation was submitted, false otherwise.
|
|
198
194
|
*/
|
|
199
|
-
public tryResubmitMessage(
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
195
|
+
public tryResubmitMessage(
|
|
196
|
+
content: unknown,
|
|
197
|
+
localOpMetadata: IMapMessageLocalMetadata,
|
|
198
|
+
): boolean {
|
|
199
|
+
if (isMapOperation(content)) {
|
|
200
|
+
const { value, key } = content;
|
|
201
|
+
const localValue = this.data.get(key);
|
|
203
202
|
assert(localValue !== undefined, 0x3f8 /* Local value expected on resubmission */);
|
|
203
|
+
localValue.resubmitMessage(value, localOpMetadata);
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
public tryRollback(content: any, localOpMetadata: unknown) {
|
|
210
|
+
if (isMapOperation(content)) {
|
|
211
|
+
const localValue = this.data.get(content.key);
|
|
212
|
+
|
|
213
|
+
assert(localValue !== undefined, 0xb7e /* Local value expected on rollback */);
|
|
214
|
+
|
|
215
|
+
localValue.rollback(content.value, localOpMetadata as IMapMessageLocalMetadata);
|
|
204
216
|
|
|
205
|
-
const handler = opsMap[op.value.opName];
|
|
206
|
-
const rebased = handler.rebase(localValue, op.value, localOpMetadata);
|
|
207
|
-
if (rebased !== undefined) {
|
|
208
|
-
const { rebasedOp, rebasedLocalOpMetadata } = rebased;
|
|
209
|
-
this.submitMessage({ ...op, value: rebasedOp }, rebasedLocalOpMetadata);
|
|
210
|
-
}
|
|
211
217
|
return true;
|
|
212
218
|
}
|
|
213
219
|
return false;
|
|
214
220
|
}
|
|
215
221
|
|
|
216
|
-
public tryApplyStashedOp(
|
|
217
|
-
if (isMapOperation(
|
|
218
|
-
const { value, key } =
|
|
222
|
+
public tryApplyStashedOp(content: unknown): boolean {
|
|
223
|
+
if (isMapOperation(content)) {
|
|
224
|
+
const { value, key } = content;
|
|
219
225
|
const map = this.get(key);
|
|
220
|
-
const { id, properties } = getSerializedProperties(value.value);
|
|
221
226
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
map.add({
|
|
225
|
-
id,
|
|
226
|
-
// Todo: we should improve typing so we know add ops always have start and end
|
|
227
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
228
|
-
start: toSequencePlace(value.value.start!, value.value.startSide),
|
|
229
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
230
|
-
end: toSequencePlace(value.value.end!, value.value.endSide),
|
|
231
|
-
props: properties,
|
|
232
|
-
});
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
case "change": {
|
|
236
|
-
map.change(id, {
|
|
237
|
-
start: toOptionalSequencePlace(value.value.start, value.value.startSide),
|
|
238
|
-
end: toOptionalSequencePlace(value.value.end, value.value.endSide),
|
|
239
|
-
props: properties,
|
|
240
|
-
});
|
|
241
|
-
return true;
|
|
242
|
-
}
|
|
243
|
-
case "delete": {
|
|
244
|
-
map.removeIntervalById(id);
|
|
245
|
-
return true;
|
|
246
|
-
}
|
|
247
|
-
default:
|
|
248
|
-
throw new Error("unknown ops should not be stashed");
|
|
249
|
-
}
|
|
227
|
+
map.applyStashedOp(value);
|
|
228
|
+
return true;
|
|
250
229
|
}
|
|
251
230
|
return false;
|
|
252
231
|
}
|
|
@@ -267,23 +246,15 @@ export class IntervalCollectionMap {
|
|
|
267
246
|
* (since its data no longer matches what other clients think the data should be) and will avoid overriding document content or misleading the users into thinking their current state is accurate.
|
|
268
247
|
*/
|
|
269
248
|
public tryProcessMessage(
|
|
270
|
-
|
|
249
|
+
content: unknown,
|
|
271
250
|
local: boolean,
|
|
272
251
|
message: ISequencedDocumentMessage,
|
|
273
252
|
localOpMetadata: unknown,
|
|
274
253
|
): boolean {
|
|
275
|
-
if (isMapOperation(
|
|
276
|
-
const
|
|
277
|
-
const
|
|
278
|
-
|
|
279
|
-
const translatedValue = op.value.value as any;
|
|
280
|
-
handler.process(
|
|
281
|
-
previousValue,
|
|
282
|
-
translatedValue,
|
|
283
|
-
local,
|
|
284
|
-
message,
|
|
285
|
-
localOpMetadata as IMapMessageLocalMetadata,
|
|
286
|
-
);
|
|
254
|
+
if (isMapOperation(content)) {
|
|
255
|
+
const { value, key } = content;
|
|
256
|
+
const localValue = this.data.get(key) ?? this.createCore(key, local);
|
|
257
|
+
localValue.process(value, local, message, localOpMetadata as IMapMessageLocalMetadata);
|
|
287
258
|
return true;
|
|
288
259
|
}
|
|
289
260
|
return false;
|
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
|
|
20
20
|
export interface IMapMessageLocalMetadata {
|
|
21
21
|
localSeq: number;
|
|
22
|
+
previous?: ISerializedInterval;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
/**
|
|
@@ -74,25 +75,6 @@ export interface IIntervalCollectionOperation {
|
|
|
74
75
|
message: ISequencedDocumentMessage | undefined,
|
|
75
76
|
localOpMetadata: IMapMessageLocalMetadata | undefined,
|
|
76
77
|
): void;
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Rebases an `op` on `value` from its original perspective (ref/local seq) to the current
|
|
80
|
-
* perspective. Should be invoked on reconnection.
|
|
81
|
-
* @param value - The current value stored at the given key, which should be the value type.
|
|
82
|
-
* @param op - The op to be rebased.
|
|
83
|
-
* @param localOpMetadata - Any local metadata that was originally submitted with the op.
|
|
84
|
-
* @returns A rebased version of the op and any local metadata that should be submitted with it.
|
|
85
|
-
*/
|
|
86
|
-
rebase(
|
|
87
|
-
value: IntervalCollection,
|
|
88
|
-
op: IIntervalCollectionTypeOperationValue,
|
|
89
|
-
localOpMetadata: IMapMessageLocalMetadata,
|
|
90
|
-
):
|
|
91
|
-
| {
|
|
92
|
-
rebasedOp: IIntervalCollectionTypeOperationValue;
|
|
93
|
-
rebasedLocalOpMetadata: IMapMessageLocalMetadata;
|
|
94
|
-
}
|
|
95
|
-
| undefined;
|
|
96
78
|
}
|
|
97
79
|
|
|
98
80
|
/**
|
|
@@ -138,14 +120,37 @@ export interface ISerializedIntervalCollection {
|
|
|
138
120
|
* serializable via JSON.stringify/parse but differs in that it has no equivalency with an in-memory value - rather
|
|
139
121
|
* it just describes an operation to be applied to an already-in-memory value.
|
|
140
122
|
*/
|
|
141
|
-
export
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
123
|
+
export type IIntervalCollectionTypeOperationValue =
|
|
124
|
+
| {
|
|
125
|
+
/**
|
|
126
|
+
* The name of the operation.
|
|
127
|
+
*/
|
|
128
|
+
opName: typeof IntervalDeltaOpType.ADD;
|
|
146
129
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
130
|
+
/**
|
|
131
|
+
* The payload that is submitted along with the operation.
|
|
132
|
+
*/
|
|
133
|
+
value: ISerializedInterval;
|
|
134
|
+
}
|
|
135
|
+
| {
|
|
136
|
+
/**
|
|
137
|
+
* The name of the operation.
|
|
138
|
+
*/
|
|
139
|
+
opName: typeof IntervalDeltaOpType.CHANGE;
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The payload that is submitted along with the operation.
|
|
143
|
+
*/
|
|
144
|
+
value: SerializedIntervalDelta;
|
|
145
|
+
}
|
|
146
|
+
| {
|
|
147
|
+
/**
|
|
148
|
+
* The name of the operation.
|
|
149
|
+
*/
|
|
150
|
+
opName: typeof IntervalDeltaOpType.DELETE;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* The payload that is submitted along with the operation.
|
|
154
|
+
*/
|
|
155
|
+
value: SerializedIntervalDelta;
|
|
156
|
+
};
|
|
@@ -16,7 +16,7 @@ import { ISerializableInterval, type SequenceInterval } from "../intervals/index
|
|
|
16
16
|
* @legacy
|
|
17
17
|
* @alpha
|
|
18
18
|
*
|
|
19
|
-
* @
|
|
19
|
+
* @deprecated The generic version of this interface is no longer used and will be removed. Use {@link SequenceIntervalIndex} instead.
|
|
20
20
|
*/
|
|
21
21
|
export interface IntervalIndex<TInterval extends ISerializableInterval> {
|
|
22
22
|
/**
|
|
@@ -26,7 +26,7 @@ import { IntervalIndex, type SequenceIntervalIndex } from "./intervalIndex.js";
|
|
|
26
26
|
* Use {@link ISequenceOverlappingIntervalsIndex} instead.
|
|
27
27
|
* @legacy
|
|
28
28
|
* @alpha
|
|
29
|
-
* @
|
|
29
|
+
* @deprecated The generic version of this interface is no longer used and will be removed. Use {@link ISequenceOverlappingIntervalsIndex} instead.
|
|
30
30
|
*/
|
|
31
31
|
export interface IOverlappingIntervalsIndex<TInterval extends ISerializableInterval>
|
|
32
32
|
extends IntervalIndex<TInterval> {
|
|
@@ -219,7 +219,11 @@ export class SequenceIntervalClass implements SequenceInterval {
|
|
|
219
219
|
return this.#props.properties;
|
|
220
220
|
}
|
|
221
221
|
|
|
222
|
-
public changeProperties(
|
|
222
|
+
public changeProperties(
|
|
223
|
+
props: PropertySet | undefined,
|
|
224
|
+
op?: ISequencedDocumentMessage,
|
|
225
|
+
rollback?: boolean,
|
|
226
|
+
) {
|
|
223
227
|
if (props !== undefined) {
|
|
224
228
|
this.#props.propertyManager ??= new PropertiesManager();
|
|
225
229
|
return this.#props.propertyManager.handleProperties(
|
|
@@ -230,6 +234,7 @@ export class SequenceIntervalClass implements SequenceInterval {
|
|
|
230
234
|
: UniversalSequenceNumber,
|
|
231
235
|
op?.minimumSequenceNumber ?? UniversalSequenceNumber,
|
|
232
236
|
this.client.getCollabWindow().collaborating,
|
|
237
|
+
rollback,
|
|
233
238
|
);
|
|
234
239
|
}
|
|
235
240
|
}
|
|
@@ -573,6 +578,7 @@ export function createPositionReferenceFromSegoff(
|
|
|
573
578
|
fromSnapshot?: boolean,
|
|
574
579
|
slidingPreference?: SlidingPreference,
|
|
575
580
|
canSlideToEndpoint?: boolean,
|
|
581
|
+
rollback?: boolean,
|
|
576
582
|
): LocalReferencePosition {
|
|
577
583
|
if (segoff === "start" || segoff === "end") {
|
|
578
584
|
return client.createLocalReferencePosition(
|
|
@@ -606,7 +612,8 @@ export function createPositionReferenceFromSegoff(
|
|
|
606
612
|
!op &&
|
|
607
613
|
!localSeq &&
|
|
608
614
|
!fromSnapshot &&
|
|
609
|
-
!refTypeIncludesFlag(refType, ReferenceType.Transient)
|
|
615
|
+
!refTypeIncludesFlag(refType, ReferenceType.Transient) &&
|
|
616
|
+
!rollback
|
|
610
617
|
) {
|
|
611
618
|
throw new UsageError("Non-transient references need segment");
|
|
612
619
|
}
|
|
@@ -624,6 +631,7 @@ function createPositionReference(
|
|
|
624
631
|
slidingPreference?: SlidingPreference,
|
|
625
632
|
exclusive: boolean = false,
|
|
626
633
|
useNewSlidingBehavior: boolean = false,
|
|
634
|
+
rollback?: boolean,
|
|
627
635
|
): LocalReferencePosition {
|
|
628
636
|
let segoff;
|
|
629
637
|
|
|
@@ -661,6 +669,7 @@ function createPositionReference(
|
|
|
661
669
|
fromSnapshot,
|
|
662
670
|
slidingPreference,
|
|
663
671
|
exclusive,
|
|
672
|
+
rollback,
|
|
664
673
|
);
|
|
665
674
|
}
|
|
666
675
|
|
|
@@ -690,6 +699,7 @@ export function createSequenceInterval(
|
|
|
690
699
|
fromSnapshot?: boolean,
|
|
691
700
|
useNewSlidingBehavior: boolean = false,
|
|
692
701
|
props?: PropertySet,
|
|
702
|
+
rollback?: boolean,
|
|
693
703
|
): SequenceIntervalClass {
|
|
694
704
|
const { startPos, startSide, endPos, endSide } = endpointPosAndSide(
|
|
695
705
|
start ?? "start",
|
|
@@ -731,6 +741,7 @@ export function createSequenceInterval(
|
|
|
731
741
|
startReferenceSlidingPreference(stickiness),
|
|
732
742
|
startReferenceSlidingPreference(stickiness) === SlidingPreference.BACKWARD,
|
|
733
743
|
useNewSlidingBehavior,
|
|
744
|
+
rollback,
|
|
734
745
|
);
|
|
735
746
|
|
|
736
747
|
const endLref = createPositionReference(
|
|
@@ -743,6 +754,7 @@ export function createSequenceInterval(
|
|
|
743
754
|
endReferenceSlidingPreference(stickiness),
|
|
744
755
|
endReferenceSlidingPreference(stickiness) === SlidingPreference.FORWARD,
|
|
745
756
|
useNewSlidingBehavior,
|
|
757
|
+
rollback,
|
|
746
758
|
);
|
|
747
759
|
|
|
748
760
|
const rangeProp = {
|
package/src/packageVersion.ts
CHANGED
package/src/sequence.ts
CHANGED
|
@@ -796,6 +796,21 @@ export abstract class SharedSegmentSequence<T extends ISegment>
|
|
|
796
796
|
});
|
|
797
797
|
}
|
|
798
798
|
|
|
799
|
+
/**
|
|
800
|
+
* Revert an op
|
|
801
|
+
*/
|
|
802
|
+
protected rollback(content: any, localOpMetadata: unknown): void {
|
|
803
|
+
const originalRefSeq = this.inFlightRefSeqs.pop();
|
|
804
|
+
assert(
|
|
805
|
+
originalRefSeq !== undefined,
|
|
806
|
+
0xb7f /* Expected a recorded refSeq when rolling back an op */,
|
|
807
|
+
);
|
|
808
|
+
|
|
809
|
+
if (!this.intervalCollections.tryRollback(content, localOpMetadata)) {
|
|
810
|
+
this.client.rollback(content, localOpMetadata);
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
|
|
799
814
|
/**
|
|
800
815
|
* {@inheritDoc @fluidframework/shared-object-base#SharedObject.loadCore}
|
|
801
816
|
*/
|
|
@@ -10,7 +10,7 @@ import { ISerializableInterval } from "./intervals/index.js";
|
|
|
10
10
|
/**
|
|
11
11
|
* @legacy
|
|
12
12
|
* @alpha
|
|
13
|
-
* @
|
|
13
|
+
* @deprecated This interface is no longer used and will be removed.
|
|
14
14
|
*/
|
|
15
15
|
export interface ISharedIntervalCollection<TInterval extends ISerializableInterval> {
|
|
16
16
|
// eslint-disable-next-line import/no-deprecated
|
package/src/sharedString.ts
CHANGED
|
@@ -271,17 +271,6 @@ export class SharedStringClass
|
|
|
271
271
|
public getMarkerFromId(id: string): ISegment | undefined {
|
|
272
272
|
return this.client.getMarkerFromId(id);
|
|
273
273
|
}
|
|
274
|
-
|
|
275
|
-
/**
|
|
276
|
-
* Revert an op
|
|
277
|
-
*/
|
|
278
|
-
protected rollback(content: any, localOpMetadata: unknown): void {
|
|
279
|
-
if (this.client.rollback !== undefined) {
|
|
280
|
-
this.client.rollback(content, localOpMetadata);
|
|
281
|
-
} else {
|
|
282
|
-
super.rollback(content, localOpMetadata);
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
274
|
}
|
|
286
275
|
|
|
287
276
|
interface ITextAndMarkerAccumulator {
|