@fluidframework/sequence 2.90.0-378676 → 2.90.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 (84) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/api-report/sequence.legacy.beta.api.md +1 -1
  3. package/dist/intervalCollection.d.ts +3 -2
  4. package/dist/intervalCollection.d.ts.map +1 -1
  5. package/dist/intervalCollection.js +5 -5
  6. package/dist/intervalCollection.js.map +1 -1
  7. package/dist/intervalIndex/endpointInRangeIndex.d.ts +3 -3
  8. package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  9. package/dist/intervalIndex/endpointInRangeIndex.js +5 -6
  10. package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
  11. package/dist/intervalIndex/endpointIndex.d.ts +3 -3
  12. package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
  13. package/dist/intervalIndex/endpointIndex.js +5 -6
  14. package/dist/intervalIndex/endpointIndex.js.map +1 -1
  15. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +8 -7
  16. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  17. package/dist/intervalIndex/overlappingIntervalsIndex.js +5 -6
  18. package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  19. package/dist/intervalIndex/startpointInRangeIndex.d.ts +3 -3
  20. package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  21. package/dist/intervalIndex/startpointInRangeIndex.js +5 -6
  22. package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
  23. package/dist/intervals/index.d.ts +1 -1
  24. package/dist/intervals/index.d.ts.map +1 -1
  25. package/dist/intervals/index.js +4 -2
  26. package/dist/intervals/index.js.map +1 -1
  27. package/dist/intervals/sequenceInterval.d.ts +60 -35
  28. package/dist/intervals/sequenceInterval.d.ts.map +1 -1
  29. package/dist/intervals/sequenceInterval.js +166 -102
  30. package/dist/intervals/sequenceInterval.js.map +1 -1
  31. package/dist/packageVersion.d.ts +1 -1
  32. package/dist/packageVersion.d.ts.map +1 -1
  33. package/dist/packageVersion.js +1 -1
  34. package/dist/packageVersion.js.map +1 -1
  35. package/dist/sequence.d.ts +3 -6
  36. package/dist/sequence.d.ts.map +1 -1
  37. package/dist/sequence.js +2 -5
  38. package/dist/sequence.js.map +1 -1
  39. package/lib/intervalCollection.d.ts +3 -2
  40. package/lib/intervalCollection.d.ts.map +1 -1
  41. package/lib/intervalCollection.js +5 -5
  42. package/lib/intervalCollection.js.map +1 -1
  43. package/lib/intervalIndex/endpointInRangeIndex.d.ts +3 -3
  44. package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  45. package/lib/intervalIndex/endpointInRangeIndex.js +6 -7
  46. package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
  47. package/lib/intervalIndex/endpointIndex.d.ts +3 -3
  48. package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
  49. package/lib/intervalIndex/endpointIndex.js +6 -7
  50. package/lib/intervalIndex/endpointIndex.js.map +1 -1
  51. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +8 -7
  52. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  53. package/lib/intervalIndex/overlappingIntervalsIndex.js +7 -8
  54. package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  55. package/lib/intervalIndex/startpointInRangeIndex.d.ts +3 -3
  56. package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  57. package/lib/intervalIndex/startpointInRangeIndex.js +6 -7
  58. package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
  59. package/lib/intervals/index.d.ts +1 -1
  60. package/lib/intervals/index.d.ts.map +1 -1
  61. package/lib/intervals/index.js +1 -1
  62. package/lib/intervals/index.js.map +1 -1
  63. package/lib/intervals/sequenceInterval.d.ts +60 -35
  64. package/lib/intervals/sequenceInterval.d.ts.map +1 -1
  65. package/lib/intervals/sequenceInterval.js +162 -100
  66. package/lib/intervals/sequenceInterval.js.map +1 -1
  67. package/lib/packageVersion.d.ts +1 -1
  68. package/lib/packageVersion.d.ts.map +1 -1
  69. package/lib/packageVersion.js +1 -1
  70. package/lib/packageVersion.js.map +1 -1
  71. package/lib/sequence.d.ts +3 -6
  72. package/lib/sequence.d.ts.map +1 -1
  73. package/lib/sequence.js +2 -5
  74. package/lib/sequence.js.map +1 -1
  75. package/package.json +20 -20
  76. package/src/intervalCollection.ts +6 -3
  77. package/src/intervalIndex/endpointInRangeIndex.ts +11 -7
  78. package/src/intervalIndex/endpointIndex.ts +7 -7
  79. package/src/intervalIndex/overlappingIntervalsIndex.ts +18 -25
  80. package/src/intervalIndex/startpointInRangeIndex.ts +11 -7
  81. package/src/intervals/index.ts +3 -1
  82. package/src/intervals/sequenceInterval.ts +249 -124
  83. package/src/packageVersion.ts +1 -1
  84. package/src/sequence.ts +8 -11
