@fluidframework/sequence 2.0.0-dev.5.2.0.169897 → 2.0.0-dev.6.4.0.191258

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 (231) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/README.md +4 -3
  3. package/dist/defaultMap.d.ts +1 -1
  4. package/dist/defaultMap.d.ts.map +1 -1
  5. package/dist/defaultMap.js +9 -10
  6. package/dist/defaultMap.js.map +1 -1
  7. package/dist/defaultMapInterfaces.d.ts +1 -1
  8. package/dist/defaultMapInterfaces.d.ts.map +1 -1
  9. package/dist/defaultMapInterfaces.js.map +1 -1
  10. package/dist/index.d.ts +3 -2
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +15 -9
  13. package/dist/index.js.map +1 -1
  14. package/dist/intervalCollection.d.ts +14 -437
  15. package/dist/intervalCollection.d.ts.map +1 -1
  16. package/dist/intervalCollection.js +96 -916
  17. package/dist/intervalCollection.js.map +1 -1
  18. package/dist/intervalIndex/endpointInRangeIndex.d.ts +20 -0
  19. package/dist/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
  20. package/dist/intervalIndex/endpointInRangeIndex.js +60 -0
  21. package/dist/intervalIndex/endpointInRangeIndex.js.map +1 -0
  22. package/dist/intervalIndex/endpointIndex.d.ts +21 -0
  23. package/dist/intervalIndex/endpointIndex.d.ts.map +1 -0
  24. package/dist/intervalIndex/endpointIndex.js +42 -0
  25. package/dist/intervalIndex/endpointIndex.js.map +1 -0
  26. package/dist/intervalIndex/idIntervalIndex.d.ts +12 -0
  27. package/dist/intervalIndex/idIntervalIndex.d.ts.map +1 -0
  28. package/dist/intervalIndex/idIntervalIndex.js +41 -0
  29. package/dist/intervalIndex/idIntervalIndex.js.map +1 -0
  30. package/dist/intervalIndex/index.d.ts +13 -0
  31. package/dist/intervalIndex/index.d.ts.map +1 -0
  32. package/dist/intervalIndex/index.js +20 -0
  33. package/dist/intervalIndex/index.js.map +1 -0
  34. package/dist/intervalIndex/intervalIndex.d.ts +29 -0
  35. package/dist/intervalIndex/intervalIndex.d.ts.map +1 -0
  36. package/dist/intervalIndex/intervalIndex.js +7 -0
  37. package/dist/intervalIndex/intervalIndex.js.map +1 -0
  38. package/dist/intervalIndex/intervalIndexUtils.d.ts +17 -0
  39. package/dist/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
  40. package/dist/intervalIndex/intervalIndexUtils.js +22 -0
  41. package/dist/intervalIndex/intervalIndexUtils.js.map +1 -0
  42. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts +33 -0
  43. package/dist/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -0
  44. package/dist/intervalIndex/overlappingIntervalsIndex.js +103 -0
  45. package/dist/intervalIndex/overlappingIntervalsIndex.js.map +1 -0
  46. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +8 -0
  47. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -0
  48. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js +33 -0
  49. package/dist/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -0
  50. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts +33 -0
  51. package/dist/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -0
  52. package/dist/intervalIndex/sequenceIntervalIndexes.js +7 -0
  53. package/dist/intervalIndex/sequenceIntervalIndexes.js.map +1 -0
  54. package/dist/intervalIndex/startpointInRangeIndex.d.ts +20 -0
  55. package/dist/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
  56. package/dist/intervalIndex/startpointInRangeIndex.js +62 -0
  57. package/dist/intervalIndex/startpointInRangeIndex.js.map +1 -0
  58. package/dist/intervalTree.d.ts +2 -56
  59. package/dist/intervalTree.d.ts.map +1 -1
  60. package/dist/intervalTree.js +2 -11
  61. package/dist/intervalTree.js.map +1 -1
  62. package/dist/intervals/index.d.ts +8 -0
  63. package/dist/intervals/index.d.ts.map +1 -0
  64. package/dist/intervals/index.js +23 -0
  65. package/dist/intervals/index.js.map +1 -0
  66. package/dist/intervals/interval.d.ts +88 -0
  67. package/dist/intervals/interval.d.ts.map +1 -0
  68. package/dist/intervals/interval.js +180 -0
  69. package/dist/intervals/interval.js.map +1 -0
  70. package/dist/intervals/intervalUtils.d.ts +200 -0
  71. package/dist/intervals/intervalUtils.d.ts.map +1 -0
  72. package/dist/intervals/intervalUtils.js +79 -0
  73. package/dist/intervals/intervalUtils.js.map +1 -0
  74. package/dist/intervals/sequenceInterval.d.ts +132 -0
  75. package/dist/intervals/sequenceInterval.d.ts.map +1 -0
  76. package/dist/intervals/sequenceInterval.js +313 -0
  77. package/dist/intervals/sequenceInterval.js.map +1 -0
  78. package/dist/packageVersion.d.ts +1 -1
  79. package/dist/packageVersion.js +1 -1
  80. package/dist/packageVersion.js.map +1 -1
  81. package/dist/revertibles.d.ts +1 -1
  82. package/dist/revertibles.d.ts.map +1 -1
  83. package/dist/revertibles.js +85 -52
  84. package/dist/revertibles.js.map +1 -1
  85. package/dist/sequence.d.ts +33 -4
  86. package/dist/sequence.d.ts.map +1 -1
  87. package/dist/sequence.js +91 -47
  88. package/dist/sequence.js.map +1 -1
  89. package/dist/sequenceDeltaEvent.d.ts +8 -3
  90. package/dist/sequenceDeltaEvent.d.ts.map +1 -1
  91. package/dist/sequenceDeltaEvent.js +3 -4
  92. package/dist/sequenceDeltaEvent.js.map +1 -1
  93. package/dist/sharedIntervalCollection.d.ts +2 -1
  94. package/dist/sharedIntervalCollection.d.ts.map +1 -1
  95. package/dist/sharedIntervalCollection.js +2 -2
  96. package/dist/sharedIntervalCollection.js.map +1 -1
  97. package/dist/sharedSequence.d.ts +9 -0
  98. package/dist/sharedSequence.d.ts.map +1 -1
  99. package/dist/sharedSequence.js +9 -6
  100. package/dist/sharedSequence.js.map +1 -1
  101. package/dist/sharedString.d.ts.map +1 -1
  102. package/dist/sharedString.js +9 -29
  103. package/dist/sharedString.js.map +1 -1
  104. package/lib/defaultMap.d.ts +1 -1
  105. package/lib/defaultMap.d.ts.map +1 -1
  106. package/lib/defaultMap.js +5 -6
  107. package/lib/defaultMap.js.map +1 -1
  108. package/lib/defaultMapInterfaces.d.ts +1 -1
  109. package/lib/defaultMapInterfaces.d.ts.map +1 -1
  110. package/lib/defaultMapInterfaces.js.map +1 -1
  111. package/lib/index.d.ts +3 -2
  112. package/lib/index.d.ts.map +1 -1
  113. package/lib/index.js +3 -1
  114. package/lib/index.js.map +1 -1
  115. package/lib/intervalCollection.d.ts +14 -437
  116. package/lib/intervalCollection.d.ts.map +1 -1
  117. package/lib/intervalCollection.js +64 -877
  118. package/lib/intervalCollection.js.map +1 -1
  119. package/lib/intervalIndex/endpointInRangeIndex.d.ts +20 -0
  120. package/lib/intervalIndex/endpointInRangeIndex.d.ts.map +1 -0
  121. package/lib/intervalIndex/endpointInRangeIndex.js +56 -0
  122. package/lib/intervalIndex/endpointInRangeIndex.js.map +1 -0
  123. package/lib/intervalIndex/endpointIndex.d.ts +21 -0
  124. package/lib/intervalIndex/endpointIndex.d.ts.map +1 -0
  125. package/lib/intervalIndex/endpointIndex.js +38 -0
  126. package/lib/intervalIndex/endpointIndex.js.map +1 -0
  127. package/lib/intervalIndex/idIntervalIndex.d.ts +12 -0
  128. package/lib/intervalIndex/idIntervalIndex.d.ts.map +1 -0
  129. package/lib/intervalIndex/idIntervalIndex.js +37 -0
  130. package/lib/intervalIndex/idIntervalIndex.js.map +1 -0
  131. package/lib/intervalIndex/index.d.ts +13 -0
  132. package/lib/intervalIndex/index.d.ts.map +1 -0
  133. package/lib/intervalIndex/index.js +11 -0
  134. package/lib/intervalIndex/index.js.map +1 -0
  135. package/lib/intervalIndex/intervalIndex.d.ts +29 -0
  136. package/lib/intervalIndex/intervalIndex.d.ts.map +1 -0
  137. package/lib/intervalIndex/intervalIndex.js +6 -0
  138. package/lib/intervalIndex/intervalIndex.js.map +1 -0
  139. package/lib/intervalIndex/intervalIndexUtils.d.ts +17 -0
  140. package/lib/intervalIndex/intervalIndexUtils.d.ts.map +1 -0
  141. package/lib/intervalIndex/intervalIndexUtils.js +18 -0
  142. package/lib/intervalIndex/intervalIndexUtils.js.map +1 -0
  143. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts +33 -0
  144. package/lib/intervalIndex/overlappingIntervalsIndex.d.ts.map +1 -0
  145. package/lib/intervalIndex/overlappingIntervalsIndex.js +98 -0
  146. package/lib/intervalIndex/overlappingIntervalsIndex.js.map +1 -0
  147. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts +8 -0
  148. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.d.ts.map +1 -0
  149. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js +29 -0
  150. package/lib/intervalIndex/overlappingSequenceIntervalsIndex.js.map +1 -0
  151. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts +33 -0
  152. package/lib/intervalIndex/sequenceIntervalIndexes.d.ts.map +1 -0
  153. package/lib/intervalIndex/sequenceIntervalIndexes.js +6 -0
  154. package/lib/intervalIndex/sequenceIntervalIndexes.js.map +1 -0
  155. package/lib/intervalIndex/startpointInRangeIndex.d.ts +20 -0
  156. package/lib/intervalIndex/startpointInRangeIndex.d.ts.map +1 -0
  157. package/lib/intervalIndex/startpointInRangeIndex.js +58 -0
  158. package/lib/intervalIndex/startpointInRangeIndex.js.map +1 -0
  159. package/lib/intervalTree.d.ts +2 -56
  160. package/lib/intervalTree.d.ts.map +1 -1
  161. package/lib/intervalTree.js +2 -11
  162. package/lib/intervalTree.js.map +1 -1
  163. package/lib/intervals/index.d.ts +8 -0
  164. package/lib/intervals/index.d.ts.map +1 -0
  165. package/lib/intervals/index.js +8 -0
  166. package/lib/intervals/index.js.map +1 -0
  167. package/lib/intervals/interval.d.ts +88 -0
  168. package/lib/intervals/interval.d.ts.map +1 -0
  169. package/lib/intervals/interval.js +175 -0
  170. package/lib/intervals/interval.js.map +1 -0
  171. package/lib/intervals/intervalUtils.d.ts +200 -0
  172. package/lib/intervals/intervalUtils.d.ts.map +1 -0
  173. package/lib/intervals/intervalUtils.js +74 -0
  174. package/lib/intervals/intervalUtils.js.map +1 -0
  175. package/lib/intervals/sequenceInterval.d.ts +132 -0
  176. package/lib/intervals/sequenceInterval.d.ts.map +1 -0
  177. package/lib/intervals/sequenceInterval.js +305 -0
  178. package/lib/intervals/sequenceInterval.js.map +1 -0
  179. package/lib/packageVersion.d.ts +1 -1
  180. package/lib/packageVersion.js +1 -1
  181. package/lib/packageVersion.js.map +1 -1
  182. package/lib/revertibles.d.ts +1 -1
  183. package/lib/revertibles.d.ts.map +1 -1
  184. package/lib/revertibles.js +69 -36
  185. package/lib/revertibles.js.map +1 -1
  186. package/lib/sequence.d.ts +33 -4
  187. package/lib/sequence.d.ts.map +1 -1
  188. package/lib/sequence.js +86 -41
  189. package/lib/sequence.js.map +1 -1
  190. package/lib/sequenceDeltaEvent.d.ts +8 -3
  191. package/lib/sequenceDeltaEvent.d.ts.map +1 -1
  192. package/lib/sequenceDeltaEvent.js +2 -3
  193. package/lib/sequenceDeltaEvent.js.map +1 -1
  194. package/lib/sharedIntervalCollection.d.ts +2 -1
  195. package/lib/sharedIntervalCollection.d.ts.map +1 -1
  196. package/lib/sharedIntervalCollection.js +1 -1
  197. package/lib/sharedIntervalCollection.js.map +1 -1
  198. package/lib/sharedSequence.d.ts +9 -0
  199. package/lib/sharedSequence.d.ts.map +1 -1
  200. package/lib/sharedSequence.js +8 -5
  201. package/lib/sharedSequence.js.map +1 -1
  202. package/lib/sharedString.d.ts.map +1 -1
  203. package/lib/sharedString.js +9 -29
  204. package/lib/sharedString.js.map +1 -1
  205. package/package.json +31 -34
  206. package/src/defaultMap.ts +2 -1
  207. package/src/defaultMapInterfaces.ts +1 -1
  208. package/src/index.ts +21 -9
  209. package/src/intervalCollection.ts +118 -1403
  210. package/src/intervalIndex/endpointInRangeIndex.ts +104 -0
  211. package/src/intervalIndex/endpointIndex.ts +78 -0
  212. package/src/intervalIndex/idIntervalIndex.ts +58 -0
  213. package/src/intervalIndex/index.ts +16 -0
  214. package/src/intervalIndex/intervalIndex.ts +31 -0
  215. package/src/intervalIndex/intervalIndexUtils.ts +27 -0
  216. package/src/intervalIndex/overlappingIntervalsIndex.ts +162 -0
  217. package/src/intervalIndex/overlappingSequenceIntervalsIndex.ts +71 -0
  218. package/src/intervalIndex/sequenceIntervalIndexes.ts +32 -0
  219. package/src/intervalIndex/startpointInRangeIndex.ts +109 -0
  220. package/src/intervalTree.ts +3 -75
  221. package/src/intervals/index.ts +25 -0
  222. package/src/intervals/interval.ts +230 -0
  223. package/src/intervals/intervalUtils.ts +256 -0
  224. package/src/intervals/sequenceInterval.ts +494 -0
  225. package/src/packageVersion.ts +1 -1
  226. package/src/revertibles.ts +81 -16
  227. package/src/sequence.ts +100 -35
  228. package/src/sequenceDeltaEvent.ts +12 -4
  229. package/src/sharedIntervalCollection.ts +2 -3
  230. package/src/sharedSequence.ts +11 -5
  231. package/src/sharedString.ts +8 -25
