@fluidframework/sequence 2.0.0-internal.6.3.3 → 2.0.0-internal.7.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 (191) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +130 -0
  3. package/dist/defaultMap.d.ts +1 -1
  4. package/dist/defaultMap.d.ts.map +1 -1
  5. package/dist/defaultMap.js +6 -6
  6. package/dist/defaultMap.js.map +1 -1
  7. package/dist/defaultMapInterfaces.d.ts +21 -2
  8. package/dist/defaultMapInterfaces.d.ts.map +1 -1
  9. package/dist/defaultMapInterfaces.js.map +1 -1
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/intervalCollection.d.ts +140 -22
  15. package/dist/intervalCollection.d.ts.map +1 -1
  16. package/dist/intervalCollection.js +146 -49
  17. package/dist/intervalCollection.js.map +1 -1
  18. package/dist/intervalIndex/endpointInRangeIndex.d.ts +13 -3
  19. package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  20. package/dist/intervalIndex/endpointInRangeIndex.js +9 -6
  21. package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -1
  22. package/dist/intervalIndex/endpointIndex.d.ts +13 -2
  23. package/dist/intervalIndex/endpointIndex.d.ts.map +1 -1
  24. package/dist/intervalIndex/endpointIndex.js +7 -5
  25. package/dist/intervalIndex/endpointIndex.js.map +1 -1
  26. package/dist/intervalIndex/idIntervalIndex.js.map +1 -1
  27. package/dist/intervalIndex/index.d.ts +4 -4
  28. package/dist/intervalIndex/index.d.ts.map +1 -1
  29. package/dist/intervalIndex/index.js +5 -1
  30. package/dist/intervalIndex/index.js.map +1 -1
  31. package/dist/intervalIndex/intervalIndex.d.ts +2 -2
  32. package/dist/intervalIndex/intervalIndex.js.map +1 -1
  33. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +8 -6
  34. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  35. package/dist/intervalIndex/overlappingIntervalsIndex.js +11 -4
  36. package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  37. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +2 -2
  38. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
  39. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +3 -1
  40. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
  41. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
  42. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
  43. package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
  44. package/dist/intervalIndex/startpointInRangeIndex.d.ts +13 -3
  45. package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  46. package/dist/intervalIndex/startpointInRangeIndex.js +9 -8
  47. package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -1
  48. package/dist/intervalTree.d.ts +1 -1
  49. package/dist/intervalTree.d.ts.map +1 -1
  50. package/dist/intervals/interval.d.ts +4 -3
  51. package/dist/intervals/interval.d.ts.map +1 -1
  52. package/dist/intervals/interval.js +14 -6
  53. package/dist/intervals/interval.js.map +1 -1
  54. package/dist/intervals/intervalUtils.d.ts +42 -20
  55. package/dist/intervals/intervalUtils.d.ts.map +1 -1
  56. package/dist/intervals/intervalUtils.js +12 -10
  57. package/dist/intervals/intervalUtils.js.map +1 -1
  58. package/dist/intervals/sequenceInterval.d.ts +30 -17
  59. package/dist/intervals/sequenceInterval.d.ts.map +1 -1
  60. package/dist/intervals/sequenceInterval.js +124 -45
  61. package/dist/intervals/sequenceInterval.js.map +1 -1
  62. package/dist/packageVersion.d.ts +1 -1
  63. package/dist/packageVersion.js +1 -1
  64. package/dist/packageVersion.js.map +1 -1
  65. package/dist/revertibles.d.ts +3 -15
  66. package/dist/revertibles.d.ts.map +1 -1
  67. package/dist/revertibles.js +6 -17
  68. package/dist/revertibles.js.map +1 -1
  69. package/dist/sequence.d.ts +3 -2
  70. package/dist/sequence.d.ts.map +1 -1
  71. package/dist/sequence.js +46 -45
  72. package/dist/sequence.js.map +1 -1
  73. package/dist/sequenceDeltaEvent.d.ts +8 -3
  74. package/dist/sequenceDeltaEvent.d.ts.map +1 -1
  75. package/dist/sequenceDeltaEvent.js.map +1 -1
  76. package/dist/sequenceFactory.js +1 -1
  77. package/dist/sequenceFactory.js.map +1 -1
  78. package/dist/sharedIntervalCollection.js +9 -9
  79. package/dist/sharedIntervalCollection.js.map +1 -1
  80. package/dist/sharedSequence.js +6 -6
  81. package/dist/sharedSequence.js.map +1 -1
  82. package/dist/sharedString.d.ts +1 -1
  83. package/dist/sharedString.d.ts.map +1 -1
  84. package/dist/sharedString.js +7 -6
  85. package/dist/sharedString.js.map +1 -1
  86. package/dist/tsdoc-metadata.json +1 -1
  87. package/lib/defaultMap.d.ts +1 -1
  88. package/lib/defaultMap.d.ts.map +1 -1
  89. package/lib/defaultMap.js +6 -6
  90. package/lib/defaultMap.js.map +1 -1
  91. package/lib/defaultMapInterfaces.d.ts +21 -2
  92. package/lib/defaultMapInterfaces.d.ts.map +1 -1
  93. package/lib/defaultMapInterfaces.js.map +1 -1
  94. package/lib/index.d.ts +2 -2
  95. package/lib/index.d.ts.map +1 -1
  96. package/lib/index.js +1 -1
  97. package/lib/index.js.map +1 -1
  98. package/lib/intervalCollection.d.ts +140 -22
  99. package/lib/intervalCollection.d.ts.map +1 -1
  100. package/lib/intervalCollection.js +144 -50
  101. package/lib/intervalCollection.js.map +1 -1
  102. package/lib/intervalIndex/endpointInRangeIndex.d.ts +13 -3
  103. package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -1
  104. package/lib/intervalIndex/endpointInRangeIndex.js +9 -7
  105. package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -1
  106. package/lib/intervalIndex/endpointIndex.d.ts +13 -2
  107. package/lib/intervalIndex/endpointIndex.d.ts.map +1 -1
  108. package/lib/intervalIndex/endpointIndex.js +7 -6
  109. package/lib/intervalIndex/endpointIndex.js.map +1 -1
  110. package/lib/intervalIndex/idIntervalIndex.js.map +1 -1
  111. package/lib/intervalIndex/index.d.ts +4 -4
  112. package/lib/intervalIndex/index.d.ts.map +1 -1
  113. package/lib/intervalIndex/index.js +4 -4
  114. package/lib/intervalIndex/index.js.map +1 -1
  115. package/lib/intervalIndex/intervalIndex.d.ts +2 -2
  116. package/lib/intervalIndex/intervalIndex.js.map +1 -1
  117. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +8 -6
  118. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -1
  119. package/lib/intervalIndex/overlappingIntervalsIndex.js +12 -5
  120. package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -1
  121. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +2 -2
  122. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -1
  123. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +3 -1
  124. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -1
  125. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +1 -1
  126. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -1
  127. package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -1
  128. package/lib/intervalIndex/startpointInRangeIndex.d.ts +13 -3
  129. package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -1
  130. package/lib/intervalIndex/startpointInRangeIndex.js +9 -9
  131. package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -1
  132. package/lib/intervalTree.d.ts +1 -1
  133. package/lib/intervalTree.d.ts.map +1 -1
  134. package/lib/intervals/interval.d.ts +4 -3
  135. package/lib/intervals/interval.d.ts.map +1 -1
  136. package/lib/intervals/interval.js +14 -6
  137. package/lib/intervals/interval.js.map +1 -1
  138. package/lib/intervals/intervalUtils.d.ts +42 -20
  139. package/lib/intervals/intervalUtils.d.ts.map +1 -1
  140. package/lib/intervals/intervalUtils.js +8 -6
  141. package/lib/intervals/intervalUtils.js.map +1 -1
  142. package/lib/intervals/sequenceInterval.d.ts +30 -17
  143. package/lib/intervals/sequenceInterval.d.ts.map +1 -1
  144. package/lib/intervals/sequenceInterval.js +125 -44
  145. package/lib/intervals/sequenceInterval.js.map +1 -1
  146. package/lib/packageVersion.d.ts +1 -1
  147. package/lib/packageVersion.js +1 -1
  148. package/lib/packageVersion.js.map +1 -1
  149. package/lib/revertibles.d.ts +3 -15
  150. package/lib/revertibles.d.ts.map +1 -1
  151. package/lib/revertibles.js +6 -17
  152. package/lib/revertibles.js.map +1 -1
  153. package/lib/sequence.d.ts +3 -2
  154. package/lib/sequence.d.ts.map +1 -1
  155. package/lib/sequence.js +46 -45
  156. package/lib/sequence.js.map +1 -1
  157. package/lib/sequenceDeltaEvent.d.ts +8 -3
  158. package/lib/sequenceDeltaEvent.d.ts.map +1 -1
  159. package/lib/sequenceDeltaEvent.js.map +1 -1
  160. package/lib/sequenceFactory.js +1 -1
  161. package/lib/sequenceFactory.js.map +1 -1
  162. package/lib/sharedIntervalCollection.js +9 -9
  163. package/lib/sharedIntervalCollection.js.map +1 -1
  164. package/lib/sharedSequence.js +6 -6
  165. package/lib/sharedSequence.js.map +1 -1
  166. package/lib/sharedString.d.ts +1 -1
  167. package/lib/sharedString.d.ts.map +1 -1
  168. package/lib/sharedString.js +7 -6
  169. package/lib/sharedString.js.map +1 -1
  170. package/package.json +49 -23
  171. package/src/defaultMapInterfaces.ts +21 -2
  172. package/src/index.ts +4 -1
  173. package/src/intervalCollection.ts +347 -84
  174. package/src/intervalIndex/endpointInRangeIndex.ts +19 -11
  175. package/src/intervalIndex/endpointIndex.ts +16 -9
  176. package/src/intervalIndex/idIntervalIndex.ts +1 -1
  177. package/src/intervalIndex/index.ts +12 -3
  178. package/src/intervalIndex/intervalIndex.ts +2 -2
  179. package/src/intervalIndex/overlappingIntervalsIndex.ts +31 -15
  180. package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +4 -1
  181. package/src/intervalIndex/sequenceIntervalIndexes.ts +1 -1
  182. package/src/intervalIndex/startpointInRangeIndex.ts +19 -17
  183. package/src/intervals/interval.ts +30 -8
  184. package/src/intervals/intervalUtils.ts +51 -28
  185. package/src/intervals/sequenceInterval.ts +197 -49
  186. package/src/packageVersion.ts +1 -1
  187. package/src/revertibles.ts +8 -33
  188. package/src/sequence.ts +5 -2
  189. package/src/sequenceDeltaEvent.ts +11 -3
  190. package/src/sequenceFactory.ts +1 -1
  191. package/src/sharedString.ts +2 -1
