@fluidframework/sequence 2.43.0 → 2.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/intervalCollection.d.ts +4 -5
  3. package/dist/intervalCollection.d.ts.map +1 -1
  4. package/dist/intervalCollection.js +93 -97
  5. package/dist/intervalCollection.js.map +1 -1
  6. package/dist/intervalCollectionMapInterfaces.d.ts +2 -11
  7. package/dist/intervalCollectionMapInterfaces.d.ts.map +1 -1
  8. package/dist/intervalCollectionMapInterfaces.js.map +1 -1
  9. package/dist/intervals/sequenceInterval.d.ts +7 -3
  10. package/dist/intervals/sequenceInterval.d.ts.map +1 -1
  11. package/dist/intervals/sequenceInterval.js +72 -30
  12. package/dist/intervals/sequenceInterval.js.map +1 -1
  13. package/dist/packageVersion.d.ts +1 -1
  14. package/dist/packageVersion.js +1 -1
  15. package/dist/packageVersion.js.map +1 -1
  16. package/lib/intervalCollection.d.ts +4 -5
  17. package/lib/intervalCollection.d.ts.map +1 -1
  18. package/lib/intervalCollection.js +93 -97
  19. package/lib/intervalCollection.js.map +1 -1
  20. package/lib/intervalCollectionMapInterfaces.d.ts +2 -11
  21. package/lib/intervalCollectionMapInterfaces.d.ts.map +1 -1
  22. package/lib/intervalCollectionMapInterfaces.js.map +1 -1
  23. package/lib/intervals/sequenceInterval.d.ts +7 -3
  24. package/lib/intervals/sequenceInterval.d.ts.map +1 -1
  25. package/lib/intervals/sequenceInterval.js +74 -32
  26. package/lib/intervals/sequenceInterval.js.map +1 -1
  27. package/lib/packageVersion.d.ts +1 -1
  28. package/lib/packageVersion.js +1 -1
  29. package/lib/packageVersion.js.map +1 -1
  30. package/package.json +17 -17
  31. package/src/intervalCollection.ts +109 -106
  32. package/src/intervalCollectionMapInterfaces.ts +2 -13
  33. package/src/intervals/sequenceInterval.ts +88 -32
  34. package/src/packageVersion.ts +1 -1
@@ -5,6 +5,7 @@
5
5
 
6
6
  /* eslint-disable no-bitwise */
7
7
 
8
+ import type { IDisposable } from "@fluidframework/core-interfaces";
8
9
  import { assert } from "@fluidframework/core-utils/internal";
9
10
  import { ISequencedDocumentMessage } from "@fluidframework/driver-definitions/internal";