@@ -2,53 +2,15 @@
2
2
  * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
3
  * Licensed under the MIT License.
4
4
  */
5
- var __rest = (this && this.__rest) || function (s, e) {
6
- var t = {};
7
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
8
- t[p] = s[p];
9
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
10
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
11
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
12
- t[p[i]] = s[p[i]];
13
- }
14
- return t;
15
- };
16
5
  /* eslint-disable no-bitwise */
17
- import { assert, TypedEventEmitter } from "@fluidframework/common-utils";
18
- import { UsageError } from "@fluidframework/container-utils";
19
- import { addProperties, compareReferencePositions, createMap, MergeTreeDeltaType, minReferencePosition, PropertiesManager, RedBlackTree, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, maxReferencePosition, createDetachedLocalReferencePosition, DetachedReferencePosition, SlidingPreference, } from "@fluidframework/merge-tree";
20
- import { LoggingError } from "@fluidframework/telemetry-utils";
6
+ import { TypedEventEmitter } from "@fluid-internal/client-utils";
7
+ import { assert } from "@fluidframework/core-utils";
8
+ import { addProperties, createMap, getSlideToSegoff, MergeTreeDeltaType, ReferenceType, refTypeIncludesFlag, reservedRangeLabelsKey, UnassignedSequenceNumber, DetachedReferencePosition, } from "@fluidframework/merge-tree";
9
+ import { LoggingError, UsageError } from "@fluidframework/telemetry-utils";
21
10
  import { v4 as uuid } from "uuid";
22
- import { IntervalTree } from "./intervalTree";
11
+ import { IntervalOpType, IntervalStickiness, IntervalType, SequenceInterval, createPositionReferenceFromSegoff, endReferenceSlidingPreference, startReferenceSlidingPreference, sequenceIntervalHelpers, createInterval, } from "./intervals";
12
+ import { createEndpointIndex, createIdIntervalIndex, createOverlappingIntervalsIndex, } from "./intervalIndex";
23
13
  const reservedIntervalIdKey = "intervalId";