@@ -4,8 +4,9 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.LocalIntervalCollection = exports.createIntervalIndex = void 0;
7
+ exports.intervalLocatorFromEndpoint = exports.IntervalCollection = exports.makeOpsMap = exports.IntervalCollectionValueType = exports.SequenceIntervalCollectionValueType = exports.LocalIntervalCollection = exports.createIntervalIndex = exports.computeStickinessFromSide = exports.endpointPosAndSide = exports.sidesFromStickiness = exports.Side = void 0;
8
8
  /* eslint-disable no-bitwise */
9
+ /* eslint-disable import/no-deprecated */
9
10
  const client_utils_1 = require("@fluid-internal/client-utils");
10
11
  const core_utils_1 = require("@fluidframework/core-utils");
11
12
  const merge_tree_1 = require("@fluidframework/merge-tree");
@@ -13,19 +14,39 @@ const telemetry_utils_1 = require("@fluidframework/telemetry-utils");
13
14
  const uuid_1 = require("uuid");
14
15
  const intervals_1 = require("./intervals");
15
16
  const intervalIndex_1 = require("./intervalIndex");
17
+ /**
18
+ * Defines a side relative to a character in a sequence.
19
+ *
20
+ * @remarks See {@link SequencePlace} for additional context on usage.
21
+ */
22
+ var Side;
23
+ (function (Side) {
24
+ Side[Side["Before"] = 0] = "Before";
25
+ Side[Side["After"] = 1] = "After";
26
+ })(Side || (exports.Side = Side = {}));
16
27
  const reservedIntervalIdKey = "intervalId";