@@ -3,18 +3,15 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import {
7
- Client,
8
- SequencePlace,
9
- endpointPosAndSide,
10
- } from "@fluidframework/merge-tree/internal";
6
+ import { SequencePlace, endpointPosAndSide } from "@fluidframework/merge-tree/internal";
11
7
 
12
8
  import { IntervalNode, IntervalTree } from "../intervalTree.js";
13
9
  import {
14
10
  SequenceInterval,
15
- SequenceIntervalClass,
16
- createTransientInterval,
11
+ BaseSequenceInterval,
12
+ createTransientIntervalFromSequence,
17
13
  } from "../intervals/index.js";
14
+ import type { ISharedSegmentSequence } from "../sequence.js";
18
15
  import { ISharedString } from "../sharedString.js";
19
16
 
20
17
  import type { SequenceIntervalIndex } from "./intervalIndex.js";
@@ -41,12 +38,9 @@ export interface ISequenceOverlappingIntervalsIndex extends SequenceIntervalInde
41
38
  }
42
39
 
43
40
  export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsIndex {
44
- protected readonly intervalTree = new IntervalTree<SequenceIntervalClass>();
45
- protected readonly client: Client;
41
+ protected readonly intervalTree = new IntervalTree<BaseSequenceInterval>();
46
42
 
47
- constructor(client: Client) {
48
- this.client = client;
49
- }
43
+ constructor(protected readonly sequence: ISharedSegmentSequence<any>) {}
50
44
 
51
45
  public map(fn: (interval: SequenceInterval) => void) {
52
46
  this.intervalTree.map(fn);
@@ -69,7 +63,7 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
69
63
  if (start === undefined && end === undefined) {
70
64
  // No start/end provided. Gather the whole tree in the specified order.
71
65
  if (iteratesForward) {
72
- this.intervalTree.map((interval: SequenceIntervalClass) => {
66
+ this.intervalTree.map((interval: SequenceInterval) => {
73
67
  results.push(interval);
74
68
  });
75
69
  } else {
@@ -78,23 +72,23 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
78
72
  });
79
73
  }
80
74
  } else {
81
- const transientInterval: SequenceIntervalClass = createTransientInterval(
75
+ const transientInterval: BaseSequenceInterval = createTransientIntervalFromSequence(
82
76
  start ?? "start",
83
77
  end ?? "end",
84
- this.client,
78
+ this.sequence,
85
79
  );
86
80
 
87
81
  if (start === undefined) {
88
82
  // Only end position provided. Since the tree is not sorted by end position,
89
83
  // walk the whole tree in the specified order, gathering intervals that match the end.
90
84
  if (iteratesForward) {
91
- this.intervalTree.map((interval: SequenceIntervalClass) => {
85
+ this.intervalTree.map((interval: SequenceInterval) => {
92
86
  if (transientInterval.compareEnd(interval) === 0) {
93
87
  results.push(interval);
94
88
  }
95
89
  });
96
90
  } else {
97
- this.intervalTree.mapBackward((interval: SequenceIntervalClass) => {
91
+ this.intervalTree.mapBackward((interval: SequenceInterval) => {
98
92
  if (transientInterval.compareEnd(interval) === 0) {
99
93
  results.push(interval);
100
94
  }
@@ -105,15 +99,15 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
105
99
  // this start position.
106
100
  const compareFn =
107
101
  end === undefined
108
- ? (node: IntervalNode<SequenceIntervalClass>) => {
102
+ ? (node: IntervalNode<BaseSequenceInterval>) => {
109
103
  return transientInterval.compareStart(node.key);
110
104
  }
111
- : (node: IntervalNode<SequenceIntervalClass>) => {
105
+ : (node: IntervalNode<BaseSequenceInterval>) => {
112
106
  return transientInterval.compare(node.key);
113
107
  };
114
108
  const continueLeftFn = (cmpResult: number) => cmpResult <= 0;
115
109
  const continueRightFn = (cmpResult: number) => cmpResult >= 0;
116
- const actionFn = (node: IntervalNode<SequenceIntervalClass>) => {
110
+ const actionFn = (node: IntervalNode<BaseSequenceInterval>) => {
117
111
  results.push(node.key);
118
112
  };
119
113
 
@@ -152,17 +146,17 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
152
146
  ) {
153
147
  return [];
154
148
  }
155
- const transientInterval = createTransientInterval(start, end, this.client);
149
+ const transientInterval = createTransientIntervalFromSequence(start, end, this.sequence);
156
150
 
157
151
  const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
158
152
  return overlappingIntervalNodes.map((node) => node.key);
159
153
  }
160
154
 
161
- public remove(interval: SequenceIntervalClass) {
155
+ public remove(interval: BaseSequenceInterval) {
162
156
  this.intervalTree.removeExisting(interval);
163
157
  }
164
158
 
165
- public add(interval: SequenceIntervalClass) {
159
+ public add(interval: BaseSequenceInterval) {
166
160
  this.intervalTree.put(interval);
167
161
  }
168
162
  }
@@ -175,6 +169,5 @@ export class OverlappingIntervalsIndex implements ISequenceOverlappingIntervalsI
175
169
  export function createOverlappingIntervalsIndex(
176
170
  sharedString: ISharedString,
177
171
  ): ISequenceOverlappingIntervalsIndex {
178
- const client = (sharedString as unknown as { client: Client }).client;
179
- return new OverlappingIntervalsIndex(client);
172
+ return new OverlappingIntervalsIndex(sharedString);
180
173
  }
@@ -3,9 +3,10 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { Client, PropertyAction, RedBlackTree } from "@fluidframework/merge-tree/internal";
6
+ import { PropertyAction, RedBlackTree } from "@fluidframework/merge-tree/internal";
7
7
 
8
- import { SequenceInterval, createTransientInterval } from "../intervals/index.js";
8
+ import { SequenceInterval, createTransientIntervalFromSequence } from "../intervals/index.js";
9
+ import type { ISharedSegmentSequence } from "../sequence.js";
9
10
  import { ISharedString } from "../sharedString.js";
10
11
 
11
12
  import type { SequenceIntervalIndex } from "./intervalIndex.js";
@@ -31,7 +32,7 @@ export interface IStartpointInRangeIndex extends SequenceIntervalIndex {
31
32
  export class StartpointInRangeIndex implements IStartpointInRangeIndex {
32
33
  private readonly intervalTree;
33
34
 
34
- constructor(private readonly client: Client) {
35
+ constructor(private readonly sequence: ISharedSegmentSequence<any>) {
35
36
  this.intervalTree = new RedBlackTree<SequenceInterval, SequenceInterval>(
36
37
  (a: SequenceInterval, b: SequenceInterval) => {
37
38
  const compareStartsResult = a.compareStart(b);
@@ -74,9 +75,13 @@ export class StartpointInRangeIndex implements IStartpointInRangeIndex {
74
75
  return true;
75
76
  };
76
77
 
77
- const transientStartInterval = createTransientInterval(start, start, this.client);
78
+ const transientStartInterval = createTransientIntervalFromSequence(
79
+ start,
80
+ start,
81
+ this.sequence,
82
+ );
78
83
 
79
- const transientEndInterval = createTransientInterval(end, end, this.client);
84
+ const transientEndInterval = createTransientIntervalFromSequence(end, end, this.sequence);
80
85
 
81
86
  // Add comparison overrides to the transient intervals
82
87
  (transientStartInterval as Partial<HasComparisonOverride>)[forceCompare] = -1;
@@ -94,6 +99,5 @@ export class StartpointInRangeIndex implements IStartpointInRangeIndex {
94
99
  export function createStartpointInRangeIndex(
95
100
  sharedString: ISharedString,
96
101
  ): IStartpointInRangeIndex {
97
- const client = (sharedString as unknown as { client: Client }).client;
98
- return new StartpointInRangeIndex(client);
102
+ return new StartpointInRangeIndex(sharedString);
99
103
  }
@@ -19,8 +19,10 @@ export {
19
19
  export {
20
20
  SequenceInterval,
21
21
  SequenceIntervalClass,
22
+ BaseSequenceInterval,
22
23
  createSequenceInterval,
23
24
  createPositionReferenceFromSegoff,
24
- createTransientInterval,
25
+ createTransientIntervalFromSequence,
26
+ resolvePositionRef,
25
27
  getSerializedProperties,
26
28
  } from "./sequenceInterval.js";
@@ -35,6 +35,8 @@ import {
35
35
  import { LoggingError, UsageError } from "@fluidframework/telemetry-utils/internal";
36
36
  import { v4 as uuid } from "uuid";
37
37
 
38
+ import type { ISharedSegmentSequence } from "../sequence.js";
39
+
38
40
  import {
39
41
  ISerializableInterval,
40
42
  ISerializedInterval,
@@ -182,8 +184,148 @@ export interface SequenceInterval extends IInterval {
182
184
  getIntervalId(): string;
183
185
  }
184
186
 
187
+ /**
188
+ * Lightweight interval for index queries (overlap, comparison).
189
+ * Has no Client dependency; cannot serialize or be disposed.
190
+ */
191
+ export class BaseSequenceInterval implements SequenceInterval, ISerializableInterval {
192
+ readonly #id: string;
193
+ readonly #properties: PropertySet = createMap<any>();
194
+
195
+ constructor(
196
+ id: string,
197
+ /**
198
+ * Start endpoint of this interval.
199
+ * @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
200
+ */
201
+ public start: LocalReferencePosition,
202
+ /**
203
+ * End endpoint of this interval.
204
+ * @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
205
+ */
206
+ public end: LocalReferencePosition,
207
+ public intervalType: IntervalType,
208
+ public readonly startSide: Side = Side.Before,
209
+ public readonly endSide: Side = Side.Before,
210
+ ) {
211
+ this.#id = id;
212
+ }
213
+
214
+ public get properties(): Readonly<PropertySet> {
215
+ return this.#properties;
216
+ }
217
+
218
+ /***/
219
+ public get stickiness(): IntervalStickiness {
220
+ this.verifyNotDispose();
221
+
222
+ const startSegment: ISegmentInternal | undefined = this.start.getSegment();
223
+ const endSegment: ISegmentInternal | undefined = this.end.getSegment();
224
+ return computeStickinessFromSide(
225
+ startSegment?.endpointType,
226
+ this.startSide,
227
+ endSegment?.endpointType,
228
+ this.endSide,
229
+ );
230
+ }
231
+
232
+ /**
233
+ * {@inheritDoc ISerializableInterval.getIntervalId}
234
+ */
235
+ public getIntervalId(): string {
236
+ return this.#id;
237
+ }
238
+
239
+ /**
240
+ * {@inheritDoc IInterval.compare}
241
+ */
242
+ public compare(b: SequenceInterval) {
243
+ const startResult = this.compareStart(b);
244
+ if (startResult === 0) {
245
+ const endResult = this.compareEnd(b);
246
+ if (endResult === 0) {
247
+ const thisId = this.getIntervalId();
248
+ if (thisId) {
249
+ const bId = b.getIntervalId();
250
+ if (bId) {
251
+ return thisId > bId ? 1 : thisId < bId ? -1 : 0;
252
+ }
253
+ return 0;
254
+ }
255
+ return 0;
256
+ } else {
257
+ return endResult;
258
+ }
259
+ } else {
260
+ return startResult;
261
+ }
262
+ }
263
+
264
+ /**
265
+ * {@inheritDoc IInterval.compareStart}
266
+ */
267
+ public compareStart(b: SequenceInterval) {
268
+ this.verifyNotDispose();
269
+
270
+ const dist = compareReferencePositions(this.start, b.start);
271
+
272
+ if (dist === 0) {
273
+ return compareSides(this.startSide, b.startSide);
274
+ }
275
+
276
+ return dist;
277
+ }
278
+
279
+ /**
280
+ * {@inheritDoc IInterval.compareEnd}
281
+ */
282
+ public compareEnd(b: SequenceInterval): number {
283
+ this.verifyNotDispose();
284
+
285
+ const dist = compareReferencePositions(this.end, b.end);
286
+
287
+ if (dist === 0) {
288
+ return compareSides(b.endSide, this.endSide);
289
+ }
290
+
291
+ return dist;
292
+ }
293
+
294
+ /**
295
+ * {@inheritDoc IInterval.overlaps}
296
+ */
297
+ public overlaps(b: SequenceInterval) {
298
+ this.verifyNotDispose();
299
+
300
+ const result =
301
+ compareReferencePositions(this.start, b.end) <= 0 &&
302
+ compareReferencePositions(this.end, b.start) >= 0;
303
+ return result;
304
+ }
305
+
306
+ /**
307
+ * Whether this interval overlaps the provided numerical positions.
308
+ */
309
+ public overlapsPos(_bstart: number, _bend: number): boolean {
310
+ assert(false, 0xcd7 /* overlapsPos not supported on BaseSequenceInterval */);
311
+ }
312
+
313
+ public clone(): BaseSequenceInterval {
314
+ assert(false, 0xcd8 /* clone not supported on BaseSequenceInterval */);
315
+ }
316
+
317
+ public union(_b: BaseSequenceInterval): BaseSequenceInterval {
318
+ assert(false, 0xcd9 /* union not supported on BaseSequenceInterval */);
319
+ }
320
+
321
+ protected verifyNotDispose(): void {
322
+ // No-op: transient intervals are not disposable.
323
+ }
324
+ }
325
+
185
326
  export class SequenceIntervalClass
186
- implements SequenceInterval, ISerializableInterval, IDisposable
327
+ extends BaseSequenceInterval
328
+ implements ISerializableInterval, IDisposable
187
329
  {
188
330
  readonly #props: {
189
331
  propertyManager?: PropertiesManager;
@@ -193,7 +335,7 @@ export class SequenceIntervalClass
193
335
  /**
194
336
  * {@inheritDoc ISerializableInterval.properties}
195
337
  */
196
- public get properties(): Readonly<PropertySet> {
338
+ public override get properties(): Readonly<PropertySet> {
197
339
  this.verifyNotDispose();
198
340
  return this.#props.properties;
199
341
  }
@@ -220,39 +362,18 @@ export class SequenceIntervalClass
220
362
  }
221
363
  }
222
364
 
223
- /***/
224
- public get stickiness(): IntervalStickiness {
225
- this.verifyNotDispose();
226
-
227
- const startSegment: ISegmentInternal | undefined = this.start.getSegment();
228
- const endSegment: ISegmentInternal | undefined = this.end.getSegment();
229
- return computeStickinessFromSide(
230
- startSegment?.endpointType,
231
- this.startSide,
232
- endSegment?.endpointType,
233
- this.endSide,
234
- );
235
- }
236
-
237
365
  constructor(
238
366
  private readonly client: Client,
239
- private readonly id: string,
367
+ id: string,
240
368
  private readonly label: string,
241
- /**
242
- * Start endpoint of this interval.
243
- * @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
244
- */
245
- public start: LocalReferencePosition,
246
- /**
247
- * End endpoint of this interval.
248
- * @remarks This endpoint can be resolved into a character position using the SharedString it's a part of.
249
- */
250
- public end: LocalReferencePosition,
251
- public intervalType: IntervalType,
369
+ start: LocalReferencePosition,
370
+ end: LocalReferencePosition,
371
+ intervalType: IntervalType,
252
372
  props?: PropertySet,
253
- public readonly startSide: Side = Side.Before,
254
- public readonly endSide: Side = Side.Before,
373
+ startSide: Side = Side.Before,
374
+ endSide: Side = Side.Before,
255
375
  ) {
376
+ super(id, start, end, intervalType, startSide, endSide);
256
377
  if (props) {
257
378
  this.#props.properties = addProperties(this.#props.properties, props);
258
379
  }
@@ -270,7 +391,7 @@ export class SequenceIntervalClass
270
391
  this.#props.propertyManager = undefined;
271
392
  }
272
393
 
273
- private verifyNotDispose() {
394
+ protected override verifyNotDispose() {
274
395
  if (this.#disposed) {
275
396
  throw new LoggingError("Invalid interval access after dispose");
276
397
  }
@@ -350,7 +471,7 @@ export class SequenceIntervalClass
350
471
  endSide: includeEndpoints ? this.endSide : undefined,
351
472
  properties: {
352
473
  ...props,
353
- [reservedIntervalIdKey]: this.id,
474
+ [reservedIntervalIdKey]: this.getIntervalId(),
354
475
  [reservedRangeLabelsKey]: [this.label],
355
476
  },
356
477
  } satisfies SerializedIntervalDelta;
@@ -364,7 +485,7 @@ export class SequenceIntervalClass
364
485
 
365
486
  return new SequenceIntervalClass(
366
487
  this.client,
367
- this.id,
488
+ this.getIntervalId(),
368
489
  this.label,
369
490
  this.start,
370
491
  this.end,
@@ -375,80 +496,6 @@ export class SequenceIntervalClass
375
496
  );
376
497
  }
377
498
 
378
- /**
379
- * {@inheritDoc IInterval.compare}
380
- */
381
- public compare(b: SequenceInterval) {
382
- const startResult = this.compareStart(b);
383
- if (startResult === 0) {
384
- const endResult = this.compareEnd(b);
385
- if (endResult === 0) {
386
- const thisId = this.getIntervalId();
387
- if (thisId) {
388
- const bId = b.getIntervalId();
389
- if (bId) {
390
- return thisId > bId ? 1 : thisId < bId ? -1 : 0;
391
- }
392
- return 0;
393
- }
394
- return 0;
395
- } else {
396
- return endResult;
397
- }
398
- } else {
399
- return startResult;
400
- }
401
- }
402
-
403
- /**
404
- * {@inheritDoc IInterval.compareStart}
405
- */
406
- public compareStart(b: SequenceInterval) {
407
- this.verifyNotDispose();
408
-
409
- const dist = compareReferencePositions(this.start, b.start);
410
-
411
- if (dist === 0) {
412
- return compareSides(this.startSide, b.startSide);
413
- }
414
-
415
- return dist;
416
- }
417
-
418
- /**
419
- * {@inheritDoc IInterval.compareEnd}
420
- */
421
- public compareEnd(b: SequenceInterval): number {
422
- this.verifyNotDispose();
423
-
424
- const dist = compareReferencePositions(this.end, b.end);
425
-
426
- if (dist === 0) {
427
- return compareSides(b.endSide, this.endSide);
428
- }
429
-
430
- return dist;
431
- }
432
-
433
- /**
434
- * {@inheritDoc IInterval.overlaps}
435
- */
436
- public overlaps(b: SequenceInterval) {
437
- this.verifyNotDispose();
438
-
439
- const result =
440
- compareReferencePositions(this.start, b.end) <= 0 &&
441
- compareReferencePositions(this.end, b.start) >= 0;
442
- return result;
443
- }
444
-
445
- /**
446
- * {@inheritDoc ISerializableInterval.getIntervalId}
447
- */
448
- public getIntervalId(): string {
449
- return this.id;
450
- }
451
-
452
499
  /**
453
500
  * {@inheritDoc IInterval.union}
454
501
  */
@@ -490,7 +537,7 @@ export class SequenceIntervalClass
490
537
  /**
491
538
  * Whether this interval overlaps the provided numerical positions.
492
539
  */
493
- public overlapsPos(bstart: number, bend: number) {
540
+ public override overlapsPos(bstart: number, bend: number) {
494
541
  this.verifyNotDispose();
495
542
 
496
543
  const startPos = this.client.localReferencePositionToPosition(this.start);
@@ -602,7 +649,7 @@ export class SequenceIntervalClass
602
649
 
603
650
  const newInterval = new SequenceIntervalClass(
604
651
  this.client,
605
- this.id,
652
+ this.getIntervalId(),
606
653
  this.label,
607
654
  startRef,
608
655
  endRef,
@@ -697,6 +744,41 @@ export function createPositionReferenceFromSegoff({
697
744
  return createDetachedLocalReferencePosition(slidingPreference, refType);
698
745
  }
699
746
 
747
+ /**
748
+ * Resolves a position to a {@link LocalReferencePosition} using an
749
+ * {@link ISharedSegmentSequence} (no Client or op context needed).
750
+ */
751
+ export function resolvePositionRef(
752
+ sequence: ISharedSegmentSequence<any>,
753
+ pos: number | "start" | "end",
754
+ refType: ReferenceType,
755
+ slidingPreference: SlidingPreference,
756
+ canSlideToEndpoint?: boolean,
757
+ ): LocalReferencePosition {
758
+ if (pos === "start" || pos === "end") {
759
+ return sequence.createLocalReferencePosition(
760
+ pos,
761
+ undefined,
762
+ refType,
763
+ undefined,
764
+ slidingPreference,
765
+ canSlideToEndpoint,
766
+ );
767
+ }
768
+ const segoff = sequence.getContainingSegment(pos);
769
+ if (segoff?.segment !== undefined && segoff?.offset !== undefined) {
770
+ return sequence.createLocalReferencePosition(
771
+ segoff.segment,
772
+ segoff.offset,
773
+ refType,
774
+ undefined,
775
+ slidingPreference,
776
+ canSlideToEndpoint,
777
+ );
778
+ }
779
+ return createDetachedLocalReferencePosition(slidingPreference, refType);
780
+ }
781
+
700
782
  function createPositionReference({
701
783
  client,
702
784
  pos,
@@ -758,18 +840,61 @@ function createPositionReference({
758
840
  });
759
841
  }
760
842
 
761
- export function createTransientInterval(
843
+ /**
844
+ * Creates a transient interval using an `ISharedSegmentSequence` instead of a `Client`.
845
+ * This avoids coupling index classes to merge-tree internals.
846
+ */
847
+ export function createTransientIntervalFromSequence(
762
848
  start: SequencePlace | undefined,
763
849
  end: SequencePlace | undefined,
764
- client: Client,
765
- ) {
766
- return createSequenceInterval(
767
- "transient",
850
+ sequence: ISharedSegmentSequence<any>,
851
+ ): BaseSequenceInterval {
852
+ const { startPos, startSide, endPos, endSide } = endpointPosAndSide(
853
+ start ?? "start",
854
+ end ?? "end",
855
+ );
856
+ assert(
857
+ startPos !== undefined &&
858
+ endPos !== undefined &&
859
+ startSide !== undefined &&
860
+ endSide !== undefined,
861
+ 0xcda /* start and end cannot be undefined because they were not passed in as undefined */,
862
+ );
863
+
864
+ const startSlidingPref = startReferenceSlidingPreference(
865
+ startPos,
866
+ startSide,
867
+ endPos,
868
+ endSide,
869
+ );
870
+ const endSlidingPref = endReferenceSlidingPreference(startPos, startSide, endPos, endSide);
871
+
872
+ const startLref = resolvePositionRef(
873
+ sequence,
874
+ startPos,
875
+ ReferenceType.Transient,
876
+ startSlidingPref,
877
+ );
878
+ const endLref = resolvePositionRef(
879
+ sequence,
880
+ endPos,
881
+ ReferenceType.Transient,
882
+ endSlidingPref,
883
+ );
884
+
885
+ const rangeProp = {
886
+ [reservedRangeLabelsKey]: ["transient"],
887
+ };
888
+ startLref.addProperties(rangeProp);
889
+ endLref.addProperties(rangeProp);
890
+
891
+ return new BaseSequenceInterval(
768
892
  uuid(),
769
- start,
770
- end,
771
- client,
893
+ startLref,
894
+ endLref,
772
895
  IntervalType.Transient,
896
+ startSide,
897
+ endSide,
773
898
  );
774
899
  }
775
900
 
@@ -824,6 +949,13 @@ export function createSequenceInterval(
824
949
  endSide,
825
950
  );
826
951
 
952
+ const endSlidingPreference = endReferenceSlidingPreference(
953
+ startPos,
954
+ startSide,
955
+ endPos,
956
+ endSide,
957
+ );
958
+
827
959
  const startLref = createPositionReference({
828
960
  client,
829
961
  pos: startPos,
@@ -835,13 +967,6 @@ export function createSequenceInterval(
835
967
  rollback,
836
968
  });
837
969
 
838
- const endSlidingPreference = endReferenceSlidingPreference(
839
- startPos,
840
- startSide,
841
- endPos,
842
- endSide,
843
- );
844
-
845
970
  const endLref = createPositionReference({
846
971
  client,
847
972
  pos: endPos,
@@ -6,4 +6,4 @@
6
6
  */
7
7
 
8
8
  export const pkgName = "@fluidframework/sequence";
9
- export const pkgVersion = "2.90.0-378676";
9
+ export const pkgVersion = "2.90.0";