24
- /**
25
- * Values are used in persisted formats (ops) and revertibles.
26
- * @alpha
27
- */
28
- export const IntervalOpType = {
29
- ADD: "add",
30
- DELETE: "delete",
31
- CHANGE: "change",
32
- PROPERTY_CHANGED: "propertyChanged",
33
- POSITION_REMOVE: "positionRemove",
34
- };
35
- export var IntervalType;
36
- (function (IntervalType) {
37
- IntervalType[IntervalType["Simple"] = 0] = "Simple";
38
- IntervalType[IntervalType["Nest"] = 1] = "Nest";
39
- /**
40
- * SlideOnRemove indicates that the ends of the interval will slide if the segment
41
- * they reference is removed and acked.
42
- * See `packages\dds\merge-tree\docs\REFERENCEPOSITIONS.md` for details
43
- * SlideOnRemove is the default interval behavior and does not need to be specified.
44
- */
45
- IntervalType[IntervalType["SlideOnRemove"] = 2] = "SlideOnRemove";
46
- /**
47
- * A temporary interval, used internally
48
- * @internal
49
- */
50
- IntervalType[IntervalType["Transient"] = 4] = "Transient";
51
- })(IntervalType || (IntervalType = {}));
52
14
  /**
53
15
  * Decompress an interval after loading a summary from JSON. The exact format
54
16
  * of this compression is unspecified and subject to change
@@ -59,7 +21,7 @@ function decompressInterval(interval, label) {
59
21
  end: interval[1],
60
22
  sequenceNumber: interval[2],
61
23
  intervalType: interval[3],
62
- properties: Object.assign(Object.assign({}, interval[4]), { [reservedRangeLabelsKey]: [label] }),
24
+ properties: { ...interval[4], [reservedRangeLabelsKey]: [label] },
63
25
  stickiness: interval[5],
64
26
  };
65
27
  }
@@ -74,764 +36,23 @@ function compressInterval(interval) {
74
36
  end,
75
37
  sequenceNumber,
76
38
  intervalType,
77
- Object.assign(Object.assign({}, properties), { [reservedRangeLabelsKey]: undefined }),
39
+ // remove the `referenceRangeLabels` property as it is already stored
40
+ // in the `label` field of the summary
41
+ { ...properties, [reservedRangeLabelsKey]: undefined },
78
42
  ];
79
43
  if (interval.stickiness !== undefined && interval.stickiness !== IntervalStickiness.END) {
80
44
  base.push(interval.stickiness);
81
45
  }
82
46
  return base;
83
47
  }
84
- function startReferenceSlidingPreference(stickiness) {
85
- // if any start stickiness, prefer sliding backwards
86
- return (stickiness & IntervalStickiness.START) !== 0
87
- ? SlidingPreference.BACKWARD
88
- : SlidingPreference.FORWARD;
89
- }
90
- function endReferenceSlidingPreference(stickiness) {
91
- // if any end stickiness, prefer sliding forwards
92
- return (stickiness & IntervalStickiness.END) !== 0
93
- ? SlidingPreference.FORWARD
94
- : SlidingPreference.BACKWARD;
95
- }
96
- /**
97
- * Determines how an interval should expand when segments are inserted adjacent
98
- * to the range it spans
99
- *
100
- * Note that interval stickiness is currently an experimental feature and must
101
- * be explicitly enabled with the `intervalStickinessEnabled` flag
102
- */
103
- export const IntervalStickiness = {
104
- /**
105
- * Interval does not expand to include adjacent segments
106
- */
107
- NONE: 0b00,
108
- /**
109
- * Interval expands to include segments inserted adjacent to the start
110
- */
111
- START: 0b01,
112
- /**
113
- * Interval expands to include segments inserted adjacent to the end
114
- *
115
- * This is the default stickiness
116
- */
117
- END: 0b10,
118
- /**
119
- * Interval expands to include all segments inserted adjacent to it
120
- */
121
- FULL: 0b11,
122
- };
123
- /**
124
- * Serializable interval whose endpoints are plain-old numbers.
125
- */
126
- export class Interval {
127
- constructor(start, end, props) {
128
- this.start = start;
129
- this.end = end;
130
- this.propertyManager = new PropertiesManager();
131
- this.properties = {};
132
- if (props) {
133
- this.addProperties(props);
134
- }
135
- }
136
- /**
137
- * {@inheritDoc ISerializableInterval.getIntervalId}
138
- */
139
- getIntervalId() {
140
- var _a;
141
- const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
142
- assert(id !== undefined, 0x5e1 /* interval ID should not be undefined */);
143
- return `${id}`;
144
- }
145
- /**
146
- * @returns an array containing any auxiliary property sets added with `addPropertySet`.
147
- */
148
- getAdditionalPropertySets() {
149
- var _a;
150
- return (_a = this.auxProps) !== null && _a !== void 0 ? _a : [];
151
- }
152
- /**
153
- * Adds an auxiliary set of properties to this interval.
154
- * These properties can be recovered using `getAdditionalPropertySets`
155
- * @param props - set of properties to add
156
- * @remarks - This gets called as part of the default conflict resolver for `IIntervalCollection<Interval>`
157
- * (i.e. non-sequence-based interval collections). However, the additional properties don't get serialized.
158
- * This functionality seems half-baked.
159
- */
160
- addPropertySet(props) {
161
- if (this.auxProps === undefined) {
162
- this.auxProps = [];
163
- }
164
- this.auxProps.push(props);
165
- }
166
- /**
167
- * {@inheritDoc ISerializableInterval.serialize}
168
- * @internal
169
- */
170
- serialize() {
171
- const serializedInterval = {
172
- end: this.end,
173
- intervalType: 0,
174
- sequenceNumber: 0,
175
- start: this.start,
176
- };
177
- if (this.properties) {
178
- serializedInterval.properties = this.properties;
179
- }
180
- return serializedInterval;
181
- }
182
- /**
183
- * {@inheritDoc IInterval.clone}
184
- */
185
- clone() {
186
- return new Interval(this.start, this.end, this.properties);
187
- }
188
- /**
189
- * {@inheritDoc IInterval.compare}
190
- */
191
- compare(b) {
192
- const startResult = this.compareStart(b);
193
- if (startResult === 0) {
194
- const endResult = this.compareEnd(b);
195
- if (endResult === 0) {
196
- const thisId = this.getIntervalId();
197
- if (thisId) {
198
- const bId = b.getIntervalId();
199
- if (bId) {
200
- return thisId > bId ? 1 : thisId < bId ? -1 : 0;
201
- }
202
- return 0;
203
- }
204
- return 0;
205
- }
206
- else {
207
- return endResult;
208
- }
209
- }
210
- else {
211
- return startResult;
212
- }
213
- }
214
- /**
215
- * {@inheritDoc IInterval.compareStart}
216
- */
217
- compareStart(b) {
218
- return this.start - b.start;
219
- }
220
- /**
221
- * {@inheritDoc IInterval.compareEnd}
222
- */
223
- compareEnd(b) {
224
- return this.end - b.end;
225
- }
226
- /**
227
- * {@inheritDoc IInterval.overlaps}
228
- */
229
- overlaps(b) {
230
- const result = this.start <= b.end && this.end >= b.start;
231
- return result;
232
- }
233
- /**
234
- * {@inheritDoc IInterval.union}
235
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
236
- */
237
- union(b) {
238
- return new Interval(Math.min(this.start, b.start), Math.max(this.end, b.end), this.properties);
239
- }
240
- getProperties() {
241
- return this.properties;
242
- }
243
- /**
244
- * {@inheritDoc ISerializableInterval.addProperties}
245
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
246
- */
247
- addProperties(newProps, collaborating = false, seq, op) {
248
- if (newProps) {
249
- this.initializeProperties();
250
- return this.propertyManager.addProperties(this.properties, newProps, op, seq, collaborating);
251
- }
252
- }
253
- /**
254
- * {@inheritDoc IInterval.modify}
255
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
256
- */
257
- modify(label, start, end, op) {
258
- const startPos = start !== null && start !== void 0 ? start : this.start;
259
- const endPos = end !== null && end !== void 0 ? end : this.end;
260
- if (this.start === startPos && this.end === endPos) {
261
- // Return undefined to indicate that no change is necessary.
262
- return;
263
- }
264
- const newInterval = new Interval(startPos, endPos);
265
- if (this.properties) {
266
- newInterval.initializeProperties();
267
- this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
268
- }
269
- return newInterval;
270
- }
271
- initializeProperties() {
272
- if (!this.propertyManager) {
273
- this.propertyManager = new PropertiesManager();
274
- }
275
- if (!this.properties) {
276
- this.properties = createMap();
277
- }
278
- }
279
- }
280
- /**
281
- * Interval implementation whose ends are associated with positions in a mutatable sequence.
282
- * As such, when content is inserted into the middle of the interval, the interval expands to
283
- * include that content.
284
- *
285
- * @remarks - The endpoint's position should be treated exclusively to get reasonable behavior--i.e.
286
- * an interval referring to "hello" in "hello world" should have a start position of 0 and an end
287
- * position of 5.
288
- *
289
- * To see why, consider what happens if "llo wor" is removed from the string to make "held".
290
- * The interval's startpoint remains on the "h" (it isn't altered), but the interval's endpoint
291
- * slides forward to the next unremoved position, which is the "l" in "held".
292
- * Users would generally expect the interval to now refer to "he" (as it is the subset of content
293
- * remaining after the removal), hence the "l" should be excluded.
294
- * If the interval endpoint was treated inclusively, the interval would now refer to "hel", which
295
- * is undesirable.
296
- *
297
- * Since the end of an interval is treated exclusively but cannot be greater than or equal to the
298
- * length of the associated sequence, application models which leverage interval collections should
299
- * consider inserting a marker at the end of the sequence to represent the end of the content.
300
- */
301
- export class SequenceInterval {
302
- constructor(client,
303
- /**
304
- * Start endpoint of this interval.
305
- * @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
306
- */
307
- start,
308
- /**
309
- * End endpoint of this interval.
310
- * @remarks - This endpoint can be resolved into a character position using the SharedString it's a part of.
311
- */
312
- end, intervalType, props, stickiness = IntervalStickiness.END) {
313
- this.client = client;
314
- this.start = start;
315
- this.end = end;
316
- this.intervalType = intervalType;
317
- this.stickiness = stickiness;
318
- this.propertyManager = new PropertiesManager();
319
- this.properties = {};
320
- if (props) {
321
- this.addProperties(props);
322
- }
323
- }
324
- /**
325
- * Subscribes to position change events on this interval if there are no current listeners.
326
- * @internal
327
- */
328
- addPositionChangeListeners(beforePositionChange, afterPositionChange) {
329
- var _a, _b;
330
- var _c, _d;
331
- if (this.callbacks === undefined) {
332
- this.callbacks = {
333
- beforePositionChange,
334
- afterPositionChange,
335
- };
336
- const startCbs = ((_a = (_c = this.start).callbacks) !== null && _a !== void 0 ? _a : (_c.callbacks = {}));
337
- const endCbs = ((_b = (_d = this.end).callbacks) !== null && _b !== void 0 ? _b : (_d.callbacks = {}));
338
- startCbs.beforeSlide = endCbs.beforeSlide = beforePositionChange;
339
- startCbs.afterSlide = endCbs.afterSlide = afterPositionChange;
340
- }
341
- }
342
- /**
343
- * Removes the currently subscribed position change listeners.
344
- * @internal
345
- */
346
- removePositionChangeListeners() {
347
- if (this.callbacks) {
348
- this.callbacks = undefined;
349
- this.start.callbacks = undefined;
350
- this.end.callbacks = undefined;
351
- }
352
- }
353
- /**
354
- * {@inheritDoc ISerializableInterval.serialize}
355
- * @internal
356
- */
357
- serialize() {
358
- const startPosition = this.client.localReferencePositionToPosition(this.start);
359
- const endPosition = this.client.localReferencePositionToPosition(this.end);
360
- const serializedInterval = {
361
- end: endPosition,
362
- intervalType: this.intervalType,
363
- sequenceNumber: this.client.getCurrentSeq(),
364
- start: startPosition,
365
- };
366
- if (this.properties) {
367
- serializedInterval.properties = this.properties;
368
- }
369
- if (this.stickiness !== IntervalStickiness.END) {
370
- serializedInterval.stickiness = this.stickiness;
371
- }
372
- return serializedInterval;
373
- }
374
- /**
375
- * {@inheritDoc IInterval.clone}
376
- */
377
- clone() {
378
- return new SequenceInterval(this.client, this.start, this.end, this.intervalType, this.properties, this.stickiness);
379
- }
380
- /**
381
- * {@inheritDoc IInterval.compare}
382
- */
383
- compare(b) {
384
- const startResult = this.compareStart(b);
385
- if (startResult === 0) {
386
- const endResult = this.compareEnd(b);
387
- if (endResult === 0) {
388
- const thisId = this.getIntervalId();
389
- if (thisId) {
390
- const bId = b.getIntervalId();
391
- if (bId) {
392
- return thisId > bId ? 1 : thisId < bId ? -1 : 0;
393
- }
394
- return 0;
395
- }
396
- return 0;
397
- }
398
- else {
399
- return endResult;
400
- }
401
- }
402
- else {
403
- return startResult;
404
- }
405
- }
406
- /**
407
- * {@inheritDoc IInterval.compareStart}
408
- */
409
- compareStart(b) {
410
- return compareReferencePositions(this.start, b.start);
411
- }
412
- /**
413
- * {@inheritDoc IInterval.compareEnd}
414
- */
415
- compareEnd(b) {
416
- return compareReferencePositions(this.end, b.end);
417
- }
418
- /**
419
- * {@inheritDoc IInterval.overlaps}
420
- */
421
- overlaps(b) {
422
- const result = compareReferencePositions(this.start, b.end) <= 0 &&
423
- compareReferencePositions(this.end, b.start) >= 0;
424
- return result;
425
- }
426
- /**
427
- * {@inheritDoc ISerializableInterval.getIntervalId}
428
- */
429
- getIntervalId() {
430
- var _a;
431
- const id = (_a = this.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
432
- assert(id !== undefined, 0x5e2 /* interval ID should not be undefined */);
433
- return `${id}`;
434
- }
435
- /**
436
- * {@inheritDoc IInterval.union}
437
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
438
- */
439
- union(b) {
440
- return new SequenceInterval(this.client, minReferencePosition(this.start, b.start), maxReferencePosition(this.end, b.end), this.intervalType);
441
- }
442
- /**
443
- * {@inheritDoc ISerializableInterval.addProperties}
444
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
445
- */
446
- addProperties(newProps, collab = false, seq, op) {
447
- this.initializeProperties();
448
- return this.propertyManager.addProperties(this.properties, newProps, op, seq, collab);
449
- }
450
- /**
451
- * @returns whether this interval overlaps two numerical positions.
452
- */
453
- overlapsPos(bstart, bend) {
454
- const startPos = this.client.localReferencePositionToPosition(this.start);
455
- const endPos = this.client.localReferencePositionToPosition(this.end);
456
- return endPos > bstart && startPos < bend;
457
- }
458
- /**
459
- * {@inheritDoc IInterval.modify}
460
- * @deprecated - This API was never intended to be public and will be marked internal in a future release.
461
- */
462
- modify(label, start, end, op, localSeq, stickiness = IntervalStickiness.END) {
463
- const getRefType = (baseType) => {
464
- let refType = baseType;
465
- if (op === undefined) {
466
- refType &= ~ReferenceType.SlideOnRemove;
467
- refType |= ReferenceType.StayOnRemove;
468
- }
469
- return refType;
470
- };
471
- let startRef = this.start;
472
- if (start !== undefined) {
473
- startRef = createPositionReference(this.client, start, getRefType(this.start.refType), op, undefined, localSeq, startReferenceSlidingPreference(stickiness));
474
- if (this.start.properties) {
475
- startRef.addProperties(this.start.properties);
476
- }
477
- }
478
- let endRef = this.end;
479
- if (end !== undefined) {
480
- endRef = createPositionReference(this.client, end, getRefType(this.end.refType), op, undefined, localSeq, endReferenceSlidingPreference(stickiness));
481
- if (this.end.properties) {
482
- endRef.addProperties(this.end.properties);
483
- }
484
- }
485
- const newInterval = new SequenceInterval(this.client, startRef, endRef, this.intervalType);
486
- if (this.properties) {
487
- newInterval.initializeProperties();
488
- this.propertyManager.copyTo(this.properties, newInterval.properties, newInterval.propertyManager);
489
- }
490
- return newInterval;
491
- }
492
- initializeProperties() {
493
- if (!this.propertyManager) {
494
- this.propertyManager = new PropertiesManager();
495
- }
496
- if (!this.properties) {
497
- this.properties = createMap();
498
- }
499
- }
500
- }
501
- function createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference) {
502
- if (segoff.segment) {
503
- const ref = client.createLocalReferencePosition(segoff.segment, segoff.offset, refType, undefined, slidingPreference);
504
- return ref;
505
- }
506
- // Creating references on detached segments is allowed for:
507
- // - Transient segments
508
- // - References coming from a remote client (location may have been concurrently removed)
509
- // - References being rebased to a new sequence number
510
- // (segment they originally referred to may have been removed with no suitable replacement)
511
- if (!op &&
512
- !localSeq &&
513
- !fromSnapshot &&
514
- !refTypeIncludesFlag(refType, ReferenceType.Transient)) {
515
- throw new UsageError("Non-transient references need segment");
516
- }
517
- return createDetachedLocalReferencePosition(refType);
518
- }
519
- function createPositionReference(client, pos, refType, op, fromSnapshot, localSeq, slidingPreference) {
520
- let segoff;
521
- if (op) {
522
- assert((refType & ReferenceType.SlideOnRemove) !== 0, 0x2f5 /* op create references must be SlideOnRemove */);
523
- segoff = client.getContainingSegment(pos, {
524
- referenceSequenceNumber: op.referenceSequenceNumber,
525
- clientId: op.clientId,
526
- });
527
- segoff = client.getSlideToSegment(segoff);
528
- }
529
- else {
530
- assert((refType & ReferenceType.SlideOnRemove) === 0 || !!fromSnapshot, 0x2f6 /* SlideOnRemove references must be op created */);
531
- segoff = client.getContainingSegment(pos, undefined, localSeq);
532
- }
533
- return createPositionReferenceFromSegoff(client, segoff, refType, op, localSeq, fromSnapshot, slidingPreference);
534
- }
535
- export function createSequenceInterval(label, start, end, client, intervalType, op, fromSnapshot, stickiness = IntervalStickiness.END) {
536
- let beginRefType = ReferenceType.RangeBegin;
537
- let endRefType = ReferenceType.RangeEnd;
538
- if (intervalType === IntervalType.Transient) {
539
- beginRefType = ReferenceType.Transient;
540
- endRefType = ReferenceType.Transient;
541
- }
542
- else {
543
- if (intervalType === IntervalType.Nest) {
544
- beginRefType = ReferenceType.NestBegin;
545
- endRefType = ReferenceType.NestEnd;
546
- }
547
- // All non-transient interval references must eventually be SlideOnRemove
548
- // To ensure eventual consistency, they must start as StayOnRemove when
549
- // pending (created locally and creation op is not acked)
550
- if (op || fromSnapshot) {
551
- beginRefType |= ReferenceType.SlideOnRemove;
552
- endRefType |= ReferenceType.SlideOnRemove;
553
- }
554
- else {
555
- beginRefType |= ReferenceType.StayOnRemove;
556
- endRefType |= ReferenceType.StayOnRemove;
557
- }
558
- }
559
- const startLref = createPositionReference(client, start, beginRefType, op, fromSnapshot, undefined, startReferenceSlidingPreference(stickiness));
560
- const endLref = createPositionReference(client, end, endRefType, op, fromSnapshot, undefined, endReferenceSlidingPreference(stickiness));
561
- const rangeProp = {
562
- [reservedRangeLabelsKey]: [label],
563
- };
564
- startLref.addProperties(rangeProp);
565
- endLref.addProperties(rangeProp);
566
- const ival = new SequenceInterval(client, startLref, endLref, intervalType, rangeProp, stickiness);
567
- return ival;
568
- }
569
48
  export function createIntervalIndex() {
570
49
  const helpers = {
571
- compareEnds: compareIntervalEnds,
50
+ compareEnds: (a, b) => a.end - b.end,
572
51
  create: createInterval,
573
52
  };
574
53
  const lc = new LocalIntervalCollection(undefined, "", helpers);
575
54
  return lc;
576
55
  }