28
+ function sidesFromStickiness(stickiness) {
29
+ const startSide = (stickiness & intervals_1.IntervalStickiness.START) !== 0 ? Side.After : Side.Before;
30
+ const endSide = (stickiness & intervals_1.IntervalStickiness.END) !== 0 ? Side.Before : Side.After;
31
+ return { startSide, endSide };
32
+ }
33
+ exports.sidesFromStickiness = sidesFromStickiness;
17
34
  /**
18
35
  * Decompress an interval after loading a summary from JSON. The exact format
19
36
  * of this compression is unspecified and subject to change
20
37
  */
21
38
  function decompressInterval(interval, label) {
39
+ const stickiness = interval[5] ?? intervals_1.IntervalStickiness.END;
40
+ const { startSide, endSide } = sidesFromStickiness(stickiness);
22
41
  return {
23
42
  start: interval[0],
24
43
  end: interval[1],
25
44
  sequenceNumber: interval[2],
26
45
  intervalType: interval[3],
27
46
  properties: { ...interval[4], [merge_tree_1.reservedRangeLabelsKey]: [label] },
28
- stickiness: interval[5],
47
+ stickiness,
48
+ startSide,
49
+ endSide,
29
50
  };
30
51
  }
31
52
  /**
@@ -34,7 +55,7 @@ function decompressInterval(interval, label) {
34
55
  */
