@fluidframework/sequence 1.2.1 → 2.0.0-internal.1.0.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 (46) hide show
  1. package/dist/intervalCollection.d.ts +5 -10
  2. package/dist/intervalCollection.d.ts.map +1 -1
  3. package/dist/intervalCollection.js +31 -41
  4. package/dist/intervalCollection.js.map +1 -1
  5. package/dist/packageVersion.d.ts +1 -1
  6. package/dist/packageVersion.d.ts.map +1 -1
  7. package/dist/packageVersion.js +1 -1
  8. package/dist/packageVersion.js.map +1 -1
  9. package/dist/sequence.d.ts +5 -17
  10. package/dist/sequence.d.ts.map +1 -1
  11. package/dist/sequence.js +4 -28
  12. package/dist/sequence.js.map +1 -1
  13. package/dist/sequenceDeltaEvent.d.ts +0 -6
  14. package/dist/sequenceDeltaEvent.d.ts.map +1 -1
  15. package/dist/sequenceDeltaEvent.js +0 -1
  16. package/dist/sequenceDeltaEvent.js.map +1 -1
  17. package/dist/sharedString.d.ts +30 -1
  18. package/dist/sharedString.d.ts.map +1 -1
  19. package/dist/sharedString.js +40 -5
  20. package/dist/sharedString.js.map +1 -1
  21. package/lib/intervalCollection.d.ts +5 -10
  22. package/lib/intervalCollection.d.ts.map +1 -1
  23. package/lib/intervalCollection.js +32 -42
  24. package/lib/intervalCollection.js.map +1 -1
  25. package/lib/packageVersion.d.ts +1 -1
  26. package/lib/packageVersion.d.ts.map +1 -1
  27. package/lib/packageVersion.js +1 -1
  28. package/lib/packageVersion.js.map +1 -1
  29. package/lib/sequence.d.ts +5 -17
  30. package/lib/sequence.d.ts.map +1 -1
  31. package/lib/sequence.js +5 -29
  32. package/lib/sequence.js.map +1 -1
  33. package/lib/sequenceDeltaEvent.d.ts +0 -6
  34. package/lib/sequenceDeltaEvent.d.ts.map +1 -1
  35. package/lib/sequenceDeltaEvent.js +0 -1
  36. package/lib/sequenceDeltaEvent.js.map +1 -1
  37. package/lib/sharedString.d.ts +30 -1
  38. package/lib/sharedString.d.ts.map +1 -1
  39. package/lib/sharedString.js +38 -4
  40. package/lib/sharedString.js.map +1 -1
  41. package/package.json +61 -21
  42. package/src/intervalCollection.ts +45 -61
  43. package/src/packageVersion.ts +1 -1
  44. package/src/sequence.ts +4 -36
  45. package/src/sequenceDeltaEvent.ts +0 -7
  46. package/src/sharedString.ts +44 -6
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/sequence",
3
- "version": "1.2.1",
3
+ "version": "2.0.0-internal.1.0.0",
4
4
  "description": "Distributed sequence",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -63,29 +63,29 @@
63
63
  },