577
- class OverlappingIntervalsIndex {
578
- constructor(client, helpers) {
579
- this.client = client;
580
- this.helpers = helpers;
581
- this.intervalTree = new IntervalTree();
582
- }
583
- map(fn) {
584
- this.intervalTree.map(fn);
585
- }
586
- mapUntil(fn) {
587
- this.intervalTree.mapUntil(fn);
588
- }
589
- gatherIterationResults(results, iteratesForward, start, end) {
590
- if (this.intervalTree.intervals.isEmpty()) {
591
- return;
592
- }
593
- if (start === undefined && end === undefined) {
594
- // No start/end provided. Gather the whole tree in the specified order.
595
- if (iteratesForward) {
596
- this.intervalTree.map((interval) => {
597
- results.push(interval);
598
- });
599
- }
600
- else {
601
- this.intervalTree.mapBackward((interval) => {
602
- results.push(interval);
603
- });
604
- }
605
- }
606
- else {
607
- const transientInterval = this.helpers.create("transient", start, end, this.client, IntervalType.Transient);
608
- if (start === undefined) {
609
- // Only end position provided. Since the tree is not sorted by end position,
610
- // walk the whole tree in the specified order, gathering intervals that match the end.
611
- if (iteratesForward) {
612
- this.intervalTree.map((interval) => {
613
- if (transientInterval.compareEnd(interval) === 0) {
614
- results.push(interval);
615
- }
616
- });
617
- }
618
- else {
619
- this.intervalTree.mapBackward((interval) => {
620
- if (transientInterval.compareEnd(interval) === 0) {
621
- results.push(interval);
622
- }
623
- });
624
- }
625
- }
626
- else {
627
- // Start and (possibly) end provided. Walk the subtrees that may contain
628
- // this start position.
629
- const compareFn = end === undefined
630
- ? (node) => {
631
- return transientInterval.compareStart(node.key);
632
- }
633
- : (node) => {
634
- return transientInterval.compare(node.key);
635
- };
636
- const continueLeftFn = (cmpResult) => cmpResult <= 0;
637
- const continueRightFn = (cmpResult) => cmpResult >= 0;
638
- const actionFn = (node) => {
639
- results.push(node.key);
640
- };
641
- if (iteratesForward) {
642
- this.intervalTree.intervals.walkExactMatchesForward(compareFn, actionFn, continueLeftFn, continueRightFn);
643
- }
644
- else {
645
- this.intervalTree.intervals.walkExactMatchesBackward(compareFn, actionFn, continueLeftFn, continueRightFn);
646
- }
647
- }
648
- }
649
- }
650
- /**
651
- * @returns an array of all intervals contained in this collection that overlap the range
652
- * `[startPosition, endPosition)`.
653
- */
654
- findOverlappingIntervals(startPosition, endPosition) {
655
- if (endPosition < startPosition || this.intervalTree.intervals.isEmpty()) {
656
- return [];
657
- }
658
- const transientInterval = this.helpers.create("transient", startPosition, endPosition, this.client, IntervalType.Transient);
659
- const overlappingIntervalNodes = this.intervalTree.match(transientInterval);
660
- return overlappingIntervalNodes.map((node) => node.key);
661
- }
662
- remove(interval) {
663
- this.intervalTree.removeExisting(interval);
664
- }
665
- add(interval) {
666
- this.intervalTree.put(interval);
667
- }
668
- }
669
- class IdIntervalIndex {
670
- constructor() {
671
- this.intervalIdMap = new Map();
672
- }
673
- add(interval) {
674
- const id = interval.getIntervalId();
675
- assert(id !== undefined, 0x2c0 /* "ID must be created before adding interval to collection" */);
676
- // Make the ID immutable.
677
- Object.defineProperty(interval.properties, reservedIntervalIdKey, {
678
- configurable: false,
679
- enumerable: true,
680
- writable: false,
681
- });
682
- this.intervalIdMap.set(id, interval);
683
- }
684
- remove(interval) {
685
- const id = interval.getIntervalId();
686
- assert(id !== undefined, 0x311 /* expected id to exist on interval */);
687
- this.intervalIdMap.delete(id);
688
- }
689
- getIntervalById(id) {
690
- return this.intervalIdMap.get(id);
691
- }
692
- [Symbol.iterator]() {
693
- return this.intervalIdMap.values();
694
- }
695
- }
696
- class EndpointIndex {
697
- constructor(client, helpers) {
698
- this.client = client;
699
- this.helpers = helpers;
700
- // eslint-disable-next-line @typescript-eslint/unbound-method
701
- this.endIntervalTree = new RedBlackTree(helpers.compareEnds);
702
- }
703
- previousInterval(pos) {
704
- const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
705
- const rbNode = this.endIntervalTree.floor(transientInterval);
706
- if (rbNode) {
707
- return rbNode.data;
708
- }
709
- }
710
- nextInterval(pos) {
711
- const transientInterval = this.helpers.create("transient", pos, pos, this.client, IntervalType.Transient);
712
- const rbNode = this.endIntervalTree.ceil(transientInterval);
713
- if (rbNode) {
714
- return rbNode.data;
715
- }
716
- }
717
- add(interval) {
718
- this.endIntervalTree.put(interval, interval);
719
- }
720
- remove(interval) {
721
- this.endIntervalTree.remove(interval);
722
- }
723
- }
724
- /**
725
- * Interface for intervals that have comparison override properties.
726
- */
727
- const forceCompare = Symbol();
728
- /**
729
- * Compares two objects based on their comparison override properties.
730
- * @returns A number indicating the order of the intervals (negative for a is lower than b, 0 for tie, positive for a is greater than b).
731
- */
732
- function compareOverrideables(a, b) {
733
- var _a, _b;
734
- const forceCompareA = (_a = a[forceCompare]) !== null && _a !== void 0 ? _a : 0;
735
- const forceCompareB = (_b = b[forceCompare]) !== null && _b !== void 0 ? _b : 0;
736
- return forceCompareA - forceCompareB;
737
- }
738
- class EndpointInRangeIndex {
739
- constructor(helpers, client) {
740
- this.helpers = helpers;
741
- this.client = client;
742
- this.intervalTree = new RedBlackTree((a, b) => {
743
- const compareEndsResult = helpers.compareEnds(a, b);
744
- if (compareEndsResult !== 0) {
745
- return compareEndsResult;
746
- }
747
- const overrideablesComparison = compareOverrideables(a, b);
748
- if (overrideablesComparison !== 0) {
749
- return overrideablesComparison;
750
- }
751
- const aId = a.getIntervalId();
752
- const bId = b.getIntervalId();
753
- if (aId !== undefined && bId !== undefined) {
754
- return aId.localeCompare(bId);
755
- }
756
- return 0;
757
- });
758
- }
759
- add(interval) {
760
- this.intervalTree.put(interval, interval);
761
- }
762
- remove(interval) {
763
- this.intervalTree.remove(interval);
764
- }
765
- findIntervalsWithEndpointInRange(start, end) {
766
- if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
767
- return [];
768
- }
769
- const results = [];
770
- const action = (node) => {
771
- results.push(node.data);
772
- return true;
773
- };
774
- const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
775
- const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
776
- // Add comparison overrides to the transient intervals
777
- transientStartInterval[forceCompare] = -1;
778
- transientEndInterval[forceCompare] = 1;
779
- this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
780
- return results;
781
- }
782
- }
783
- class StartpointInRangeIndex {
784
- constructor(helpers, client) {
785
- this.helpers = helpers;
786
- this.client = client;
787
- this.intervalTree = new RedBlackTree((a, b) => {
788
- assert(typeof helpers.compareStarts === "function", 0x6d1 /* compareStarts does not exist in the helpers */);
789
- const compareStartsResult = helpers.compareStarts(a, b);
790
- if (compareStartsResult !== 0) {
791
- return compareStartsResult;
792
- }
793
- const overrideablesComparison = compareOverrideables(a, b);
794
- if (overrideablesComparison !== 0) {
795
- return overrideablesComparison;
796
- }
797
- const aId = a.getIntervalId();
798
- const bId = b.getIntervalId();
799
- if (aId !== undefined && bId !== undefined) {
800
- return aId.localeCompare(bId);
801
- }
802
- return 0;
803
- });
804
- }
805
- add(interval) {
806
- this.intervalTree.put(interval, interval);
807
- }
808
- remove(interval) {
809
- this.intervalTree.remove(interval);
810
- }
811
- findIntervalsWithStartpointInRange(start, end) {
812
- if (start <= 0 || start > end || this.intervalTree.isEmpty()) {
813
- return [];
814
- }
815
- const results = [];
816
- const action = (node) => {
817
- results.push(node.data);
818
- return true;
819
- };
820
- const transientStartInterval = this.helpers.create("transient", start, start, this.client, IntervalType.Transient);
821
- const transientEndInterval = this.helpers.create("transient", end, end, this.client, IntervalType.Transient);
822
- // Add comparison overrides to the transient intervals
823
- transientStartInterval[forceCompare] = -1;
824
- transientEndInterval[forceCompare] = 1;
825
- this.intervalTree.mapRange(action, results, transientStartInterval, transientEndInterval);
826
- return results;
827
- }
828
- }
829
- export function createEndpointInRangeIndex(helpers, client) {
830
- return new EndpointInRangeIndex(helpers, client);
831
- }
832
- export function createStartpointInRangeIndex(helpers, client) {
833
- return new StartpointInRangeIndex(helpers, client);
834
- }
835
56
  export class LocalIntervalCollection {
836
57
  constructor(client, label, helpers,
837
58
  /** Callback invoked each time one of the endpoints of an interval slides. */
@@ -840,9 +61,9 @@ export class LocalIntervalCollection {
840
61
  this.label = label;
841
62
  this.helpers = helpers;
842
63
  this.onPositionChange = onPositionChange;
843
- this.overlappingIntervalsIndex = new OverlappingIntervalsIndex(client, helpers);
844
- this.idIntervalIndex = new IdIntervalIndex();
845
- this.endIntervalIndex = new EndpointIndex(client, helpers);
64
+ this.overlappingIntervalsIndex = createOverlappingIntervalsIndex(client, helpers);
65
+ this.idIntervalIndex = createIdIntervalIndex();
66
+ this.endIntervalIndex = createEndpointIndex(client, helpers);
846
67
  this.indexes = new Set([
847
68
  this.overlappingIntervalsIndex,
848
69
  this.idIntervalIndex,
@@ -862,8 +83,7 @@ export class LocalIntervalCollection {
862
83
  * @returns The interval's existing or newly created id
863
84
  */
864
85
  ensureSerializedId(serializedInterval) {
865
- var _a;
866
- let id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
86
+ let id = serializedInterval.properties?.[reservedIntervalIdKey];
867
87
  if (id === undefined) {
868
88
  // Back-compat: 0.39 and earlier did not have IDs on intervals. If an interval from such a client
869
89
  // comes over the wire, create a non-unique one based on start/end.
@@ -902,16 +122,22 @@ export class LocalIntervalCollection {
902
122
  }
903
123
  addInterval(start, end, intervalType, props, op, stickiness = IntervalStickiness.END) {
904
124
  var _a;
905
- var _b;
906
125
  const interval = this.createInterval(start, end, intervalType, op, stickiness);
907
126
  if (interval) {
908
127
  if (!interval.properties) {
909
128
  interval.properties = createMap();
910
129
  }
911
130
  if (props) {
131
+ // This check is intended to prevent scenarios where a random interval is created and then
132
+ // inserted into a collection. The aim is to ensure that the collection is created first
133
+ // then the user can create/add intervals based on the collection
134
+ if (props[reservedRangeLabelsKey] !== undefined &&
135
+ props[reservedRangeLabelsKey][0] !== this.label) {
136
+ throw new LoggingError("Adding an interval that belongs to another interval collection is not permitted");
137
+ }
912
138
  interval.addProperties(props);
913
139
  }
914
- (_a = (_b = interval.properties)[reservedIntervalIdKey]) !== null && _a !== void 0 ? _a : (_b[reservedIntervalIdKey] = uuid());
140
+ (_a = interval.properties)[reservedIntervalIdKey] ?? (_a[reservedIntervalIdKey] = uuid());
915
141
  this.add(interval);
916
142
  }
917
143
  return interval;
@@ -971,12 +197,11 @@ export class LocalIntervalCollection {
971
197
  this.removeIntervalFromIndexes(interval);
972
198
  }
973
199
  }, () => {
974
- var _a;
975
200
  assert(previousInterval !== undefined, 0x3fa /* Invalid interleaving of before/after slide */);
976
201
  pendingChanges--;
977
202
  if (pendingChanges === 0) {
978
203
  this.addIntervalToIndexes(interval);
979
- (_a = this.onPositionChange) === null || _a === void 0 ? void 0 : _a.call(this, interval, previousInterval);
204
+ this.onPositionChange?.(interval, previousInterval);
980
205
  previousInterval = undefined;
981
206
  }
982
207
  });
@@ -989,18 +214,6 @@ export class LocalIntervalCollection {
989
214
  }
990
215
  }
991
216
  LocalIntervalCollection.legacyIdPrefix = "legacy";
992
- export const compareSequenceIntervalEnds = (a, b) => compareReferencePositions(a.end, b.end);
993
- export const compareSequenceIntervalStarts = (a, b) => compareReferencePositions(a.start, b.start);
994
- export const sequenceIntervalHelpers = {
995
- compareEnds: compareSequenceIntervalEnds,
996
- compareStarts: compareSequenceIntervalStarts,
997
- create: createSequenceInterval,
998
- };
999
- export const intervalHelpers = {
1000
- compareEnds: (a, b) => a.end - b.end,
1001
- compareStarts: (a, b) => a.start - b.start,
1002
- create: createInterval,
1003
- };
1004
217
  class SequenceIntervalCollectionFactory {
1005
218
  load(emitter, raw = [], options) {
1006
219
  return new IntervalCollection(sequenceIntervalHelpers, true, emitter, raw, options);
@@ -1023,18 +236,10 @@ export class SequenceIntervalCollectionValueType {
1023
236
  SequenceIntervalCollectionValueType.Name = "sharedStringIntervalCollection";
1024
237
  SequenceIntervalCollectionValueType._factory = new SequenceIntervalCollectionFactory();
1025
238
  SequenceIntervalCollectionValueType._ops = makeOpsMap();
1026
- const compareIntervalEnds = (a, b) => a.end - b.end;
1027
- function createInterval(label, start, end, client, intervalType, op, fromSnapshot) {
1028
- const rangeProp = {};
1029
- if (label && label.length > 0) {
1030
- rangeProp[reservedRangeLabelsKey] = [label];
1031
- }
1032
- return new Interval(start, end, rangeProp);
1033
- }
1034
239
  class IntervalCollectionFactory {
1035
240
  load(emitter, raw = [], options) {
1036
241
  const helpers = {
1037
- compareEnds: compareIntervalEnds,
242
+ compareEnds: (a, b) => a.end - b.end,
1038
243
  create: createInterval,
1039
244
  };
1040
245
  const collection = new IntervalCollection(helpers, false, emitter, raw, options);
@@ -1063,7 +268,7 @@ export function makeOpsMap() {
1063
268
  const rebase = (collection, op, localOpMetadata) => {
1064
269
  const { localSeq } = localOpMetadata;
1065
270
  const rebasedValue = collection.rebaseLocalInterval(op.opName, op.value, localSeq);
1066
- const rebasedOp = Object.assign(Object.assign({}, op), { value: rebasedValue });
271
+ const rebasedOp = { ...op, value: rebasedValue };
1067
272
  return { rebasedOp, rebasedLocalOpMetadata: localOpMetadata };
1068
273
  };
1069
274
  return new Map([
@@ -1157,25 +362,23 @@ export class IntervalCollection extends TypedEventEmitter {
1157
362
  * {@inheritdoc IIntervalCollection.attachIndex}
1158
363
  */
1159
364
  attachIndex(index) {
1160
- var _a;
1161
365
  if (!this.attached) {
1162
366
  throw new LoggingError("The local interval collection must exist");
1163
367
  }
1164
368
  for (const interval of this) {
1165
369
  index.add(interval);
1166
370
  }
1167
- (_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.appendIndex(index);
371
+ this.localCollection?.appendIndex(index);
1168
372
  }
1169
373
  /**
1170
374
  * {@inheritdoc IIntervalCollection.detachIndex}
1171
375
  */
1172
376
  detachIndex(index) {
1173
- var _a;
1174
377
  if (!this.attached) {
1175
378
  throw new LoggingError("The local interval collection must exist");
1176
379
  }
1177
380
  // Avoid removing intervals if the index does not exist
1178
- if (!((_a = this.localCollection) === null || _a === void 0 ? void 0 : _a.removeIndex(index))) {
381
+ if (!this.localCollection?.removeIndex(index)) {
1179
382
  return false;
1180
383
  }
1181
384
  for (const interval of this) {
@@ -1184,7 +387,6 @@ export class IntervalCollection extends TypedEventEmitter {
1184
387
  return true;
1185
388
  }
1186
389
  rebasePositionWithSegmentSlide(pos, seqNumberFrom, localSeq) {
1187
- var _a;
1188
390
  if (!this.client) {
1189
391
  throw new LoggingError("mergeTree client must exist");
1190
392
  }
@@ -1195,7 +397,7 @@ export class IntervalCollection extends TypedEventEmitter {
1195
397
  }, localSeq);
1196
398
  // if segment is undefined, it slid off the string
1197
399
  assert(segment !== undefined, 0x54e /* No segment found */);
1198
- const segoff = (_a = this.client.getSlideToSegment({ segment, offset })) !== null && _a !== void 0 ? _a : segment;
400
+ const segoff = getSlideToSegoff({ segment, offset }) ?? segment;
1199
401
  // case happens when rebasing op, but concurrently entire string has been deleted
1200
402
  if (segoff.segment === undefined || segoff.offset === undefined) {
1201
403
  return DetachedReferencePosition;
@@ -1207,7 +409,7 @@ export class IntervalCollection extends TypedEventEmitter {
1207
409
  assert(this.client !== undefined, 0x550 /* Client should be defined when computing rebased position */);
1208
410
  const original = this.localSeqToSerializedInterval.get(localSeq);
1209
411
  assert(original !== undefined, 0x551 /* Failed to store pending serialized interval info for this localSeq. */);
1210
- const rebased = Object.assign({}, original);
412
+ const rebased = { ...original };
1211
413
  const { start, end, sequenceNumber } = original;
1212
414
  if (start !== undefined) {
1213
415
  rebased.start = this.rebasePositionWithSegmentSlide(start, sequenceNumber, localSeq);
@@ -1234,7 +436,7 @@ export class IntervalCollection extends TypedEventEmitter {
1234
436
  }
1235
437
  });
1236
438
  }
1237
- this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true));
439
+ this.localCollection = new LocalIntervalCollection(client, label, this.helpers, (interval, previousInterval) => this.emitChange(interval, previousInterval, true, true));
1238
440
  if (this.savedSerializedIntervals) {
1239
441
  for (const serializedInterval of this.savedSerializedIntervals) {
1240
442
  this.localCollection.ensureSerializedId(serializedInterval);
@@ -1257,7 +459,7 @@ export class IntervalCollection extends TypedEventEmitter {
1257
459
  }
1258
460
  return 0;
1259
461
  }
1260
- emitChange(interval, previousInterval, local, op) {
462
+ emitChange(interval, previousInterval, local, slide, op) {
1261
463
  // Temporarily make references transient so that positional queries work (non-transient refs
1262
464
  // on resolve to DetachedPosition on any segments that don't contain them). The original refType
1263
465
  // is restored as single-endpoint changes re-use previous references.
@@ -1268,12 +470,12 @@ export class IntervalCollection extends TypedEventEmitter {
1268
470
  endRefType = previousInterval.end.refType;
1269
471
  previousInterval.start.refType = ReferenceType.Transient;
1270
472
  previousInterval.end.refType = ReferenceType.Transient;
1271
- this.emit("changeInterval", interval, previousInterval, local, op);
473
+ this.emit("changeInterval", interval, previousInterval, local, op, slide);
1272
474
  previousInterval.start.refType = startRefType;
1273
475
  previousInterval.end.refType = endRefType;
1274
476
  }
1275
477
  else {
1276
- this.emit("changeInterval", interval, previousInterval, local, op);
478
+ this.emit("changeInterval", interval, previousInterval, local, op, slide);
1277
479
  }
1278
480
  }
1279
481
  /**
@@ -1289,7 +491,6 @@ export class IntervalCollection extends TypedEventEmitter {
1289
491
  * {@inheritdoc IIntervalCollection.add}
1290
492
  */
1291
493
  add(start, end, intervalType, props, stickiness = IntervalStickiness.END) {
1292
- var _a, _b;
1293
494
  if (!this.localCollection) {
1294
495
  throw new LoggingError("attach must be called prior to adding intervals");
1295
496
  }
@@ -1305,7 +506,7 @@ export class IntervalCollection extends TypedEventEmitter {
1305
506
  end,
1306
507
  intervalType,
1307
508
  properties: interval.properties,
1308
- sequenceNumber: (_b = (_a = this.client) === null || _a === void 0 ? void 0 : _a.getCurrentSeq()) !== null && _b !== void 0 ? _b : 0,
509
+ sequenceNumber: this.client?.getCurrentSeq() ?? 0,
1309
510
  start,
1310
511
  stickiness,
1311
512
  };
@@ -1364,6 +565,11 @@ export class IntervalCollection extends TypedEventEmitter {
1364
565
  if (!props) {
1365
566
  throw new LoggingError("changeProperties should be called with a property set");
1366
567
  }
568
+ // prevent the overwriting of an interval label, it should remain unchanged
569
+ // once it has been inserted into the collection.
570
+ if (props[reservedRangeLabelsKey] !== undefined) {
571
+ throw new LoggingError("The label property should not be modified once inserted to the collection");
572
+ }
1367
573
  const interval = this.getIntervalById(id);
1368
574
  if (interval) {
1369
575
  // Pass Unassigned as the sequence number to indicate that this is a local op that is waiting for an ack.
@@ -1409,7 +615,7 @@ export class IntervalCollection extends TypedEventEmitter {
1409
615
  this.localSeqToSerializedInterval.set(localSeq, serializedInterval);
1410
616
  this.emitter.emit("change", undefined, serializedInterval, { localSeq });
1411
617
  this.addPendingChange(id, serializedInterval);
1412
- this.emitChange(newInterval, interval, true);
618
+ this.emitChange(newInterval, interval, true, false);
1413
619
  return newInterval;
1414
620
  }
1415
621
  // No interval to change
@@ -1432,9 +638,8 @@ export class IntervalCollection extends TypedEventEmitter {
1432
638
  entries.push(serializedInterval);
1433
639
  }
1434
640
  removePendingChange(serializedInterval) {
1435
- var _a;
1436
641
  // Change ops always have an ID.
1437
- const id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
642
+ const id = serializedInterval.properties?.[reservedIntervalIdKey];
1438
643
  if (serializedInterval.start !== undefined) {
1439
644
  this.removePendingChangeHelper(id, this.pendingChangesStart, serializedInterval);
1440
645
  }
@@ -1449,8 +654,8 @@ export class IntervalCollection extends TypedEventEmitter {
1449
654
  if (entries.length === 0) {
1450
655
  pendingChanges.delete(id);
1451
656
  }
1452
- if ((pendingChange === null || pendingChange === void 0 ? void 0 : pendingChange.start) !== serializedInterval.start ||
1453
- (pendingChange === null || pendingChange === void 0 ? void 0 : pendingChange.end) !== serializedInterval.end) {
657
+ if (pendingChange?.start !== serializedInterval.start ||
658
+ pendingChange?.end !== serializedInterval.end) {
1454
659
  throw new LoggingError("Mismatch in pending changes");
1455
660
  }
1456
661
  }
@@ -1465,20 +670,19 @@ export class IntervalCollection extends TypedEventEmitter {
1465
670
  }
1466
671
  /** @internal */
1467
672
  ackChange(serializedInterval, local, op, localOpMetadata) {
1468
- var _a, _b, _c, _d;
1469
673
  if (!this.localCollection) {
1470
674
  throw new LoggingError("Attach must be called before accessing intervals");
1471
675
  }
1472
676
  if (local) {
1473
677
  assert(localOpMetadata !== undefined, 0x552 /* op metadata should be defined for local op */);
1474
- this.localSeqToSerializedInterval.delete(localOpMetadata === null || localOpMetadata === void 0 ? void 0 : localOpMetadata.localSeq);
678
+ this.localSeqToSerializedInterval.delete(localOpMetadata?.localSeq);
1475
679
  // This is an ack from the server. Remove the pending change.
1476
680
  this.removePendingChange(serializedInterval);
1477
681
  }
1478
682
  // Note that the ID is in the property bag only to allow us to find the interval.
1479
683
  // This API cannot change the ID, and writing to the ID property will result in an exception. So we
1480
684
  // strip it out of the properties here.
1481
- const _e = (_a = serializedInterval.properties) !== null && _a !== void 0 ? _a : {}, _f = reservedIntervalIdKey, id = _e[_f], newProps = __rest(_e, [typeof _f === "symbol" ? _f : _f + ""]);
685
+ const { [reservedIntervalIdKey]: id, ...newProps } = serializedInterval.properties ?? {};
1482
686
  assert(id !== undefined, 0x3fe /* id must exist on the interval */);
1483
687
  const interval = this.getIntervalById(id);
1484
688
  if (!interval) {
@@ -1487,9 +691,9 @@ export class IntervalCollection extends TypedEventEmitter {
1487
691
  }
1488
692
  if (local) {
1489
693
  // Let the propertyManager prune its pending change-properties set.
1490
- (_b = interval.propertyManager) === null || _b === void 0 ? void 0 : _b.ackPendingProperties({
694
+ interval.propertyManager?.ackPendingProperties({
1491
695
  type: MergeTreeDeltaType.ANNOTATE,
1492
- props: (_c = serializedInterval.properties) !== null && _c !== void 0 ? _c : {},
696
+ props: serializedInterval.properties ?? {},
1493
697
  });
1494
698
  this.ackInterval(interval, op);
1495
699
  }
@@ -1510,14 +714,14 @@ export class IntervalCollection extends TypedEventEmitter {
1510
714
  // If changeInterval gives us a new interval, work with that one. Otherwise keep working with
1511
715
  // the one we originally found in the tree.
1512
716
  newInterval =
1513
- (_d = this.localCollection.changeInterval(interval, start, end, op)) !== null && _d !== void 0 ? _d : interval;
717
+ this.localCollection.changeInterval(interval, start, end, op) ?? interval;
1514
718
  }
1515
719
  const deltaProps = newInterval.addProperties(newProps, true, op.sequenceNumber);
1516
720
  if (this.onDeserialize) {
1517
721
  this.onDeserialize(newInterval);
1518
722
  }
1519
723
  if (newInterval !== interval) {
1520
- this.emitChange(newInterval, interval, local, op);
724
+ this.emitChange(newInterval, interval, local, false, op);
1521
725
  }
1522
726
  const changedProperties = Object.keys(newProps).length > 0;
1523
727
  if (changedProperties) {
@@ -1525,18 +729,6 @@ export class IntervalCollection extends TypedEventEmitter {
1525
729
  }
1526
730
  }
1527
731
  }
1528
- /**
1529
- * @deprecated - This functionality was useful when adding two intervals at the same start/end positions resulted
1530
- * in a conflict. This is no longer the case (as of PR#6407), as interval collections support multiple intervals
1531
- * at the same location and gives each interval a unique id.
1532
- *
1533
- * As such, the conflict resolver is never invoked and unnecessary. This API will be removed in an upcoming release.
1534
- */
1535
- addConflictResolver(_) {
1536
- if (!this.localCollection) {
1537
- throw new LoggingError("attachSequence must be called");
1538
- }
1539
- }
1540
732
  /**
1541
733
  * {@inheritdoc IIntervalCollection.attachDeserializer}
1542
734
  */
@@ -1560,7 +752,6 @@ export class IntervalCollection extends TypedEventEmitter {
1560
752
  * @internal
1561
753
  */
1562
754
  rebaseLocalInterval(opName, serializedInterval, localSeq) {
1563
- var _a, _b, _c, _d, _e, _f;
1564
755
  if (!this.client) {
1565
756
  // If there's no associated mergeTree client, the originally submitted op is still correct.
1566
757
  return serializedInterval;
@@ -1569,14 +760,14 @@ export class IntervalCollection extends TypedEventEmitter {
1569
760
  throw new LoggingError("attachSequence must be called");
1570
761
  }
1571
762
  const { intervalType, properties } = serializedInterval;
1572
- const { start: startRebased, end: endRebased } = (_a = this.localSeqToRebasedInterval.get(localSeq)) !== null && _a !== void 0 ? _a : this.computeRebasedPositions(localSeq);
1573
- const intervalId = properties === null || properties === void 0 ? void 0 : properties[reservedIntervalIdKey];
1574
- const localInterval = (_b = this.localCollection) === null || _b === void 0 ? void 0 : _b.idIntervalIndex.getIntervalById(intervalId);
763
+ const { start: startRebased, end: endRebased } = this.localSeqToRebasedInterval.get(localSeq) ?? this.computeRebasedPositions(localSeq);
764
+ const intervalId = properties?.[reservedIntervalIdKey];
765
+ const localInterval = this.localCollection?.idIntervalIndex.getIntervalById(intervalId);
1575
766
  const rebased = {
1576
767
  start: startRebased,
1577
768
  end: endRebased,
1578
769
  intervalType,
1579
- sequenceNumber: (_d = (_c = this.client) === null || _c === void 0 ? void 0 : _c.getCurrentSeq()) !== null && _d !== void 0 ? _d : 0,
770
+ sequenceNumber: this.client?.getCurrentSeq() ?? 0,
1580
771
  properties,
1581
772
  };
1582
773
  if (opName === "change" &&
@@ -1588,7 +779,7 @@ export class IntervalCollection extends TypedEventEmitter {
1588
779
  if (startRebased === DetachedReferencePosition ||
1589
780
  endRebased === DetachedReferencePosition) {
1590
781
  if (localInterval) {
1591
- (_e = this.localCollection) === null || _e === void 0 ? void 0 : _e.removeExistingInterval(localInterval);
782
+ this.localCollection?.removeExistingInterval(localInterval);
1592
783
  }
1593
784
  return undefined;
1594
785
  }
@@ -1597,20 +788,19 @@ export class IntervalCollection extends TypedEventEmitter {
1597
788
  assert(localInterval instanceof SequenceInterval, 0x3a0 /* localInterval must be `SequenceInterval` when used with client */);
1598
789
  // The rebased op may place this interval's endpoints on different segments. Calling `changeInterval` here
1599
790
  // updates the local client's state to be consistent with the emitted op.
1600
- (_f = this.localCollection) === null || _f === void 0 ? void 0 : _f.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
791
+ this.localCollection?.changeInterval(localInterval, startRebased, endRebased, undefined, localSeq);
1601
792
  }
1602
793
  return rebased;
1603
794
  }
1604
795
  getSlideToSegment(lref) {
1605
- var _a, _b;
1606
796
  if (!this.client) {
1607
797
  throw new LoggingError("client does not exist");
1608
798
  }
1609
799
  const segoff = { segment: lref.getSegment(), offset: lref.getOffset() };
1610
- if (((_b = (_a = segoff.segment) === null || _a === void 0 ? void 0 : _a.localRefs) === null || _b === void 0 ? void 0 : _b.has(lref)) !== true) {
800
+ if (segoff.segment?.localRefs?.has(lref) !== true) {
1611
801
  return undefined;
1612
802
  }
1613
- const newSegoff = this.client.getSlideToSegment(segoff);
803
+ const newSegoff = getSlideToSegoff(segoff);
1614
804
  const value = segoff.segment === newSegoff.segment && segoff.offset === newSegoff.offset
1615
805
  ? undefined
1616
806
  : newSegoff;
@@ -1623,7 +813,6 @@ export class IntervalCollection extends TypedEventEmitter {
1623
813
  lref.refType = refType;
1624
814
  }
1625
815
  ackInterval(interval, op) {
1626
- var _a, _b;
1627
816
  // Only SequenceIntervals need potential sliding
1628
817
  if (!(interval instanceof SequenceInterval)) {
1629
818
  return;
@@ -1668,7 +857,7 @@ export class IntervalCollection extends TypedEventEmitter {
1668
857
  // remove and rebuild start interval as transient for event
1669
858
  this.client.removeLocalReferencePosition(oldInterval.start);
1670
859
  oldInterval.start.refType = ReferenceType.Transient;
1671
- (_a = oldSeg === null || oldSeg === void 0 ? void 0 : oldSeg.localRefs) === null || _a === void 0 ? void 0 : _a.addLocalRef(oldInterval.start, oldInterval.start.getOffset());
860
+ oldSeg?.localRefs?.addLocalRef(oldInterval.start, oldInterval.start.getOffset());
1672
861
  }
1673
862
  if (needsEndUpdate) {
1674
863
  const props = interval.end.properties;
@@ -1680,19 +869,18 @@ export class IntervalCollection extends TypedEventEmitter {
1680
869
  const oldSeg = oldInterval.end.getSegment();
1681
870
  this.client.removeLocalReferencePosition(oldInterval.end);
1682
871
  oldInterval.end.refType = ReferenceType.Transient;
1683
- (_b = oldSeg === null || oldSeg === void 0 ? void 0 : oldSeg.localRefs) === null || _b === void 0 ? void 0 : _b.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
872
+ oldSeg?.localRefs?.addLocalRef(oldInterval.end, oldInterval.end.getOffset());
1684
873
  }
1685
874
  this.localCollection.add(interval);
1686
- this.emitChange(interval, oldInterval, true, op);
875
+ this.emitChange(interval, oldInterval, true, true, op);
1687
876
  }
1688
877
  }
1689
878
  /** @internal */
1690
879
  ackAdd(serializedInterval, local, op, localOpMetadata) {
1691
- var _a;
1692
880
  if (local) {
1693
881
  assert(localOpMetadata !== undefined, 0x553 /* op metadata should be defined for local op */);
1694
882
  this.localSeqToSerializedInterval.delete(localOpMetadata.localSeq);
1695
- const id = (_a = serializedInterval.properties) === null || _a === void 0 ? void 0 : _a[reservedIntervalIdKey];
883
+ const id = serializedInterval.properties?.[reservedIntervalIdKey];
1696
884
  const localInterval = this.getIntervalById(id);
1697
885
  if (localInterval) {
1698
886
  this.ackInterval(localInterval, op);
@@ -1828,9 +1016,8 @@ export class IntervalCollection extends TypedEventEmitter {
1828
1016
  * endpoint is a part of.
1829
1017
  */
1830
1018
  export function intervalLocatorFromEndpoint(potentialEndpoint) {
1831
- var _a;
1832
- const { interval, [reservedRangeLabelsKey]: collectionNameArray } = (_a = potentialEndpoint.properties) !== null && _a !== void 0 ? _a : {};
1833
- return interval && (collectionNameArray === null || collectionNameArray === void 0 ? void 0 : collectionNameArray.length) === 1
1019
+ const { interval, [reservedRangeLabelsKey]: collectionNameArray } = potentialEndpoint.properties ?? {};
1020
+ return interval && collectionNameArray?.length === 1
1834
1021
  ? { label: collectionNameArray[0], interval }
1835
1022
  : undefined;
1836
1023
  }