35
56
  function compressInterval(interval) {
36
57
  const { start, end, sequenceNumber, intervalType, properties } = interval;
37
- const base = [
58
+ let base = [
38
59
  start,
39
60
  end,
40
61
  sequenceNumber,
@@ -44,30 +65,63 @@ function compressInterval(interval) {
44
65
  { ...properties, [merge_tree_1.reservedRangeLabelsKey]: undefined },
45
66
  ];
46
67
  if (interval.stickiness !== undefined && interval.stickiness !== intervals_1.IntervalStickiness.END) {
47
- base.push(interval.stickiness);
68
+ // reassignment to make it easier for typescript to reason about types
69
+ base = [...base, interval.stickiness];
48
70
  }
49
71
  return base;
50
72
  }
73
+ function endpointPosAndSide(start, end) {
74
+ const startIsPlainEndpoint = typeof start === "number" || start === "start" || start === "end";
75
+ const endIsPlainEndpoint = typeof end === "number" || end === "start" || end === "end";
76
+ const startSide = startIsPlainEndpoint ? Side.Before : start?.side;
77
+ const endSide = endIsPlainEndpoint ? Side.Before : end?.side;
78
+ const startPos = startIsPlainEndpoint ? start : start?.pos;
79
+ const endPos = endIsPlainEndpoint ? end : end?.pos;
80
+ return {
81
+ startSide,
82
+ endSide,
83
+ startPos,
84
+ endPos,
85
+ };
86
+ }
87
+ exports.endpointPosAndSide = endpointPosAndSide;
88
+ function toSequencePlace(pos, side) {
89
+ return typeof pos === "number" ? { pos, side } : pos;
90
+ }
91
+ function toOptionalSequencePlace(pos, side = Side.Before) {
92
+ return typeof pos === "number" ? { pos, side } : pos;
93
+ }
94
+ function computeStickinessFromSide(startPos = -1, startSide = Side.Before, endPos = -1, endSide = Side.Before) {
95
+ let stickiness = intervals_1.IntervalStickiness.NONE;
96
+ if (startSide === Side.After || startPos === "start") {
97
+ stickiness |= intervals_1.IntervalStickiness.START;
98
+ }
99
+ if (endSide === Side.Before || endPos === "end") {
100
+ stickiness |= intervals_1.IntervalStickiness.END;
101
+ }
102
+ return stickiness;
103
+ }
104
+ exports.computeStickinessFromSide = computeStickinessFromSide;
51
105
  function createIntervalIndex() {
52
106
  const helpers = {
53
- compareEnds: (a, b) => a.end - b.end,
54
107
  create: intervals_1.createInterval,
55
108
  };
56
- const lc = new LocalIntervalCollection(undefined, "", helpers);
109
+ const lc = new LocalIntervalCollection(undefined, "", helpers, {});
57
110
  return lc;
58
111
  }
59
112
  exports.createIntervalIndex = createIntervalIndex;
60
113
  class LocalIntervalCollection {
61
- constructor(client, label, helpers,
114
+ constructor(client, label, helpers, options,
62
115
  /** Callback invoked each time one of the endpoints of an interval slides. */
63
116
  onPositionChange) {
64
117
  this.client = client;
65
118
  this.label = label;
66
119
  this.helpers = helpers;
120
+ this.options = options;
67
121
  this.onPositionChange = onPositionChange;
68
- this.overlappingIntervalsIndex = (0, intervalIndex_1.createOverlappingIntervalsIndex)(client, helpers);
122
+ this.overlappingIntervalsIndex = new intervalIndex_1.OverlappingIntervalsIndex(client, helpers);
69
123
  this.idIntervalIndex = (0, intervalIndex_1.createIdIntervalIndex)();
70
- this.endIntervalIndex = (0, intervalIndex_1.createEndpointIndex)(client, helpers);
124
+ this.endIntervalIndex = new intervalIndex_1.EndpointIndex(client, helpers);
71
125
  this.indexes = new Set([
72
126
  this.overlappingIntervalsIndex,
73
127
  this.idIntervalIndex,
@@ -121,12 +175,12 @@ class LocalIntervalCollection {
121
175
  this.removeIntervalFromIndexes(interval);
122
176
  this.removeIntervalListeners(interval);
123
177
  }
124
- createInterval(start, end, intervalType, op, stickiness = intervals_1.IntervalStickiness.END) {
125
- return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, stickiness);
178
+ createInterval(start, end, intervalType, op) {
179
+ return this.helpers.create(this.label, start, end, this.client, intervalType, op, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint);
126
180
  }
127
- addInterval(start, end, intervalType, props, op, stickiness = intervals_1.IntervalStickiness.END) {
181
+ addInterval(start, end, intervalType, props, op) {
128
182
  var _a;
129
- const interval = this.createInterval(start, end, intervalType, op, stickiness);
183
+ const interval = this.createInterval(start, end, intervalType, op);
130
184
  if (interval) {
131
185
  if (!interval.properties) {
132
186
  interval.properties = (0, merge_tree_1.createMap)();
@@ -163,7 +217,7 @@ class LocalIntervalCollection {
163
217
  this.addIntervalListeners(interval);
164
218
  }
165
219
  changeInterval(interval, start, end, op, localSeq) {
166
- const newInterval = interval.modify(this.label, start, end, op, localSeq);
220
+ const newInterval = interval.modify(this.label, start, end, op, localSeq, this.options.mergeTreeReferencesCanSlideToEndpoint);
167
221
  if (newInterval) {
168
222
  this.removeExistingInterval(interval);
169
223
  this.add(newInterval);
@@ -186,7 +240,7 @@ class LocalIntervalCollection {
186
240
  // either, so this must be special-cased.
187
241
  return ref;
188
242
  }
189
- return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference);
243
+ return this.client.createLocalReferencePosition(segment, ref.getOffset(), merge_tree_1.ReferenceType.Transient, ref.properties, ref.slidingPreference, ref.canSlideToEndpoint);
190
244
  };
191
245
  if (interval instanceof intervals_1.SequenceInterval) {
192
246
  let previousInterval;
@@ -245,7 +299,6 @@ SequenceIntervalCollectionValueType._ops = makeOpsMap();
245
299
  class IntervalCollectionFactory {
246
300
  load(emitter, raw = [], options) {
247
301
  const helpers = {
248
- compareEnds: (a, b) => a.end - b.end,
249
302
  create: intervals_1.createInterval,
250
303
  };
251
304
  const collection = new IntervalCollection(helpers, false, emitter, raw, options);
@@ -348,6 +401,9 @@ class IntervalCollectionIterator {
348
401
  * {@inheritdoc IIntervalCollection}
349
402
  */
350
403
  class IntervalCollection extends client_utils_1.TypedEventEmitter {
404
+ get attached() {
405
+ return !!this.localCollection;
406
+ }
351
407
  /** @internal */
352
408
  constructor(helpers, requiresClient, emitter, serializedIntervals, options = {}) {
353
409
  super();
@@ -363,9 +419,6 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
363
419
  ? serializedIntervals
364
420
  : serializedIntervals.intervals.map((i) => decompressInterval(i, serializedIntervals.label));
365
421
  }
366
- get attached() {
367
- return !!this.localCollection;
368
- }
369
422
  /**
370
423
  * {@inheritdoc IIntervalCollection.attachIndex}
371
424
  */
@@ -398,6 +451,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
398
451
  if (!this.client) {
399
452
  throw new telemetry_utils_1.LoggingError("mergeTree client must exist");
400
453
  }
454
+ if (pos === "start" || pos === "end") {
455
+ return pos;
456
+ }
401
457
  const { clientId } = this.client.getCollabWindow();
402
458
  const { segment, offset } = this.client.getContainingSegment(pos, {
403
459
  referenceSequenceNumber: seqNumberFrom,
@@ -405,7 +461,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
405
461
  }, localSeq);
406
462
  // if segment is undefined, it slid off the string
407
463
  (0, core_utils_1.assert)(segment !== undefined, 0x54e /* No segment found */);
408
- const segoff = (0, merge_tree_1.getSlideToSegoff)({ segment, offset }) ?? segment;
464
+ const segoff = (0, merge_tree_1.getSlideToSegoff)({ segment, offset }, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint) ?? segment;
409
465
  // case happens when rebasing op, but concurrently entire string has been deleted
410
466
  if (segoff.segment === undefined || segoff.offset === undefined) {
411
467
  return merge_tree_1.DetachedReferencePosition;
@@ -444,12 +500,18 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
444
500
  }
445
501
  });
446
502
  }
447
- this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
503
+ this.localCollection = new LocalIntervalCollection(client, label, this.helpers, this.options, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
448
504
  if (this.savedSerializedIntervals) {
449
505
  for (const serializedInterval of this.savedSerializedIntervals) {
450
506
  this.localCollection.ensureSerializedId(serializedInterval);
451
- const { start, end, intervalType, properties, stickiness } = serializedInterval;
452
- const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, stickiness);
507
+ const { start: startPos, end: endPos, intervalType, properties, startSide, endSide, } = serializedInterval;
508
+ const start = typeof startPos === "number" && startSide !== undefined
509
+ ? { pos: startPos, side: startSide }
510
+ : startPos;
511
+ const end = typeof endPos === "number" && endSide !== undefined
512
+ ? { pos: endPos, side: endSide }
513
+ : endPos;
514
+ const interval = this.helpers.create(label, start, end, client, intervalType, undefined, true, this.options.mergeTreeReferencesCanSlideToEndpoint);
453
515
  if (properties) {
454
516
  interval.addProperties(properties);
455
517
  }
@@ -495,28 +557,44 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
495
557
  }
496
558
  return this.localCollection.idIntervalIndex.getIntervalById(id);
497
559
  }
560
+ assertStickinessEnabled(start, end) {
561
+ if (!(typeof start === "number" && typeof end === "number") &&
562
+ !this.options.intervalStickinessEnabled) {
563
+ throw new telemetry_utils_1.UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
564
+ }
565
+ }
498
566
  /**
499
567
  * {@inheritdoc IIntervalCollection.add}
500
568
  */
501
- add(start, end, intervalType, props, stickiness = intervals_1.IntervalStickiness.END) {
569
+ add(start, end, intervalType, props) {
502
570
  if (!this.localCollection) {
503
571
  throw new telemetry_utils_1.LoggingError("attach must be called prior to adding intervals");
504
572
  }
505
573
  if (intervalType & intervals_1.IntervalType.Transient) {
506
574
  throw new telemetry_utils_1.LoggingError("Can not add transient intervals");
507
575
  }
508
- if (stickiness !== intervals_1.IntervalStickiness.END && !this.options.intervalStickinessEnabled) {
509
- throw new telemetry_utils_1.UsageError("attempted to set interval stickiness without enabling `intervalStickinessEnabled` feature flag");
510
- }
511
- const interval = this.localCollection.addInterval(start, end, intervalType, props, undefined, stickiness);
576
+ const { startSide, endSide, startPos, endPos } = endpointPosAndSide(start, end);
577
+ (0, core_utils_1.assert)(startPos !== undefined &&
578
+ endPos !== undefined &&
579
+ startSide !== undefined &&
580
+ endSide !== undefined, 0x793 /* start and end cannot be undefined because they were not passed in as undefined */);
581
+ const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
582
+ this.assertStickinessEnabled(start, end);
583
+ const interval = this.localCollection.addInterval(toSequencePlace(startPos, startSide), toSequencePlace(endPos, endSide), intervalType, props);
512
584
  if (interval) {
585
+ if (!this.isCollaborating && interval instanceof intervals_1.SequenceInterval) {
586
+ setSlideOnRemove(interval.start);
587
+ setSlideOnRemove(interval.end);
588
+ }
513
589
  const serializedInterval = {
514
- end,
590
+ start: startPos,
591
+ end: endPos,
515
592
  intervalType,
516
593
  properties: interval.properties,
517
594
  sequenceNumber: this.client?.getCurrentSeq() ?? 0,
518
- start,
519
595
  stickiness,
596
+ startSide,
597
+ endSide,
520
598
  };
521
599
  const localSeq = this.getNextLocalSeq();
522
600
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
@@ -580,8 +658,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
580
658
  }
581
659
  const interval = this.getIntervalById(id);
582
660
  if (interval) {
583
- // Pass Unassigned as the sequence number to indicate that this is a local op that is waiting for an ack.
584
- const deltaProps = interval.addProperties(props, true, merge_tree_1.UnassignedSequenceNumber);
661
+ const deltaProps = interval.addProperties(props, true, this.isCollaborating ? merge_tree_1.UnassignedSequenceNumber : merge_tree_1.UniversalSequenceNumber);
585
662
  const serializedInterval = interval.serialize();
586
663
  // Emit a change op that will only change properties. Add the ID to
587
664
  // the property bag provided by the caller.
@@ -612,9 +689,18 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
612
689
  if (!newInterval) {
613
690
  return undefined;
614
691
  }
692
+ if (!this.isCollaborating && newInterval instanceof intervals_1.SequenceInterval) {
693
+ setSlideOnRemove(newInterval.start);
694
+ setSlideOnRemove(newInterval.end);
695
+ }
615
696
  const serializedInterval = interval.serialize();
616
- serializedInterval.start = start;
617
- serializedInterval.end = end;
697
+ const { startPos, startSide, endPos, endSide } = endpointPosAndSide(start, end);
698
+ const stickiness = computeStickinessFromSide(startPos, startSide, endPos, endSide);
699
+ serializedInterval.start = startPos;
700
+ serializedInterval.end = endPos;
701
+ serializedInterval.startSide = startSide;
702
+ serializedInterval.endSide = endSide;
703
+ serializedInterval.stickiness = stickiness;
618
704
  // Emit a property bag containing only the ID, as we don't intend for this op to change any properties.
619
705
  serializedInterval.properties = {
620
706
  [reservedIntervalIdKey]: interval.getIntervalId(),
@@ -629,7 +715,13 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
629
715
  // No interval to change
630
716
  return undefined;
631
717
  }
718
+ get isCollaborating() {
719
+ return this.client?.getCollabWindow().collaborating ?? false;
720
+ }
632
721
  addPendingChange(id, serializedInterval) {
722
+ if (!this.isCollaborating) {
723
+ return;
724
+ }
633
725
  if (serializedInterval.start !== undefined) {
634
726
  this.addPendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
635
727
  }
@@ -722,7 +814,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
722
814
  // If changeInterval gives us a new interval, work with that one. Otherwise keep working with
723
815
  // the one we originally found in the tree.
724
816
  newInterval =
725
- this.localCollection.changeInterval(interval, start, end, op) ?? interval;
817
+ this.localCollection.changeInterval(interval, toOptionalSequencePlace(start, serializedInterval.startSide), toOptionalSequencePlace(end, serializedInterval.endSide), op) ?? interval;
726
818
  }
727
819
  const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
728
820
  if (this.onDeserialize) {
@@ -767,7 +859,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
767
859
  if (!this.attached) {
768
860
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
769
861
  }
770
- const { intervalType, properties } = serializedInterval;
862
+ const { intervalType, properties, stickiness, startSide, endSide } = serializedInterval;
771
863
  const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
772
864
  const intervalId = properties?.[reservedIntervalIdKey];
773
865
  const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
@@ -777,6 +869,9 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
777
869
  intervalType,
778
870
  sequenceNumber: this.client?.getCurrentSeq() ?? 0,
779
871
  properties,
872
+ stickiness,
873
+ startSide,
874
+ endSide,
780
875
  };
781
876
  if (opName === "change" &&
782
877
  (this.hasPendingChangeStart(intervalId) || this.hasPendingChangeEnd(intervalId))) {
@@ -796,7 +891,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
796
891
  (0, core_utils_1.assert)(localInterval instanceof intervals_1.SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
797
892
  // The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
798
893
  // updates the local client's state to be consistent with the emitted op.
799
- this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
894
+ this.localCollection?.changeInterval(localInterval, toOptionalSequencePlace(startRebased, startSide), toOptionalSequencePlace(endRebased, endSide), undefined, localSeq);
800
895
  }
801
896
  return rebased;
802
897
  }
@@ -808,18 +903,12 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
808
903
  if (segoff.segment?.localRefs?.has(lref) !== true) {
809
904
  return undefined;
810
905
  }
811
- const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff);
906
+ const newSegoff = (0, merge_tree_1.getSlideToSegoff)(segoff, undefined, this.options.mergeTreeReferencesCanSlideToEndpoint);
812
907
  const value = segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset
813
908
  ? undefined
814
909
  : newSegoff;
815
910
  return value;
816
911
  }
817
- setSlideOnRemove(lref) {
818
- let refType = lref.refType;
819
- refType = refType & ~merge_tree_1.ReferenceType.StayOnRemove;
820
- refType = refType | merge_tree_1.ReferenceType.SlideOnRemove;
821
- lref.refType = refType;
822
- }
823
912
  ackInterval(interval, op) {
824
913
  // Only SequenceIntervals need potential sliding
825
914
  if (!(interval instanceof intervals_1.SequenceInterval)) {
@@ -835,10 +924,10 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
835
924
  const hasPendingStartChange = this.hasPendingChangeStart(id);
836
925
  const hasPendingEndChange = this.hasPendingChangeEnd(id);
837
926
  if (!hasPendingStartChange) {
838
- this.setSlideOnRemove(interval.start);
927
+ setSlideOnRemove(interval.start);
839
928
  }
840
929
  if (!hasPendingEndChange) {
841
- this.setSlideOnRemove(interval.end);
930
+ setSlideOnRemove(interval.end);
842
931
  }
843
932
  const needsStartUpdate = newStart !== undefined && !hasPendingStartChange;
844
933
  const needsEndUpdate = newEnd !== undefined && !hasPendingEndChange;
@@ -857,7 +946,8 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
857
946
  }
858
947
  if (needsStartUpdate) {
859
948
  const props = interval.start.properties;
860
- interval.start = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newStart, interval.start.refType, op, (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness));
949
+ interval.start = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newStart, interval.start.refType, op, undefined, undefined, (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness), (0, intervals_1.startReferenceSlidingPreference)(interval.stickiness) ===
950
+ merge_tree_1.SlidingPreference.BACKWARD);
861
951
  if (props) {
862
952
  interval.start.addProperties(props);
863
953
  }
@@ -869,7 +959,8 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
869
959
  }
870
960
  if (needsEndUpdate) {
871
961
  const props = interval.end.properties;
872
- interval.end = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newEnd, interval.end.refType, op, (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness));
962
+ interval.end = (0, intervals_1.createPositionReferenceFromSegoff)(this.client, newEnd, interval.end.refType, op, undefined, undefined, (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness), (0, intervals_1.endReferenceSlidingPreference)(interval.stickiness) ===
963
+ merge_tree_1.SlidingPreference.FORWARD);
873
964
  if (props) {
874
965
  interval.end.addProperties(props);
875
966
  }
@@ -899,7 +990,7 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
899
990
  throw new telemetry_utils_1.LoggingError("attachSequence must be called");
900
991
  }
901
992
  this.localCollection.ensureSerializedId(serializedInterval);
902
- const interval = this.localCollection.addInterval(serializedInterval.start, serializedInterval.end, serializedInterval.intervalType, serializedInterval.properties, op, serializedInterval.stickiness);
993
+ const interval = this.localCollection.addInterval(toSequencePlace(serializedInterval.start, serializedInterval.startSide ?? Side.Before), toSequencePlace(serializedInterval.end, serializedInterval.endSide ?? Side.Before), serializedInterval.intervalType, serializedInterval.properties, op);
903
994
  if (interval) {
904
995
  if (this.onDeserialize) {
905
996
  this.onDeserialize(interval);
@@ -1018,6 +1109,12 @@ class IntervalCollection extends client_utils_1.TypedEventEmitter {
1018
1109
  }
1019
1110
  }
1020
1111
  exports.IntervalCollection = IntervalCollection;
1112
+ function setSlideOnRemove(lref) {
1113
+ let refType = lref.refType;
1114
+ refType = refType & ~merge_tree_1.ReferenceType.StayOnRemove;
1115
+ refType = refType | merge_tree_1.ReferenceType.SlideOnRemove;
1116
+ lref.refType = refType;
1117
+ }
1021
1118
  /**
1022
1119
  * Returns an object that can be used to find the interval a given LocalReferencePosition belongs to.
1023
1120
  * @returns undefined if the reference position is not the endpoint of any interval (e.g. it was created