64
64
  "dependencies": {
65
65
  "@fluidframework/common-definitions": "^0.20.1",
66
- "@fluidframework/common-utils": "^0.32.1",
67
- "@fluidframework/container-utils": "^1.2.1",
68
- "@fluidframework/core-interfaces": "^1.2.1",
69
- "@fluidframework/datastore-definitions": "^1.2.1",
70
- "@fluidframework/merge-tree": "^1.2.1",
71
- "@fluidframework/protocol-definitions": "^0.1028.2000",
72
- "@fluidframework/runtime-definitions": "^1.2.1",
73
- "@fluidframework/runtime-utils": "^1.2.1",
74
- "@fluidframework/shared-object-base": "^1.2.1",
75
- "@fluidframework/telemetry-utils": "^1.2.1",
66
+ "@fluidframework/common-utils": "^1.0.0",
67
+ "@fluidframework/container-utils": "^2.0.0-internal.1.0.0",
68
+ "@fluidframework/core-interfaces": "^2.0.0-internal.1.0.0",
69
+ "@fluidframework/datastore-definitions": "^2.0.0-internal.1.0.0",
70
+ "@fluidframework/merge-tree": "^2.0.0-internal.1.0.0",
71
+ "@fluidframework/protocol-definitions": "^1.0.0",
72
+ "@fluidframework/runtime-definitions": "^2.0.0-internal.1.0.0",
73
+ "@fluidframework/runtime-utils": "^2.0.0-internal.1.0.0",
74
+ "@fluidframework/shared-object-base": "^2.0.0-internal.1.0.0",
75
+ "@fluidframework/telemetry-utils": "^2.0.0-internal.1.0.0",
76
76
  "uuid": "^8.3.1"
77
77
  },
78
78
  "devDependencies": {
79
- "@fluid-internal/stochastic-test-utils": "^1.2.1",
80
- "@fluid-internal/test-dds-utils": "^1.2.1",
79
+ "@fluid-internal/stochastic-test-utils": "^2.0.0-internal.1.0.0",
80
+ "@fluid-internal/test-dds-utils": "^2.0.0-internal.1.0.0",
81
81
  "@fluidframework/build-common": "^0.24.0",
82
- "@fluidframework/build-tools": "^0.2.74327",
82
+ "@fluidframework/build-tools": "^0.3.1000",
83
83
  "@fluidframework/eslint-config-fluid": "^0.28.2000",
84
- "@fluidframework/gitresources": "^0.1036.5000",
85
- "@fluidframework/mocha-test-setup": "^1.2.1",
86
- "@fluidframework/sequence-previous": "npm:@fluidframework/sequence@1.2.0",
87
- "@fluidframework/server-services-client": "^0.1036.5000",
88
- "@fluidframework/test-runtime-utils": "^1.2.1",
84
+ "@fluidframework/gitresources": "^0.1037.1000",
85
+ "@fluidframework/mocha-test-setup": "^2.0.0-internal.1.0.0",
86
+ "@fluidframework/sequence-previous": "npm:@fluidframework/sequence@^1.0.0",
87
+ "@fluidframework/server-services-client": "^0.1037.1000",
88
+ "@fluidframework/test-runtime-utils": "^2.0.0-internal.1.0.0",
89
89
  "@microsoft/api-extractor": "^7.22.2",
90
90
  "@rushstack/eslint-config": "^2.5.1",
91
91
  "@types/diff": "^3.5.1",
@@ -105,7 +105,47 @@
105
105
  "typescript-formatter": "7.1.0"
106
106
  },
107
107
  "typeValidation": {
108
- "version": "1.2.1",
109
- "broken": {}
108
+ "version": "2.0.0",
109
+ "broken": {
110
+ "ClassDeclaration_IntervalCollection": {
111
+ "backCompat": false
112
+ },
113
+ "ClassDeclaration_SequenceInterval": {
114
+ "backCompat": false
115
+ },
116
+ "InterfaceDeclaration_ISharedString": {
117
+ "backCompat": false
118
+ },
119
+ "ClassDeclaration_SequenceEvent": {
120
+ "backCompat": false
121
+ },
122
+ "ClassDeclaration_SequenceDeltaEvent": {
123
+ "backCompat": false
124
+ },
125
+ "ClassDeclaration_SequenceMaintenanceEvent": {
126
+ "backCompat": false
127
+ },
128
+ "ClassDeclaration_SharedNumberSequence": {
129
+ "backCompat": false
130
+ },
131
+ "ClassDeclaration_SharedObjectSequence": {
132
+ "backCompat": false
133
+ },
134
+ "ClassDeclaration_SharedSegmentSequence": {
135
+ "backCompat": false
136
+ },
137
+ "ClassDeclaration_SharedSequence": {
138
+ "backCompat": false
139
+ },
140
+ "ClassDeclaration_SharedString": {
141
+ "backCompat": false
142
+ },
143
+ "TypeAliasDeclaration_SharedStringSegment": {
144
+ "backCompat": false
145
+ },
146
+ "ClassDeclaration_SparseMatrix": {
147
+ "backCompat": false
148
+ }
149
+ }
110
150
  }