10
11
  import {
@@ -27,12 +28,11 @@ import {
27
28
  Side,
28
29
  endpointPosAndSide,
29
30
  addProperties,
30
- copyPropertiesAndManager,
31
31
  type ISegmentInternal,
32
32
  UnassignedSequenceNumber,
33
33
  UniversalSequenceNumber,
34
34
  } from "@fluidframework/merge-tree/internal";
35
- import { UsageError } from "@fluidframework/telemetry-utils/internal";
35
+ import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
36
36
  import { v4 as uuid } from "uuid";
37
37
 
38
38
  import {
@@ -222,8 +222,10 @@ export interface SequenceInterval extends ISerializableInterval {
222
222
  getIntervalId(): string;
223
223
  }
224
224
 
225
- // eslint-disable-next-line import/no-deprecated
226
- export class SequenceIntervalClass implements SequenceInterval, ISerializableInterval {
225
+ export class SequenceIntervalClass
226
+ // eslint-disable-next-line import/no-deprecated
227
+ implements SequenceInterval, ISerializableInterval, IDisposable
228
+ {
227
229
  readonly #props: {
228
230
  propertyManager?: PropertiesManager;
229
231
  properties: PropertySet;
@@ -233,6 +235,7 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
233
235
  * {@inheritDoc ISerializableInterval.properties}
234
236
  */
235
237
  public get properties(): Readonly<PropertySet> {
238
+ this.verifyNotDispose();
236
239
  return this.#props.properties;
237
240
  }
238
241
 
@@ -241,6 +244,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
241
244
  op?: ISequencedDocumentMessage,
242
245
  rollback?: boolean,
243
246
  ) {
247
+ this.verifyNotDispose();
248
+
244
249
  if (props !== undefined) {
245
250
  this.#props.propertyManager ??= new PropertiesManager();
246
251
  return this.#props.propertyManager.handleProperties(
@@ -258,6 +263,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
258
263
 
259
264
  /***/
260
265
  public get stickiness(): IntervalStickiness {
266
+ this.verifyNotDispose();
267
+
261
268
  const startSegment: ISegmentInternal | undefined = this.start.getSegment();
262
269
  const endSegment: ISegmentInternal | undefined = this.end.getSegment();
263
270
  return computeStickinessFromSide(
@@ -291,6 +298,24 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
291
298
  this.#props.properties = addProperties(this.#props.properties, props);
292
299
  }
293
300
  }
301
+ #disposed = false;
302
+ public get disposed() {
303
+ return this.#disposed;
304
+ }
305
+ public dispose(error?: Error): void {
306
+ if (this.#disposed) return;
307
+ this.#disposed = true;
308
+ this.client.removeLocalReferencePosition(this.start);
309
+ this.client.removeLocalReferencePosition(this.end);
310
+ this.removePositionChangeListeners();
311
+ this.#props.propertyManager = undefined;
312
+ }
313
+
314
+ private verifyNotDispose() {
315
+ if (this.#disposed) {
316
+ throw new LoggingError("Invalid interval access after dispose");
317
+ }
318
+ }
294
319
 
295
320
  private callbacks?: Record<"beforePositionChange" | "afterPositionChange", () => void>;
296
321
 
@@ -301,6 +326,7 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
301
326
  beforePositionChange: () => void,
302
327
  afterPositionChange: () => void,
303
328
  ): void {
329
+ this.verifyNotDispose();
304
330
  if (this.callbacks === undefined) {
305
331
  this.callbacks = {
306
332
  beforePositionChange,
@@ -329,6 +355,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
329
355
  * {@inheritDoc ISerializableInterval.serialize}
330
356
  */
331
357
  public serialize(): ISerializedInterval {
358
+ this.verifyNotDispose();
359
+
332
360
  return this.serializeDelta({
333
361
  props: this.properties,
334
362
  includeEndpoints: true,
@@ -342,6 +370,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
342
370
  props: PropertySet | undefined;
343
371
  includeEndpoints: boolean;
344
372
  }): SerializedIntervalDelta {
373
+ this.verifyNotDispose();
374
+
345
375
  const startSegment: ISegmentInternal | undefined = this.start.getSegment();
346
376
  const endSegment: ISegmentInternal | undefined = this.end.getSegment();
347
377
  const startPosition = includeEndpoints
@@ -371,6 +401,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
371
401
  * {@inheritDoc IInterval.clone}
372
402
  */
373
403
  public clone(): SequenceIntervalClass {
404
+ this.verifyNotDispose();
405
+
374
406
  return new SequenceIntervalClass(
375
407
  this.client,
376
408
  this.id,
@@ -413,6 +445,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
413
445
  * {@inheritDoc IInterval.compareStart}
414
446
  */
415
447
  public compareStart(b: SequenceInterval) {
448
+ this.verifyNotDispose();
449
+
416
450
  const dist = compareReferencePositions(this.start, b.start);
417
451
 
418
452
  if (dist === 0) {
@@ -426,6 +460,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
426
460
  * {@inheritDoc IInterval.compareEnd}
427
461
  */
428
462
  public compareEnd(b: SequenceInterval): number {
463
+ this.verifyNotDispose();
464
+
429
465
  const dist = compareReferencePositions(this.end, b.end);
430
466
 
431
467
  if (dist === 0) {
@@ -439,6 +475,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
439
475
  * {@inheritDoc IInterval.overlaps}
440
476
  */
441
477
  public overlaps(b: SequenceInterval) {
478
+ this.verifyNotDispose();
479
+
442
480
  const result =
443
481
  compareReferencePositions(this.start, b.end) <= 0 &&
444
482
  compareReferencePositions(this.end, b.start) >= 0;
@@ -456,6 +494,8 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
456
494
  * {@inheritDoc IInterval.union}
457
495
  */
458
496
  public union(b: SequenceIntervalClass) {
497
+ this.verifyNotDispose();
498
+
459
499
  const newStart = minReferencePosition(this.start, b.start);
460
500
  const newEnd = maxReferencePosition(this.end, b.end);
461
501
 
@@ -492,41 +532,41 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
492
532
  * @returns whether this interval overlaps two numerical positions.
493
533
  */
494
534
  public overlapsPos(bstart: number, bend: number) {
535
+ this.verifyNotDispose();
536
+
495
537
  const startPos = this.client.localReferencePositionToPosition(this.start);
496
538
  const endPos = this.client.localReferencePositionToPosition(this.end);
497
539
  return endPos > bstart && startPos < bend;
498
540
  }
499
541
 
500
542
  public moveEndpointReferences(
501
- rebased: Partial<Record<"start" | "end", { segment: ISegment; offset: number }>>,
543
+ rebased: Record<"start" | "end", { segment: ISegment; offset: number }>,
502
544
  ) {
503
- if (rebased.start) {
504
- const startRef = createPositionReferenceFromSegoff({
505
- client: this.client,
506
- segoff: rebased.start,
507
- refType: this.start.refType,
508
- slidingPreference: this.start.slidingPreference,
509
- canSlideToEndpoint: this.start.canSlideToEndpoint,
510
- });
511
- if (this.start.properties) {
512
- startRef.addProperties(this.start.properties);
513
- }
514
- this.start = startRef;
545
+ this.verifyNotDispose();
546
+
547
+ const startRef = createPositionReferenceFromSegoff({
548
+ client: this.client,
549
+ segoff: rebased.start,
550
+ refType: this.start.refType,
551
+ slidingPreference: this.start.slidingPreference,
552
+ canSlideToEndpoint: this.start.canSlideToEndpoint,
553
+ });
554
+ if (this.start.properties) {
555
+ startRef.addProperties(this.start.properties);
515
556
  }
516
-
517
- if (rebased.end) {
518
- const endRef = createPositionReferenceFromSegoff({
519
- client: this.client,
520
- segoff: rebased.end,
521
- refType: this.end.refType,
522
- slidingPreference: this.end.slidingPreference,
523
- canSlideToEndpoint: this.end.canSlideToEndpoint,
524
- });
525
- if (this.end.properties) {
526
- endRef.addProperties(this.end.properties);
527
- }
528
- this.end = endRef;
557
+ this.start = startRef;
558
+
559
+ const endRef = createPositionReferenceFromSegoff({
560
+ client: this.client,
561
+ segoff: rebased.end,
562
+ refType: this.end.refType,
563
+ slidingPreference: this.end.slidingPreference,
564
+ canSlideToEndpoint: this.end.canSlideToEndpoint,
565
+ });
566
+ if (this.end.properties) {
567
+ endRef.addProperties(this.end.properties);
529
568
  }
569
+ this.end = endRef;
530
570
  }
531
571
 
532
572
  /**
@@ -540,12 +580,17 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
540
580
  localSeq?: number,
541
581
  canSlideToEndpoint: boolean = false,
542
582
  ) {
583
+ this.verifyNotDispose();
584
+
543
585
  const { startSide, endSide, startPos, endPos } = endpointPosAndSide(start, end);
544
586
  const getRefType = (baseType: ReferenceType): ReferenceType => {
545
587
  let refType = baseType;
546
588
  if (op === undefined) {
547
589
  refType &= ~ReferenceType.SlideOnRemove;
548
590
  refType |= ReferenceType.StayOnRemove;
591
+ } else {
592
+ refType &= ~ReferenceType.StayOnRemove;
593
+ refType |= ReferenceType.SlideOnRemove;
549
594
  }
550
595
  return refType;
551
596
  };
@@ -607,12 +652,23 @@ export class SequenceIntervalClass implements SequenceInterval, ISerializableInt
607
652
  startSide ?? this.startSide,
608
653
  endSide ?? this.endSide,
609
654
  );
610
- copyPropertiesAndManager(this.#props, newInterval.#props);
655
+ newInterval.#props.propertyManager = this.#props.propertyManager ??=
656
+ new PropertiesManager();
657
+ newInterval.#props.properties = this.#props.properties;
611
658
  return newInterval;
612
659
  }
613
660
 
614
661
  public ackPropertiesChange(newProps: PropertySet, op: ISequencedDocumentMessage) {
615
- this.#props.propertyManager ??= new PropertiesManager();
662
+ this.verifyNotDispose();
663
+
664
+ if (Object.keys(newProps).length === 0) {
665
+ return;
666
+ }
667
+
668
+ assert(
669
+ this.#props.propertyManager !== undefined,
670
+ 0xbd5 /* must have property manager to ack */,
671
+ );
616
672
  // Let the propertyManager prune its pending change-properties set.
617
673
  this.#props.propertyManager.ack(op.sequenceNumber, op.minimumSequenceNumber, {
618
674
  props: newProps,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/sequence";
9
- export const pkgVersion = "2.43.0";
9
+ export const pkgVersion = "2.50.0";