111
151
  }
@@ -11,6 +11,7 @@ import { UsageError } from "@fluidframework/container-utils";
11
11
  import {
12
12
  addProperties,
13
13
  Client,
14
+ compareReferencePositions,
14
15
  ConflictAction,
15
16
  createMap,
16
17
  ICombiningOp,
@@ -19,15 +20,18 @@ import {
19
20
  IntervalNode,
20
21
  IntervalTree,
21
22
  ISegment,
22
- LocalReference,
23
23
  MergeTreeDeltaType,
24
+ minReferencePosition,
24
25
  PropertiesManager,
25
26
  PropertySet,
26
27
  RedBlackTree,
28
+ LocalReferencePosition,
27
29
  ReferenceType,
28
30
  refTypeIncludesFlag,
29
31
  reservedRangeLabelsKey,
30
32
  UnassignedSequenceNumber,
33
+ maxReferencePosition,
34
+ createDetachedLocalReferencePosition,
31
35
  } from "@fluidframework/merge-tree";
32
36
  import { ISequencedDocumentMessage } from "@fluidframework/protocol-definitions";
33
37
  import { LoggingError } from "@fluidframework/telemetry-utils";
@@ -187,11 +191,7 @@ export class Interval implements ISerializableInterval {
187
191
  }
188
192
 
189
193
  public serialize(client: Client): ISerializedInterval {
190
- let seq = 0;
191
- if (client) {
192
- seq = client.getCurrentSeq();
193
- }
194
-
194
+ const seq = client?.getCurrentSeq() ?? 0;
195
195
  const serializedInterval: ISerializedInterval = {
196
196
  end: this.end,
197
197
  intervalType: 0,
@@ -295,8 +295,9 @@ export class SequenceInterval implements ISerializableInterval {
295
295
  public propertyManager: PropertiesManager;
296
296
 
297
297
  constructor(
298
- public start: LocalReference,
299
- public end: LocalReference,
298
+ private readonly client: Client,
299
+ public start: LocalReferencePosition,
300
+ public end: LocalReferencePosition,
300
301
  public intervalType: IntervalType,
301
302
  props?: PropertySet,
302
303
  ) {
@@ -341,8 +342,8 @@ export class SequenceInterval implements ISerializableInterval {
341
342
  }
342
343
 
343
344
  public serialize(client: Client): ISerializedInterval {
344
- const startPosition = this.start.toPosition();
345
- const endPosition = this.end.toPosition();
345
+ const startPosition = client.localReferencePositionToPosition(this.start);
346
+ const endPosition = client.localReferencePositionToPosition(this.end);
346
347
  const serializedInterval: ISerializedInterval = {
347
348
  end: endPosition,
348
349
  intervalType: this.intervalType,
@@ -358,7 +359,7 @@ export class SequenceInterval implements ISerializableInterval {
358
359
  }
359
360
 
360
361
  public clone() {
361
- return new SequenceInterval(this.start, this.end, this.intervalType, this.properties);
362
+ return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties);
362
363
  }
363
364
 
364
365
  public compare(b: SequenceInterval) {
@@ -384,16 +385,16 @@ export class SequenceInterval implements ISerializableInterval {
384
385
  }
385
386
 
386
387
  public compareStart(b: SequenceInterval) {
387
- return this.start.compare(b.start);
388
+ return compareReferencePositions(this.start, b.start);
388
389
  }
389
390
 
390
391
  public compareEnd(b: SequenceInterval) {
391
- return this.end.compare(b.end);
392
+ return compareReferencePositions(this.end, b.end);
392
393
  }
393
394
 
394
395
  public overlaps(b: SequenceInterval) {
395
- const result = (this.start.compare(b.end) <= 0) &&
396
- (this.end.compare(b.start) >= 0);
396
+ const result = (compareReferencePositions(this.start, b.end) <= 0) &&
397
+ (compareReferencePositions(this.end, b.start) >= 0);
397
398
  return result;
398
399
  }
399
400
 
@@ -406,8 +407,8 @@ export class SequenceInterval implements ISerializableInterval {
406
407
  }
407
408
 
408
409
  public union(b: SequenceInterval) {
409
- return new SequenceInterval(this.start.min(b.start),
410
- this.end.max(b.end), this.intervalType);
410
+ return new SequenceInterval(this.client, minReferencePosition(this.start, b.start),
411
+ maxReferencePosition(this.end, b.end), this.intervalType);
411
412
  }
412
413
 
413
414
  public addProperties(
@@ -421,8 +422,8 @@ export class SequenceInterval implements ISerializableInterval {
421
422
  }
422
423
 
423
424
  public overlapsPos(bstart: number, bend: number) {
424
- const startPos = this.start.toPosition();
425
- const endPos = this.start.toPosition();
425
+ const startPos = this.client.localReferencePositionToPosition(this.start);
426
+ const endPos = this.client.localReferencePositionToPosition(this.end);
426
427
  return (endPos > bstart) && (startPos < bend);
427
428
  }
428
429
 
@@ -438,20 +439,17 @@ export class SequenceInterval implements ISerializableInterval {
438
439
 
439
440
  let startRef = this.start;
440
441
  if (start !== undefined) {
441
- startRef = createPositionReference(this.start.getClient(), start, getRefType(this.start.refType), op);
442
+ startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op);
442
443
  startRef.addProperties(this.start.properties);
443
444
  }
444
445
 
445
446
  let endRef = this.end;
446
447
  if (end !== undefined) {
447
- endRef = createPositionReference(this.end.getClient(), end, getRefType(this.end.refType), op);
448
+ endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op);
448
449
  endRef.addProperties(this.end.properties);
449
450
  }
450
451
 
451
- startRef.pairedRef = endRef;
452
- endRef.pairedRef = startRef;
453
-
454
- const newInterval = new SequenceInterval(startRef, endRef, this.intervalType);
452
+ const newInterval = new SequenceInterval(this.client, startRef, endRef, this.intervalType);
455
453
  if (this.properties) {
456
454
  newInterval.initializeProperties();
457
455
  this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
@@ -473,16 +471,16 @@ function createPositionReferenceFromSegoff(
473
471
  client: Client,
474
472
  segoff: { segment: ISegment | undefined; offset: number | undefined; },
475
473
  refType: ReferenceType,
476
- op?: ISequencedDocumentMessage): LocalReference {
474
+ op?: ISequencedDocumentMessage): LocalReferencePosition {
477
475
  if (segoff.segment) {
478
476
  const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined);
479
- return ref as LocalReference;
477
+ return ref;
480
478
  } else {
481
479
  if (!op && !refTypeIncludesFlag(refType, ReferenceType.Transient)) {
482
480
  throw new UsageError("Non-transient references need segment");
483
481
  }
484
- return new LocalReference(client, undefined, 0, refType);
485
482
  }
483
+ return createDetachedLocalReferencePosition(refType);
486
484
  }
487
485
 
488
486
  function createPositionReference(
@@ -490,7 +488,7 @@ function createPositionReference(
490
488
  pos: number,
491
489
  refType: ReferenceType,
492
490
  op?: ISequencedDocumentMessage,
493
- fromSnapshot?: boolean): LocalReference {
491
+ fromSnapshot?: boolean): LocalReferencePosition {
494
492
  let segoff;
495
493
  if (op) {
496
494
  assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
@@ -536,15 +534,13 @@ function createSequenceInterval(
536
534
 
537
535
  const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot);
538
536
  const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot);
539
- startLref.pairedRef = endLref;
540
- endLref.pairedRef = startLref;
541
537
  const rangeProp = {
542
538
  [reservedRangeLabelsKey]: [label],
543
539
  };
544
540
  startLref.addProperties(rangeProp);
545
541
  endLref.addProperties(rangeProp);
546
542
 
547
- const ival = new SequenceInterval(startLref, endLref, intervalType, rangeProp);
543
+ const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp);
548
544
  return ival;
549
545
  }
550
546
 
@@ -867,7 +863,8 @@ export class LocalIntervalCollection<TInterval extends ISerializableInterval> {
867
863
  }
868
864
  }
869
865
 
870
- const compareSequenceIntervalEnds = (a: SequenceInterval, b: SequenceInterval): number => a.end.compare(b.end);
866
+ const compareSequenceIntervalEnds = (a: SequenceInterval, b: SequenceInterval): number =>
867
+ compareReferencePositions(a.end, b.end);
871
868
 
872
869
  class SequenceIntervalCollectionFactory
873
870
  implements IValueFactory<IntervalCollection<SequenceInterval>> {
@@ -1062,7 +1059,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1062
1059
  private savedSerializedIntervals?: ISerializedInterval[];
1063
1060
  private localCollection: LocalIntervalCollection<TInterval>;
1064
1061
  private onDeserialize: DeserializeCallback | undefined;
1065
- private client: Client;
1062
+ private client: Client | undefined;
1066
1063
  private readonly pendingChangesStart: Map<string, ISerializedInterval[]> = new Map<string, ISerializedInterval[]>();
1067
1064
  private readonly pendingChangesEnd: Map<string, ISerializedInterval[]> = new Map<string, ISerializedInterval[]>();
1068
1065
 
@@ -1128,7 +1125,11 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1128
1125
  * Gets the next local sequence number, modifying this client's collab window in doing so.
1129
1126
  */
1130
1127
  private getNextLocalSeq(): number {
1131
- return ++this.client.getCollabWindow().localSeq;
1128
+ if (this.client) {
1129
+ return ++this.client.getCollabWindow().localSeq;
1130
+ }
1131
+
1132
+ return 0;
1132
1133
  }
1133
1134
 
1134
1135
  public getIntervalById(id: string) {
@@ -1330,11 +1331,6 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1330
1331
  return entries && entries.length !== 0;
1331
1332
  }
1332
1333
 
1333
- /** @deprecated - use ackChange */
1334
- public changeInterval(serializedInterval: ISerializedInterval, local: boolean, op: ISequencedDocumentMessage) {
1335
- return this.ackChange(serializedInterval, local, op);
1336
- }
1337
-
1338
1334
  /** @internal */
1339
1335
  public ackChange(serializedInterval: ISerializedInterval, local: boolean, op: ISequencedDocumentMessage) {
1340
1336
  if (!this.attached) {
@@ -1421,6 +1417,10 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1421
1417
  serializedInterval: ISerializedInterval,
1422
1418
  localSeq: number,
1423
1419
  ) {
1420
+ if (!this.client) {
1421
+ // If there's no associated mergeTree client, the originally submitted op is still correct.
1422
+ return serializedInterval;
1423
+ }
1424
1424
  if (!this.attached) {
1425
1425
  throw new LoggingError("attachSequence must be called");
1426
1426
  }
@@ -1446,15 +1446,15 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1446
1446
  return rebased;
1447
1447
  }
1448
1448
 
1449
- private getSlideToSegment(lref: LocalReference) {
1450
- const segoff = { segment: lref.segment, offset: lref.offset };
1449
+ private getSlideToSegment(lref: LocalReferencePosition) {
1450
+ const segoff = { segment: lref.getSegment(), offset: lref.getOffset() };
1451
1451
  const newSegoff = this.client.getSlideToSegment(segoff);
1452
1452
  const value: { segment: ISegment | undefined; offset: number | undefined; } | undefined
1453
1453
  = (segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset) ? undefined : newSegoff;
1454
1454
  return value;
1455
1455
  }
1456
1456
 
1457
- private setSlideOnRemove(lref: LocalReference) {
1457
+ private setSlideOnRemove(lref: LocalReferencePosition) {
1458
1458
  let refType = lref.refType;
1459
1459
  refType = refType & ~ReferenceType.StayOnRemove;
1460
1460
  refType = refType | ReferenceType.SlideOnRemove;
@@ -1462,7 +1462,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1462
1462
  }
1463
1463
 
1464
1464
  private ackInterval(interval: TInterval, op: ISequencedDocumentMessage) {
1465
- // in current usage, interval is always a SequenceInterval
1465
+ // Only SequenceIntervals need potential sliding
1466
1466
  if (!(interval instanceof SequenceInterval)) {
1467
1467
  return;
1468
1468
  }
@@ -1493,7 +1493,7 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1493
1493
  if (needsStartUpdate || needsEndUpdate) {
1494
1494
  // In this case, where we change the start or end of an interval,
1495
1495
  // it is necessary to remove and re-add the interval listeners.
1496
- // This ensures that the correct listeners are added to the ReferencePosition.
1496
+ // This ensures that the correct listeners are added to the LocalReferencePosition.
1497
1497
  this.localCollection.removeExistingInterval(interval);
1498
1498
 
1499
1499
  if (needsStartUpdate) {
@@ -1516,14 +1516,6 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1516
1516
  }
1517
1517
  }
1518
1518
 
1519
- /** @deprecated - use ackAdd */
1520
- public addInternal(
1521
- serializedInterval: ISerializedInterval,
1522
- local: boolean,
1523
- op: ISequencedDocumentMessage) {
1524
- return this.ackAdd(serializedInterval, local, op);
1525
- }
1526
-
1527
1519
  /** @internal */
1528
1520
  public ackAdd(
1529
1521
  serializedInterval: ISerializedInterval,
@@ -1562,14 +1554,6 @@ export class IntervalCollection<TInterval extends ISerializableInterval>
1562
1554
  return interval;
1563
1555
  }
1564
1556
 
1565
- /** @deprecated - use ackDelete */
1566
- public deleteInterval(
1567
- serializedInterval: ISerializedInterval,
1568
- local: boolean,
1569
- op: ISequencedDocumentMessage): void {
1570
- return this.ackDelete(serializedInterval, local, op);
1571
- }
1572
-
1573
1557
  /** @internal */
1574
1558
  public ackDelete(
1575
1559
  serializedInterval: ISerializedInterval,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/sequence";
9
- export const pkgVersion = "1.2.1";
9
+ export const pkgVersion = "2.0.0-internal.1.0.0";
package/src/sequence.ts CHANGED
@@ -29,7 +29,6 @@ import {
29
29
  IRelativePosition,
30
30
  ISegment,
31
31
  ISegmentAction,
32
- LocalReference,
33
32
  LocalReferencePosition,
34
33
  matchProperties,
35
34
  MergeTreeDeltaType,
@@ -298,20 +297,6 @@ export abstract class SharedSegmentSequence<T extends ISegment>
298
297
  return this.client.getRangeExtentsOfPosition(pos);
299
298
  }
300
299
 
301
- /**
302
- * @deprecated - use createLocalReferencePosition
303
- */
304
- public createPositionReference(
305
- segment: T,
306
- offset: number,
307
- refType: ReferenceType): LocalReference {
308
- const lref = new LocalReference(this.client, segment, offset, refType);
309
- if (refType !== ReferenceType.Transient) {
310
- this.addLocalReference(lref);
311
- }
312
- return lref;
313
- }
314
-
315
300
  public createLocalReferencePosition(
316
301
  segment: T,
317
302
  offset: number,
@@ -324,13 +309,6 @@ export abstract class SharedSegmentSequence<T extends ISegment>
324
309
  properties);
325
310
  }
326
311
 
327
- /**
328
- * @deprecated - use localReferencePositionToPosition
329
- */
330
- public localRefToPos(localRef: LocalReference) {
331
- return this.client.localReferencePositionToPosition(localRef);
332
- }
333
-
334
312
  public localReferencePositionToPosition(lref: ReferencePosition): number {
335
313
  return this.client.localReferencePositionToPosition(lref);
336
314
  }
@@ -377,20 +355,6 @@ export abstract class SharedSegmentSequence<T extends ISegment>
377
355
  }
378
356
  }
379
357
 
380
- /**
381
- * @deprecated - use createLocalReferencePosition
382
- */
383
- public addLocalReference(lref: LocalReference) {
384
- return this.client.addLocalReference(lref);
385
- }
386
-
387
- /**
388
- * @deprecated - use removeLocalReferencePosition
389
- */
390
- public removeLocalReference(lref: LocalReference) {
391
- return this.client.removeLocalReferencePosition(lref);
392
- }
393
-
394
358
  public removeLocalReferencePosition(lref: LocalReferencePosition) {
395
359
  return this.client.removeLocalReferencePosition(lref);
396
360
  }
@@ -424,6 +388,10 @@ export abstract class SharedSegmentSequence<T extends ISegment>
424
388
  return this.client.walkSegments<TClientData>(handler, start, end, accum, splitRange);
425
389
  }
426
390
 
391
+ /**
392
+ * @deprecated for internal use only. public export will be removed.
393
+ * @internal
394
+ */
427
395
  public getStackContext(startPos: number, rangeLabels: string[]): RangeStackMap {
428
396
  return this.client.getStackContext(startPos, rangeLabels);
429
397
  }
@@ -25,12 +25,6 @@ import {
25
25
  * They will not take into any future modifications performed to the underlying sequence and merge tree.
26
26
  */
27
27
  export abstract class SequenceEvent<TOperation extends MergeTreeDeltaOperationTypes = MergeTreeDeltaOperationTypes> {
28
- /**
29
- * @deprecated - Events no longer fire when the change they correspond to had no impact (e.g. a remote delete
30
- * event for a range that had already been deleted locally).
31
- * Clients can therefore assume this property is false.
32
- */
33
- public readonly isEmpty: boolean;
34
28
  public readonly deltaOperation: TOperation;
35
29
  private readonly sortedRanges: Lazy<SortedSegmentSet<ISequenceDeltaRange<TOperation>>>;
36
30
  private readonly pFirst: Lazy<ISequenceDeltaRange<TOperation>>;
@@ -41,7 +35,6 @@ export abstract class SequenceEvent<TOperation extends MergeTreeDeltaOperationTy
41
35
  private readonly mergeTreeClient: Client,
42
36
  ) {
43
37
  assert(deltaArgs.deltaSegments.length > 0, 0x2d8 /* "Empty change event should not be emitted." */);
44
- this.isEmpty = false;
45
38
  this.deltaOperation = deltaArgs.operation;
46
39
 
47
40
  this.sortedRanges = new Lazy<SortedSegmentSet<ISequenceDeltaRange<TOperation>>>(
@@ -7,10 +7,10 @@ import {
7
7
  ICombiningOp,
8
8
  IMergeTreeInsertMsg,
9
9
  IMergeTreeRemoveMsg,
10
+ IMergeTreeTextHelper,
10
11
  IRelativePosition,
11
12
  ISegment,
12
13
  Marker,
13
- MergeTreeTextHelper,
14
14
  PropertySet,
15
15
  ReferencePosition,
16
16
  ReferenceType,
@@ -81,7 +81,7 @@ export class SharedString extends SharedSegmentSequence<SharedStringSegment> imp
81
81
  return this;
82
82
  }
83
83
 
84
- private readonly mergeTreeTextHelper: MergeTreeTextHelper;
84
+ private readonly mergeTreeTextHelper: IMergeTreeTextHelper;
85
85
 
86
86
  constructor(document: IFluidDataStoreRuntime, public id: string, attributes: IChannelAttributes) {
87
87
  super(document, id, attributes, SharedStringFactory.segmentFromSpec);
@@ -223,6 +223,9 @@ export class SharedString extends SharedSegmentSequence<SharedStringSegment> imp
223
223
  return this.client.findTile(startPos, tileLabel, preceding);
224
224
  }
225
225
 
226
+ /**
227
+ * @deprecated - use the free function `getTextAndMarkers` exported by this package instead.
228
+ */
226
229
  public getTextAndMarkers(label: string) {
227
230
  const segmentWindow = this.client.getCollabWindow();
228
231
  return this.mergeTreeTextHelper.getTextAndMarkers(segmentWindow.currentSeq, segmentWindow.clientId, label);
@@ -242,14 +245,16 @@ export class SharedString extends SharedSegmentSequence<SharedStringSegment> imp
242
245
  /**
243
246
  * Adds spaces for markers and handles, so that position calculations account for them.
244
247
  */
245
- public getTextWithPlaceholders() {
248
+ public getTextWithPlaceholders(start?: number, end?: number) {
246
249
  const segmentWindow = this.client.getCollabWindow();
247
- return this.mergeTreeTextHelper.getText(segmentWindow.currentSeq, segmentWindow.clientId, " ");
250
+ return this.mergeTreeTextHelper.getText(segmentWindow.currentSeq, segmentWindow.clientId, " ", start, end);
248
251
  }
249
252
 
253
+ /**
254
+ * @deprecated - use `getTextWithPlaceholders` instead.
255
+ */
250
256
  public getTextRangeWithPlaceholders(start: number, end: number) {
251
- const segmentWindow = this.client.getCollabWindow();
252
- return this.mergeTreeTextHelper.getText(segmentWindow.currentSeq, segmentWindow.clientId, " ", start, end);
257
+ return this.getTextWithPlaceholders(start, end);
253
258
  }
254
259
 
255
260
  public getTextRangeWithMarkers(start: number, end: number) {
@@ -260,4 +265,37 @@ export class SharedString extends SharedSegmentSequence<SharedStringSegment> imp
260
265
  public getMarkerFromId(id: string): ISegment {
261
266
  return this.client.getMarkerFromId(id);
262
267
  }
268
+
269
+ /**
270
+ * Revert an op
271
+ */
272
+ protected rollback(content: any, localOpMetadata: unknown): void {
273
+ if (this.client.rollback !== undefined) {
274
+ this.client.rollback(content, localOpMetadata);
275
+ } else {
276
+ super.rollback(content, localOpMetadata);
277
+ }
278
+ }
279
+ }
280
+
281
+ /**
282
+ * Splits the text into regions ending with markers with the given `label`.
283
+ * @param sharedString - String to retrieve text and markers from
284
+ * @param label - label to split on
285
+ * @returns Two parallel lists of text and markers, split by markers with the provided `label`.
286
+ *
287
+ * For example:
288
+ * ```typescript
289
+ * // Say sharedstring has contents "hello<paragraph marker 1>world<paragraph marker 2>missing".
290
+ * const { parallelText, parallelMarkers } = getTextAndMarkers(sharedString, "paragraph");
291
+ * // parallelText === ["hello", "world"]
292
+ * // parallelMarkers === [<paragraph marker 1 object>, <paragraph marker 2 object>]
293
+ * // Note parallelText does not include "missing".
294
+ * ```
295
+ */
296
+ export function getTextAndMarkers(sharedString: SharedString, label: string): {
297
+ parallelText: string[];
298
+ parallelMarkers: Marker[];
299
+ } {
300
+ return sharedString.getTextAndMarkers(label);
263
301
  }