@fluid-experimental/tree 0.59.2001 → 0.59.3000

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 (258) hide show
  1. package/.eslintrc.js +2 -0
  2. package/.vscode/SharedTree.code-workspace +15 -0
  3. package/.vscode/settings.json +6 -0
  4. package/dist/ChangeCompression.js +9 -9
  5. package/dist/ChangeCompression.js.map +1 -1
  6. package/dist/ChangeTypes.d.ts +1 -6
  7. package/dist/ChangeTypes.d.ts.map +1 -1
  8. package/dist/ChangeTypes.js +5 -5
  9. package/dist/ChangeTypes.js.map +1 -1
  10. package/dist/Checkout.js +14 -14
  11. package/dist/Checkout.js.map +1 -1
  12. package/dist/Common.d.ts +21 -3
  13. package/dist/Common.d.ts.map +1 -1
  14. package/dist/Common.js +29 -4
  15. package/dist/Common.js.map +1 -1
  16. package/dist/EditLog.js +26 -25
  17. package/dist/EditLog.js.map +1 -1
  18. package/dist/EditUtilities.js +17 -17
  19. package/dist/EditUtilities.js.map +1 -1
  20. package/dist/Forest.js +31 -31
  21. package/dist/Forest.js.map +1 -1
  22. package/dist/HistoryEditFactory.js +9 -9
  23. package/dist/HistoryEditFactory.js.map +1 -1
  24. package/dist/IdConversion.js +9 -9
  25. package/dist/IdConversion.js.map +1 -1
  26. package/dist/Identifiers.d.ts +4 -0
  27. package/dist/Identifiers.d.ts.map +1 -1
  28. package/dist/Identifiers.js.map +1 -1
  29. package/dist/LogViewer.d.ts +1 -5
  30. package/dist/LogViewer.d.ts.map +1 -1
  31. package/dist/LogViewer.js +11 -19
  32. package/dist/LogViewer.js.map +1 -1
  33. package/dist/MergeHealth.js +2 -2
  34. package/dist/MergeHealth.js.map +1 -1
  35. package/dist/NodeIdUtilities.js +2 -2
  36. package/dist/NodeIdUtilities.js.map +1 -1
  37. package/dist/PayloadUtilities.js +1 -1
  38. package/dist/PayloadUtilities.js.map +1 -1
  39. package/dist/RevisionValueCache.d.ts +13 -10
  40. package/dist/RevisionValueCache.d.ts.map +1 -1
  41. package/dist/RevisionValueCache.js +14 -11
  42. package/dist/RevisionValueCache.js.map +1 -1
  43. package/dist/RevisionView.js +4 -4
  44. package/dist/RevisionView.js.map +1 -1
  45. package/dist/SerializationUtilities.js +4 -4
  46. package/dist/SerializationUtilities.js.map +1 -1
  47. package/dist/SharedTree.d.ts +93 -31
  48. package/dist/SharedTree.d.ts.map +1 -1
  49. package/dist/SharedTree.js +160 -131
  50. package/dist/SharedTree.js.map +1 -1
  51. package/dist/SharedTreeEncoder.d.ts +3 -3
  52. package/dist/SharedTreeEncoder.d.ts.map +1 -1
  53. package/dist/SharedTreeEncoder.js +36 -36
  54. package/dist/SharedTreeEncoder.js.map +1 -1
  55. package/dist/StringInterner.js +1 -1
  56. package/dist/StringInterner.js.map +1 -1
  57. package/dist/Summary.js +1 -1
  58. package/dist/Summary.js.map +1 -1
  59. package/dist/SummaryBackCompatibility.js +8 -8
  60. package/dist/SummaryBackCompatibility.js.map +1 -1
  61. package/dist/Transaction.js +1 -1
  62. package/dist/Transaction.js.map +1 -1
  63. package/dist/TransactionInternal.js +17 -17
  64. package/dist/TransactionInternal.js.map +1 -1
  65. package/dist/TreeCompressor.d.ts.map +1 -1
  66. package/dist/TreeCompressor.js +6 -8
  67. package/dist/TreeCompressor.js.map +1 -1
  68. package/dist/TreeNodeHandle.js +4 -4
  69. package/dist/TreeNodeHandle.js.map +1 -1
  70. package/dist/TreeView.js +7 -7
  71. package/dist/TreeView.js.map +1 -1
  72. package/dist/TreeViewUtilities.js +2 -2
  73. package/dist/TreeViewUtilities.js.map +1 -1
  74. package/dist/UndoRedoHandler.js +1 -1
  75. package/dist/UndoRedoHandler.js.map +1 -1
  76. package/dist/UuidUtilities.d.ts +30 -0
  77. package/dist/UuidUtilities.d.ts.map +1 -0
  78. package/dist/UuidUtilities.js +106 -0
  79. package/dist/UuidUtilities.js.map +1 -0
  80. package/dist/id-compressor/AppendOnlySortedMap.d.ts +52 -28
  81. package/dist/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
  82. package/dist/id-compressor/AppendOnlySortedMap.js +167 -90
  83. package/dist/id-compressor/AppendOnlySortedMap.js.map +1 -1
  84. package/dist/id-compressor/IdCompressor.d.ts +43 -42
  85. package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
  86. package/dist/id-compressor/IdCompressor.js +179 -177
  87. package/dist/id-compressor/IdCompressor.js.map +1 -1
  88. package/dist/id-compressor/IdRange.js +1 -1
  89. package/dist/id-compressor/IdRange.js.map +1 -1
  90. package/dist/id-compressor/NumericUuid.d.ts +6 -14
  91. package/dist/id-compressor/NumericUuid.d.ts.map +1 -1
  92. package/dist/id-compressor/NumericUuid.js +15 -76
  93. package/dist/id-compressor/NumericUuid.js.map +1 -1
  94. package/dist/id-compressor/SessionIdNormalizer.d.ts +122 -0
  95. package/dist/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
  96. package/dist/id-compressor/SessionIdNormalizer.js +418 -0
  97. package/dist/id-compressor/SessionIdNormalizer.js.map +1 -0
  98. package/dist/id-compressor/persisted-types/0.0.1.d.ts +6 -13
  99. package/dist/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  100. package/dist/id-compressor/persisted-types/0.0.1.js.map +1 -1
  101. package/dist/index.d.ts +2 -2
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js.map +1 -1
  104. package/dist/persisted-types/0.1.1.d.ts +1 -6
  105. package/dist/persisted-types/0.1.1.d.ts.map +1 -1
  106. package/dist/persisted-types/0.1.1.js +3 -3
  107. package/dist/persisted-types/0.1.1.js.map +1 -1
  108. package/lib/ChangeTypes.d.ts +1 -6
  109. package/lib/ChangeTypes.d.ts.map +1 -1
  110. package/lib/Checkout.js.map +1 -1
  111. package/lib/Common.d.ts +21 -3
  112. package/lib/Common.d.ts.map +1 -1
  113. package/lib/Common.js +25 -3
  114. package/lib/Common.js.map +1 -1
  115. package/lib/EditLog.js +2 -1
  116. package/lib/EditLog.js.map +1 -1
  117. package/lib/EditUtilities.js.map +1 -1
  118. package/lib/Forest.js.map +1 -1
  119. package/lib/HistoryEditFactory.js.map +1 -1
  120. package/lib/Identifiers.d.ts +4 -0
  121. package/lib/Identifiers.d.ts.map +1 -1
  122. package/lib/Identifiers.js.map +1 -1
  123. package/lib/LogViewer.d.ts +1 -5
  124. package/lib/LogViewer.d.ts.map +1 -1
  125. package/lib/LogViewer.js +5 -13
  126. package/lib/LogViewer.js.map +1 -1
  127. package/lib/MergeHealth.js.map +1 -1
  128. package/lib/NodeIdUtilities.js.map +1 -1
  129. package/lib/RevisionValueCache.d.ts +13 -10
  130. package/lib/RevisionValueCache.d.ts.map +1 -1
  131. package/lib/RevisionValueCache.js +10 -7
  132. package/lib/RevisionValueCache.js.map +1 -1
  133. package/lib/RevisionView.js.map +1 -1
  134. package/lib/SharedTree.d.ts +93 -31
  135. package/lib/SharedTree.d.ts.map +1 -1
  136. package/lib/SharedTree.js +107 -78
  137. package/lib/SharedTree.js.map +1 -1
  138. package/lib/SharedTreeEncoder.d.ts +3 -3
  139. package/lib/SharedTreeEncoder.d.ts.map +1 -1
  140. package/lib/SharedTreeEncoder.js +4 -4
  141. package/lib/SharedTreeEncoder.js.map +1 -1
  142. package/lib/StringInterner.js.map +1 -1
  143. package/lib/Summary.js.map +1 -1
  144. package/lib/TreeCompressor.d.ts.map +1 -1
  145. package/lib/TreeCompressor.js +1 -3
  146. package/lib/TreeCompressor.js.map +1 -1
  147. package/lib/TreeNodeHandle.js.map +1 -1
  148. package/lib/TreeView.js.map +1 -1
  149. package/lib/TreeViewUtilities.js.map +1 -1
  150. package/lib/UuidUtilities.d.ts +30 -0
  151. package/lib/UuidUtilities.d.ts.map +1 -0
  152. package/lib/UuidUtilities.js +98 -0
  153. package/lib/UuidUtilities.js.map +1 -0
  154. package/lib/id-compressor/AppendOnlySortedMap.d.ts +52 -28
  155. package/lib/id-compressor/AppendOnlySortedMap.d.ts.map +1 -1
  156. package/lib/id-compressor/AppendOnlySortedMap.js +165 -88
  157. package/lib/id-compressor/AppendOnlySortedMap.js.map +1 -1
  158. package/lib/id-compressor/IdCompressor.d.ts +43 -42
  159. package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
  160. package/lib/id-compressor/IdCompressor.js +97 -95
  161. package/lib/id-compressor/IdCompressor.js.map +1 -1
  162. package/lib/id-compressor/NumericUuid.d.ts +6 -14
  163. package/lib/id-compressor/NumericUuid.d.ts.map +1 -1
  164. package/lib/id-compressor/NumericUuid.js +11 -70
  165. package/lib/id-compressor/NumericUuid.js.map +1 -1
  166. package/lib/id-compressor/SessionIdNormalizer.d.ts +122 -0
  167. package/lib/id-compressor/SessionIdNormalizer.d.ts.map +1 -0
  168. package/lib/id-compressor/SessionIdNormalizer.js +414 -0
  169. package/lib/id-compressor/SessionIdNormalizer.js.map +1 -0
  170. package/lib/id-compressor/persisted-types/0.0.1.d.ts +6 -13
  171. package/lib/id-compressor/persisted-types/0.0.1.d.ts.map +1 -1
  172. package/lib/id-compressor/persisted-types/0.0.1.js.map +1 -1
  173. package/lib/index.d.ts +2 -2
  174. package/lib/index.d.ts.map +1 -1
  175. package/lib/index.js.map +1 -1
  176. package/lib/persisted-types/0.1.1.d.ts +1 -6
  177. package/lib/persisted-types/0.1.1.d.ts.map +1 -1
  178. package/lib/persisted-types/0.1.1.js.map +1 -1
  179. package/lib/test/AppendOnlySortedMap.perf.tests.d.ts +6 -0
  180. package/lib/test/AppendOnlySortedMap.perf.tests.d.ts.map +1 -0
  181. package/lib/test/AppendOnlySortedMap.perf.tests.js +49 -0
  182. package/lib/test/AppendOnlySortedMap.perf.tests.js.map +1 -0
  183. package/lib/test/AppendOnlySortedMap.tests.js +56 -14
  184. package/lib/test/AppendOnlySortedMap.tests.js.map +1 -1
  185. package/lib/test/Checkout.tests.js +2 -2
  186. package/lib/test/Checkout.tests.js.map +1 -1
  187. package/lib/test/Forest.tests.js.map +1 -1
  188. package/lib/test/IdCompressor.perf.tests.js +8 -2
  189. package/lib/test/IdCompressor.perf.tests.js.map +1 -1
  190. package/lib/test/IdCompressor.tests.js +75 -24
  191. package/lib/test/IdCompressor.tests.js.map +1 -1
  192. package/lib/test/LogViewer.tests.js +3 -5
  193. package/lib/test/LogViewer.tests.js.map +1 -1
  194. package/lib/test/NumericUuid.perf.tests.js +4 -4
  195. package/lib/test/NumericUuid.perf.tests.js.map +1 -1
  196. package/lib/test/NumericUuid.tests.js +5 -4
  197. package/lib/test/NumericUuid.tests.js.map +1 -1
  198. package/lib/test/RevisionValueCache.tests.js.map +1 -1
  199. package/lib/test/RevisionView.tests.js.map +1 -1
  200. package/lib/test/SessionIdNormalizer.tests.d.ts +6 -0
  201. package/lib/test/SessionIdNormalizer.tests.d.ts.map +1 -0
  202. package/lib/test/SessionIdNormalizer.tests.js +299 -0
  203. package/lib/test/SessionIdNormalizer.tests.js.map +1 -0
  204. package/lib/test/Summary.tests.js +1 -1
  205. package/lib/test/Summary.tests.js.map +1 -1
  206. package/lib/test/TreeCompression.tests.js +1 -1
  207. package/lib/test/TreeCompression.tests.js.map +1 -1
  208. package/lib/test/Virtualization.tests.js +1 -1
  209. package/lib/test/Virtualization.tests.js.map +1 -1
  210. package/lib/test/fuzz/Generators.d.ts +3 -14
  211. package/lib/test/fuzz/Generators.d.ts.map +1 -1
  212. package/lib/test/fuzz/Generators.js +60 -151
  213. package/lib/test/fuzz/Generators.js.map +1 -1
  214. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts +10 -7
  215. package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
  216. package/lib/test/fuzz/SharedTreeFuzzTests.js +94 -104
  217. package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
  218. package/lib/test/fuzz/Types.d.ts +2 -9
  219. package/lib/test/fuzz/Types.d.ts.map +1 -1
  220. package/lib/test/fuzz/Types.js +1 -1
  221. package/lib/test/fuzz/Types.js.map +1 -1
  222. package/lib/test/utilities/IdCompressorTestUtilities.d.ts +57 -11
  223. package/lib/test/utilities/IdCompressorTestUtilities.d.ts.map +1 -1
  224. package/lib/test/utilities/IdCompressorTestUtilities.js +112 -98
  225. package/lib/test/utilities/IdCompressorTestUtilities.js.map +1 -1
  226. package/lib/test/utilities/PendingLocalStateTests.d.ts.map +1 -1
  227. package/lib/test/utilities/PendingLocalStateTests.js +2 -1
  228. package/lib/test/utilities/PendingLocalStateTests.js.map +1 -1
  229. package/lib/test/utilities/SharedTreeTests.d.ts.map +1 -1
  230. package/lib/test/utilities/SharedTreeTests.js +30 -1
  231. package/lib/test/utilities/SharedTreeTests.js.map +1 -1
  232. package/lib/test/utilities/SharedTreeVersioningTests.d.ts.map +1 -1
  233. package/lib/test/utilities/SharedTreeVersioningTests.js +20 -0
  234. package/lib/test/utilities/SharedTreeVersioningTests.js.map +1 -1
  235. package/lib/test/utilities/SummaryLoadPerfTests.d.ts.map +1 -1
  236. package/lib/test/utilities/SummaryLoadPerfTests.js +6 -3
  237. package/lib/test/utilities/SummaryLoadPerfTests.js.map +1 -1
  238. package/lib/test/utilities/TestNode.js.map +1 -1
  239. package/lib/test/utilities/TestUtilities.d.ts +9 -1
  240. package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
  241. package/lib/test/utilities/TestUtilities.js +27 -13
  242. package/lib/test/utilities/TestUtilities.js.map +1 -1
  243. package/package.json +19 -17
  244. package/src/Common.ts +42 -4
  245. package/src/EditLog.ts +1 -1
  246. package/src/Identifiers.ts +5 -0
  247. package/src/LogViewer.ts +4 -20
  248. package/src/RevisionValueCache.ts +11 -8
  249. package/src/SharedTree.ts +222 -75
  250. package/src/SharedTreeEncoder.ts +17 -11
  251. package/src/TreeCompressor.ts +2 -4
  252. package/src/UuidUtilities.ts +123 -0
  253. package/src/id-compressor/AppendOnlySortedMap.ts +183 -94
  254. package/src/id-compressor/IdCompressor.ts +144 -132
  255. package/src/id-compressor/NumericUuid.ts +11 -80
  256. package/src/id-compressor/SessionIdNormalizer.ts +497 -0
  257. package/src/id-compressor/persisted-types/0.0.1.ts +12 -15
  258. package/src/index.ts +5 -0
package/dist/Common.js CHANGED
@@ -4,7 +4,7 @@
4
4
  * Licensed under the MIT License.
5
5
  */
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.Result = exports.backmap = exports.compareBtrees = exports.setPropertyIfDefined = exports.copyPropertyIfDefined = exports.identity = exports.noop = exports.getOrCreate = exports.compareMaps = exports.compareArrays = exports.compareIterables = exports.find = exports.reduce = exports.filter = exports.map = exports.memoizeGetter = exports.assign = exports.assertArrayOfOne = exports.assertNotUndefined = exports.fail = exports.assert = exports.compareStrings = exports.compareFiniteNumbers = exports.isSharedTreeEvent = exports.sharedTreeAssertionErrorType = void 0;
7
+ exports.hasLength = exports.hasExactlyLength = exports.Result = exports.backmap = exports.compareBtrees = exports.setPropertyIfDefined = exports.copyPropertyIfDefined = exports.identity = exports.noop = exports.getOrCreate = exports.compareMaps = exports.compareArrays = exports.compareIterables = exports.find = exports.reduce = exports.filter = exports.map = exports.memoizeGetter = exports.assign = exports.assertArrayOfOne = exports.assertNotUndefined = exports.fail = exports.assert = exports.compareStrings = exports.compareFiniteNumbersReversed = exports.compareFiniteNumbers = exports.isSharedTreeEvent = exports.sharedTreeAssertionErrorType = void 0;
8
8
  const defaultFailMessage = 'Assertion failed';
9
9
  /**
10
10
  * Assertion failures in SharedTree will throw an exception containing this value as an `errorType`. The Fluid runtime propagates this field
@@ -37,7 +37,7 @@ class SharedTreeAssertionError extends Error {
37
37
  }
38
38
  }
39
39
  /**
40
- * Compares finite numbers to form a strict partial ordering.
40
+ * A numeric comparator used for sorting in ascending order.
41
41
  *
42
42
  * Handles +/-0 like Map: -0 is equal to +0.
43
43
  */
@@ -45,6 +45,15 @@ function compareFiniteNumbers(a, b) {
45
45
  return a - b;
46
46
  }
47
47
  exports.compareFiniteNumbers = compareFiniteNumbers;
48
+ /**
49
+ * A numeric comparator used for sorting in descending order.
50
+ *
51
+ * Handles +/-0 like Map: -0 is equal to +0.
52
+ */
53
+ function compareFiniteNumbersReversed(a, b) {
54
+ return b - a;
55
+ }
56
+ exports.compareFiniteNumbersReversed = compareFiniteNumbersReversed;
48
57
  /**
49
58
  * Compares strings lexically to form a strict partial ordering.
50
59
  */
@@ -278,13 +287,13 @@ exports.compareMaps = compareMaps;
278
287
  * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.
279
288
  * @param map - the map to query/update
280
289
  * @param key - the key to lookup in the map
281
- * @param defaultValue - a function which returns a default value. This is called and used to set an initial value in the map if none exists
290
+ * @param defaultValue - a function which returns a default value. This is called and used to set an initial value for the given key in the map if none exists
282
291
  * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)
283
292
  */
284
293
  function getOrCreate(map, key, defaultValue) {
285
294
  let value = map.get(key);
286
295
  if (value === undefined) {
287
- value = defaultValue();
296
+ value = defaultValue(key);
288
297
  map.set(key, value);
289
298
  }
290
299
  return value;
@@ -326,6 +335,7 @@ function setPropertyIfDefined(value, destination, property) {
326
335
  }
327
336
  exports.setPropertyIfDefined = setPropertyIfDefined;
328
337
  /**
338
+ * ```
329
339
  * function (thing: ObjectWithMaybeFoo) {
330
340
  * const x: MyActualType = {
331
341
  * bar: 3
@@ -334,6 +344,7 @@ exports.setPropertyIfDefined = setPropertyIfDefined;
334
344
  *
335
345
  * copyPropertyIfDefined(thing, x, 'foo');
336
346
  * }
347
+ * ```
337
348
  * @returns
338
349
  */
339
350
  function breakOnDifference() {
@@ -422,4 +433,18 @@ var Result;
422
433
  ResultType[ResultType["Error"] = 1] = "Error";
423
434
  })(ResultType = Result.ResultType || (Result.ResultType = {}));
424
435
  })(Result = exports.Result || (exports.Result = {}));
436
+ /**
437
+ * Fails if `array` does not have exactly `length` elements
438
+ */
439
+ function hasExactlyLength(array, length) {
440
+ return array.length === length;
441
+ }
442
+ exports.hasExactlyLength = hasExactlyLength;
443
+ /**
444
+ * Fails if `array` does not have at least `length` elements
445
+ */
446
+ function hasLength(array, length) {
447
+ return array.length >= length;
448
+ }
449
+ exports.hasLength = hasLength;
425
450
  //# sourceMappingURL=Common.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Common.js","sourceRoot":"","sources":["../src/Common.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseEvent, ITelemetryProperties } from '@fluidframework/common-definitions';\nimport BTree from 'sorted-btree';\n\nconst defaultFailMessage = 'Assertion failed';\n\n/**\n * Assertion failures in SharedTree will throw an exception containing this value as an `errorType`. The Fluid runtime propagates this field\n * in its handlings of errors thrown by containers. See\n * https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-utils/src/error.ts\n *\n * Exporting this enables users to safely filter telemetry handling of errors based on their type.\n *\n * @public\n */\nexport const sharedTreeAssertionErrorType = 'SharedTreeAssertion';\n\n/**\n * Telemetry properties decorated on all SharedTree events.\n */\nexport interface SharedTreeTelemetryProperties extends ITelemetryProperties {\n\treadonly isSharedTreeEvent: true;\n}\n\n/**\n * Returns if the supplied event is a SharedTree telemetry event.\n */\nexport function isSharedTreeEvent(event: ITelemetryBaseEvent): boolean {\n\treturn (event as unknown as SharedTreeTelemetryProperties).isSharedTreeEvent === true;\n}\n\n/**\n * Error object thrown by assertion failures in `SharedTree`.\n */\nclass SharedTreeAssertionError extends Error {\n\tpublic readonly errorType = sharedTreeAssertionErrorType;\n\n\tpublic constructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'Assertion error';\n\t\t// Note: conditional as `captureStackTrace` isn't defined in all browsers (e.g. Safari).\n\t\tError.captureStackTrace?.(this);\n\t}\n}\n\n/**\n * Compares finite numbers to form a strict partial ordering.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbers<T extends number>(a: T, b: T): number {\n\treturn a - b;\n}\n\n/**\n * Compares strings lexically to form a strict partial ordering.\n */\nexport function compareStrings<T extends string>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\n/**\n * Asserts against a boolean condition. Throws an Error if the assertion failed. Will run and throw in release builds.\n * Use when violations are logic errors in the program.\n * @param condition - A condition to assert is truthy\n * @param message - Message to be printed if assertion fails. Will print \"Assertion failed\" by default\n * @param containsPII - boolean flag for whether the message passed in contains personally identifying information (PII).\n */\nexport function assert(condition: unknown, message?: string, containsPII = false): asserts condition {\n\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\tif (!condition) {\n\t\tfail(message, containsPII);\n\t}\n}\n\n/**\n * Fails an assertion. Throws an Error that the assertion failed.\n * Use when violations are logic errors in the program.\n * @param message - Message to be printed if assertion fails. Will print \"Assertion failed\" by default\n * @param containsPII - boolean flag for whether the message passed in contains personally identifying information (PII).\n */\nexport function fail(message: string = defaultFailMessage, containsPII = false): never {\n\tif (process.env.NODE_ENV !== 'production') {\n\t\tdebugger;\n\t\tconsole.error(message);\n\t}\n\n\tthrow new SharedTreeAssertionError(containsPII ? 'Assertion failed' : message);\n}\n\n/**\n * Asserts a value is not undefined, and returns the value.\n * Use when violations are logic errors in the program.\n *\n * When practical, prefer the pattern `x ?? fail('message')` over `assertNotUndefined(x, 'message')`.\n * Using `?? fail` allows for message formatting without incurring the cost of formatting the message in the non failing case\n * (ex:\n * ```\n * x ?? fail(`x should exist for ${y}`)\n * ```\n * ). Additionally the `?? fail` avoids an extra call/stack frame in the non failing case.\n *\n * Another pattern to prefer over `assertNotUndefined(x, 'message')` is `assert(x !== undefined)`.\n * This pattern is preferred because it is more general (same approach works with typeof, instance of, comparison to other values etc.).\n *\n * @param value - Value to assert against is non undefined.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertNotUndefined<T>(value: T | undefined, message = 'value must not be undefined'): T {\n\tassert(value !== undefined, message);\n\treturn value;\n}\n\n/**\n * Asserts an array contains a single value and returns the value.\n * @param array - array to assert contains a single value.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertArrayOfOne<T>(array: readonly T[], message = 'array value must contain exactly one item'): T {\n\tassert(array.length === 1, message);\n\treturn array[0];\n}\n\n/**\n * Assign a property and value to a given object.\n * @param object - the object to add the property to\n * @param property - the property key\n * @param value - the value of the property\n * @returns `object` after assigning `value` to the property `property`.\n */\nexport function assign<T, K extends keyof never, V>(object: T, property: K, value: V): With<T, K, V> {\n\treturn Object.assign(object, { [property]: value }) as With<T, K, V>;\n}\n\n/**\n * Redefine a property to have the given value. This is simply a type-safe wrapper around\n * `Object.defineProperty`, but it is useful for caching public getters on first read.\n * @example\n * ```\n * // `randomOnce()` will return a random number, but always the same random number.\n * {\n * get randomOnce(): number {\n * return memoizeGetter(this, 'randomOnce', random(100))\n * }\n * }\n * ```\n * @param object - the object containing the property\n * @param propName - the name of the property on the object\n * @param value - the value of the property\n */\nexport function memoizeGetter<T, K extends keyof T>(object: T, propName: K, value: T[K]): T[K] {\n\tObject.defineProperty(object, propName, {\n\t\tvalue,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n\n\treturn value;\n}\n\n/**\n * Map an iterable to another iterable\n */\nexport function* map<T, R>(sequence: Iterable<T>, mapper: (t: T) => R): Iterable<R> {\n\tfor (const t of sequence) {\n\t\tyield mapper(t);\n\t}\n}\n\n/**\n * Filter an iterable into another iterable\n */\nexport function* filter<T>(sequence: Iterable<T>, filter: (t: T) => boolean): Iterable<T> {\n\tfor (const t of sequence) {\n\t\tif (filter(t)) {\n\t\t\tyield t;\n\t\t}\n\t}\n}\n\n/**\n * Reduce an iterable into a single value, or undefined if the iterable has too few elements to reduce\n */\nexport function reduce<T>(\n\tsequence: Iterable<T>,\n\treduce: (previous: T, current: T) => T,\n\tinitialValue?: T\n): T | undefined {\n\tlet previous: T | undefined;\n\tlet current: T | undefined;\n\tfor (const t of sequence) {\n\t\tcurrent = t;\n\t\tif (previous === undefined) {\n\t\t\tif (initialValue !== undefined) {\n\t\t\t\tcurrent = reduce(initialValue, current);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent = reduce(previous, current);\n\t\t}\n\t\tprevious = current;\n\t}\n\treturn current;\n}\n\n/**\n * Returns the first element of the given sequence that satisfies the given predicate, or undefined if no such element exists\n */\nexport function find<T>(sequence: Iterable<T>, find: (t: T) => boolean): T | undefined {\n\tfor (const t of sequence) {\n\t\tif (find(t)) {\n\t\t\treturn t;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Iterate through two iterables and return true if they yield equivalent elements in the same order.\n * @param iterableA - the first iterable to compare\n * @param iterableB - the second iterable to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareIterables<T>(\n\titerableA: Iterable<T>,\n\titerableB: Iterable<T>,\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\treturn compareIterators<T>(iterableA[Symbol.iterator](), iterableB[Symbol.iterator](), elementComparator);\n}\n\n/**\n * Iterate through two iterators and return true if they yield equivalent elements in the same order.\n * @param iteratorA - the first iterator to compare\n * @param iteratorB - the second iterator to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nfunction compareIterators<T, TReturn extends T = T>(\n\titeratorA: Iterator<T, TReturn>,\n\titeratorB: Iterator<T, TReturn>,\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\tlet a: IteratorResult<T, TReturn>;\n\tlet b: IteratorResult<T, TReturn>;\n\tfor (\n\t\ta = iteratorA.next(), b = iteratorB.next(); // Given two iterators...\n\t\ta.done !== true && b.done !== true; // ...while both have elements remaining...\n\t\ta = iteratorA.next(), b = iteratorB.next() // ...take one element at a time from each...\n\t) {\n\t\t// ...and ensure that their elements are equivalent\n\t\tif (!elementComparator(a.value, b.value)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// If one iterator is done, but not the other, then they are not equivalent\n\treturn a.done === b.done;\n}\n\n/**\n * Compare two arrays and return true if their elements are equivalent and in the same order.\n * @param arrayA - the first array to compare\n * @param arrayB - the second array to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareArrays<T>(\n\tarrayA: readonly T[],\n\tarrayB: readonly T[],\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\tif (arrayA.length !== arrayB.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arrayA.length; i++) {\n\t\tif (!elementComparator(arrayA[i], arrayB[i])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Compare two maps and return true if their contents are equivalent.\n * @param mapA - the first array to compare\n * @param mapB - the second array to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareMaps<K, V>(\n\tmapA: ReadonlyMap<K, V>,\n\tmapB: ReadonlyMap<K, V>,\n\telementComparator: (a: V, b: V) => boolean = Object.is\n): boolean {\n\tif (mapA.size !== mapB.size) {\n\t\treturn false;\n\t}\n\n\tfor (const [keyA, valueA] of mapA) {\n\t\tconst valueB = mapB.get(keyA);\n\t\tif (valueB === undefined || !elementComparator(valueA, valueB)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.\n * @param map - the map to query/update\n * @param key - the key to lookup in the map\n * @param defaultValue - a function which returns a default value. This is called and used to set an initial value in the map if none exists\n * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)\n */\nexport function getOrCreate<K, V>(map: Map<K, V>, key: K, defaultValue: () => V): V {\n\tlet value = map.get(key);\n\tif (value === undefined) {\n\t\tvalue = defaultValue();\n\t\tmap.set(key, value);\n\t}\n\treturn value;\n}\n\n/**\n * Function which does nothing (no-ops).\n */\nexport function noop(): void {\n\t// noop\n}\n\n/**\n * Function which returns its input\n */\nexport function identity<T>(t: T): T {\n\treturn t;\n}\n\n/**\n * Copies a property in such a way that it is only set on `destination` if it is present on `source`.\n * This avoids having explicit undefined values under properties that would cause `Object.hasOwnProperty` to return true.\n */\nexport function copyPropertyIfDefined<TSrc, TDst>(source: TSrc, destination: TDst, property: keyof TSrc): void {\n\tconst value = source[property];\n\tif (value !== undefined) {\n\t\t(destination as any)[property] = value;\n\t}\n}\n\n/**\n * Sets a property in such a way that it is only set on `destination` if the provided value is not undefined.\n * This avoids having explicit undefined values under properties that would cause `Object.hasOwnProperty` to return true.\n */\nexport function setPropertyIfDefined<TDst, P extends keyof TDst>(\n\tvalue: TDst[P] | undefined,\n\tdestination: TDst,\n\tproperty: P\n): void {\n\tif (value !== undefined) {\n\t\tdestination[property] = value;\n\t}\n}\n\n/**\n * function (thing: ObjectWithMaybeFoo) {\n * \t const x: MyActualType = {\n * \t bar: 3\n * };\n * \t\tx.foo = 3;\n *\n * \t copyPropertyIfDefined(thing, x, 'foo');\n * }\n * @returns\n */\n\nfunction breakOnDifference(): { break: boolean } {\n\treturn { break: true };\n}\n\n/**\n * Helper that returns whether two b-trees are equal.\n * Accelerated when large portions of the tree are shared between the two.\n */\nexport function compareBtrees<K, V>(treeA: BTree<K, V>, treeB: BTree<K, V>, compare: (valA: V, valB: V) => boolean) {\n\tconst diff = treeA.diffAgainst(treeB, breakOnDifference, breakOnDifference, (_, valA, valB) => {\n\t\tif (!compare(valA, valB)) {\n\t\t\treturn { break: true };\n\t\t}\n\t\treturn undefined;\n\t});\n\n\treturn diff === undefined;\n}\n\nexport function backmap<K, V>(forwardmap: Map<V, K>): Map<K, V> {\n\treturn new Map(map(forwardmap, ([key, value]) => [value, key]));\n}\n\n/**\n * A developer facing (non-localized) error message.\n * TODO: better error system.\n */\nexport type ErrorString = string;\n\n/**\n * Discriminated union instance that wraps either a result of type `TOk` or an error of type `TError`.\n */\nexport type Result<TOk, TError> = Result.Ok<TOk> | Result.Error<TError>;\n\nexport namespace Result {\n\t/**\n\t * Factory function for making a successful Result.\n\t * @param result - The result to wrap in the Result.\n\t */\n\texport function ok<TOk>(result: TOk): Ok<TOk> {\n\t\treturn { type: ResultType.Ok, result };\n\t}\n\t/**\n\t * Factory function for making a unsuccessful Result.\n\t * @param error - The error to wrap in the Result.\n\t */\n\texport function error<TError>(error: TError): Error<TError> {\n\t\treturn { type: ResultType.Error, error };\n\t}\n\t/**\n\t * Type guard for successful Result.\n\t * @returns True if `result` is successful.\n\t */\n\texport function isOk<TOk, TError>(result: Result<TOk, TError>): result is Ok<TOk> {\n\t\treturn result.type === ResultType.Ok;\n\t}\n\t/**\n\t * Type guard for unsuccessful Result.\n\t * @returns True if `result` is unsuccessful.\n\t */\n\texport function isError<TOk, TError>(result: Result<TOk, TError>): result is Error<TError> {\n\t\treturn result.type === ResultType.Error;\n\t}\n\t/**\n\t * Maps the given result with the given function when the result is ok.\n\t * @param result - The result to map.\n\t * @param map - The function to apply to derive the new result.\n\t * @returns The given result if it is not ok, the mapped result otherwise.\n\t */\n\texport function mapOk<TOkIn, TOkOut, TError>(\n\t\tresult: Result<TOkIn, TError>,\n\t\tmap: (ok: TOkIn) => TOkOut\n\t): Result<TOkOut, TError> {\n\t\treturn isOk(result) ? ok(map(result.result)) : result;\n\t}\n\t/**\n\t * Maps the given result with the given function when the result is an error.\n\t * @param result - The result to map.\n\t * @param map - The function to apply to derive the new error.\n\t * @returns The given result if it is ok, the mapped result otherwise.\n\t */\n\texport function mapError<TOk, TErrorIn, TErrorOut>(\n\t\tresult: Result<TOk, TErrorIn>,\n\t\tmap: (error: TErrorIn) => TErrorOut\n\t): Result<TOk, TErrorOut> {\n\t\treturn isError(result) ? error(map(result.error)) : result;\n\t}\n\t/**\n\t * Tag value use to differentiate the members of the `Result` discriminated union.\n\t */\n\texport enum ResultType {\n\t\t/** Signals a successful result. */\n\t\tOk,\n\t\t/** Signals an unsuccessful result. */\n\t\tError,\n\t}\n\t/**\n\t * Wraps a result of type `TOk`.\n\t */\n\texport interface Ok<TOk> {\n\t\treadonly type: ResultType.Ok;\n\t\treadonly result: TOk;\n\t}\n\t/**\n\t * Wraps an error of type `TError`.\n\t */\n\texport interface Error<TError> {\n\t\treadonly type: ResultType.Error;\n\t\treadonly error: TError;\n\t}\n}\n\n/** Type that removes `readonly` from fields. */\nexport type Mutable<T> = { -readonly [P in keyof T]: T[P] };\n\n/** Type that recursively removes `readonly` from fields. */\nexport type RecursiveMutable<T> = {\n\t-readonly [K in keyof T]: RecursiveMutable<T[K]>;\n};\n\n/** Type that produces a writeable map from a readonly map. */\nexport type MutableMap<T extends ReadonlyMap<unknown, unknown>> = T extends ReadonlyMap<infer K, infer V>\n\t? Map<K, V>\n\t: never;\n\n/** Type that includes the property K: V on T */\nexport type With<T, K extends keyof never, V> = T & { [key in K]: V };\n\n/**\n * A readonly `Map` which is known to contain a value for every possible key\n */\nexport interface ClosedMap<K, V> extends Omit<Map<K, V>, 'delete' | 'clear'> {\n\tget(key: K): V;\n}\n\n/**\n * Change the given property Prop of type T to have a type of TPropNew\n */\nexport type ChangePropType<T, Prop extends keyof T, TPropNew> = Omit<T, Prop> & { [_ in Prop]: TPropNew };\n\n// eslint-disable-next-line @rushstack/no-new-null\ntype Primitive = string | number | bigint | boolean | null | symbol | undefined;\n\n/**\n * Recursively replace all properties with type assignable to type TReplace in T with properties of type TWith.\n */\nexport type ReplaceRecursive<T, TReplace, TWith> = T extends TReplace\n\t? TWith\n\t: T extends Primitive\n\t? T\n\t: {\n\t\t\t[P in keyof T]: ReplaceRecursive<T[P], TReplace, TWith>;\n\t };\n"]}
1
+ {"version":3,"file":"Common.js","sourceRoot":"","sources":["../src/Common.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { ITelemetryBaseEvent, ITelemetryProperties } from '@fluidframework/common-definitions';\nimport BTree from 'sorted-btree';\n\nconst defaultFailMessage = 'Assertion failed';\n\n/**\n * Assertion failures in SharedTree will throw an exception containing this value as an `errorType`. The Fluid runtime propagates this field\n * in its handlings of errors thrown by containers. See\n * https://github.com/microsoft/FluidFramework/blob/main/packages/loader/container-utils/src/error.ts\n *\n * Exporting this enables users to safely filter telemetry handling of errors based on their type.\n *\n * @public\n */\nexport const sharedTreeAssertionErrorType = 'SharedTreeAssertion';\n\n/**\n * Telemetry properties decorated on all SharedTree events.\n */\nexport interface SharedTreeTelemetryProperties extends ITelemetryProperties {\n\treadonly isSharedTreeEvent: true;\n}\n\n/**\n * Returns if the supplied event is a SharedTree telemetry event.\n */\nexport function isSharedTreeEvent(event: ITelemetryBaseEvent): boolean {\n\treturn (event as unknown as SharedTreeTelemetryProperties).isSharedTreeEvent === true;\n}\n\n/**\n * Error object thrown by assertion failures in `SharedTree`.\n */\nclass SharedTreeAssertionError extends Error {\n\tpublic readonly errorType = sharedTreeAssertionErrorType;\n\n\tpublic constructor(message: string) {\n\t\tsuper(message);\n\t\tthis.name = 'Assertion error';\n\t\t// Note: conditional as `captureStackTrace` isn't defined in all browsers (e.g. Safari).\n\t\tError.captureStackTrace?.(this);\n\t}\n}\n\n/**\n * A numeric comparator used for sorting in ascending order.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbers<T extends number>(a: T, b: T): number {\n\treturn a - b;\n}\n\n/**\n * A numeric comparator used for sorting in descending order.\n *\n * Handles +/-0 like Map: -0 is equal to +0.\n */\nexport function compareFiniteNumbersReversed<T extends number>(a: T, b: T): number {\n\treturn b - a;\n}\n\n/**\n * Compares strings lexically to form a strict partial ordering.\n */\nexport function compareStrings<T extends string>(a: T, b: T): number {\n\treturn a > b ? 1 : a === b ? 0 : -1;\n}\n\n/**\n * Asserts against a boolean condition. Throws an Error if the assertion failed. Will run and throw in release builds.\n * Use when violations are logic errors in the program.\n * @param condition - A condition to assert is truthy\n * @param message - Message to be printed if assertion fails. Will print \"Assertion failed\" by default\n * @param containsPII - boolean flag for whether the message passed in contains personally identifying information (PII).\n */\nexport function assert(condition: unknown, message?: string, containsPII = false): asserts condition {\n\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\tif (!condition) {\n\t\tfail(message, containsPII);\n\t}\n}\n\n/**\n * Fails an assertion. Throws an Error that the assertion failed.\n * Use when violations are logic errors in the program.\n * @param message - Message to be printed if assertion fails. Will print \"Assertion failed\" by default\n * @param containsPII - boolean flag for whether the message passed in contains personally identifying information (PII).\n */\nexport function fail(message: string = defaultFailMessage, containsPII = false): never {\n\tif (process.env.NODE_ENV !== 'production') {\n\t\tdebugger;\n\t\tconsole.error(message);\n\t}\n\n\tthrow new SharedTreeAssertionError(containsPII ? 'Assertion failed' : message);\n}\n\n/**\n * Asserts a value is not undefined, and returns the value.\n * Use when violations are logic errors in the program.\n *\n * When practical, prefer the pattern `x ?? fail('message')` over `assertNotUndefined(x, 'message')`.\n * Using `?? fail` allows for message formatting without incurring the cost of formatting the message in the non failing case\n * (ex:\n * ```\n * x ?? fail(`x should exist for ${y}`)\n * ```\n * ). Additionally the `?? fail` avoids an extra call/stack frame in the non failing case.\n *\n * Another pattern to prefer over `assertNotUndefined(x, 'message')` is `assert(x !== undefined)`.\n * This pattern is preferred because it is more general (same approach works with typeof, instance of, comparison to other values etc.).\n *\n * @param value - Value to assert against is non undefined.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertNotUndefined<T>(value: T | undefined, message = 'value must not be undefined'): T {\n\tassert(value !== undefined, message);\n\treturn value;\n}\n\n/**\n * Asserts an array contains a single value and returns the value.\n * @param array - array to assert contains a single value.\n * @param message - Message to be printed if assertion fails.\n */\nexport function assertArrayOfOne<T>(array: readonly T[], message = 'array value must contain exactly one item'): T {\n\tassert(array.length === 1, message);\n\treturn array[0];\n}\n\n/**\n * Assign a property and value to a given object.\n * @param object - the object to add the property to\n * @param property - the property key\n * @param value - the value of the property\n * @returns `object` after assigning `value` to the property `property`.\n */\nexport function assign<T, K extends keyof never, V>(object: T, property: K, value: V): With<T, K, V> {\n\treturn Object.assign(object, { [property]: value }) as With<T, K, V>;\n}\n\n/**\n * Redefine a property to have the given value. This is simply a type-safe wrapper around\n * `Object.defineProperty`, but it is useful for caching public getters on first read.\n * @example\n * ```\n * // `randomOnce()` will return a random number, but always the same random number.\n * {\n * get randomOnce(): number {\n * return memoizeGetter(this, 'randomOnce', random(100))\n * }\n * }\n * ```\n * @param object - the object containing the property\n * @param propName - the name of the property on the object\n * @param value - the value of the property\n */\nexport function memoizeGetter<T, K extends keyof T>(object: T, propName: K, value: T[K]): T[K] {\n\tObject.defineProperty(object, propName, {\n\t\tvalue,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n\n\treturn value;\n}\n\n/**\n * Map an iterable to another iterable\n */\nexport function* map<T, R>(sequence: Iterable<T>, mapper: (t: T) => R): Iterable<R> {\n\tfor (const t of sequence) {\n\t\tyield mapper(t);\n\t}\n}\n\n/**\n * Filter an iterable into another iterable\n */\nexport function* filter<T>(sequence: Iterable<T>, filter: (t: T) => boolean): Iterable<T> {\n\tfor (const t of sequence) {\n\t\tif (filter(t)) {\n\t\t\tyield t;\n\t\t}\n\t}\n}\n\n/**\n * Reduce an iterable into a single value, or undefined if the iterable has too few elements to reduce\n */\nexport function reduce<T>(\n\tsequence: Iterable<T>,\n\treduce: (previous: T, current: T) => T,\n\tinitialValue?: T\n): T | undefined {\n\tlet previous: T | undefined;\n\tlet current: T | undefined;\n\tfor (const t of sequence) {\n\t\tcurrent = t;\n\t\tif (previous === undefined) {\n\t\t\tif (initialValue !== undefined) {\n\t\t\t\tcurrent = reduce(initialValue, current);\n\t\t\t}\n\t\t} else {\n\t\t\tcurrent = reduce(previous, current);\n\t\t}\n\t\tprevious = current;\n\t}\n\treturn current;\n}\n\n/**\n * Returns the first element of the given sequence that satisfies the given predicate, or undefined if no such element exists\n */\nexport function find<T>(sequence: Iterable<T>, find: (t: T) => boolean): T | undefined {\n\tfor (const t of sequence) {\n\t\tif (find(t)) {\n\t\t\treturn t;\n\t\t}\n\t}\n\treturn undefined;\n}\n\n/**\n * Iterate through two iterables and return true if they yield equivalent elements in the same order.\n * @param iterableA - the first iterable to compare\n * @param iterableB - the second iterable to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareIterables<T>(\n\titerableA: Iterable<T>,\n\titerableB: Iterable<T>,\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\treturn compareIterators<T>(iterableA[Symbol.iterator](), iterableB[Symbol.iterator](), elementComparator);\n}\n\n/**\n * Iterate through two iterators and return true if they yield equivalent elements in the same order.\n * @param iteratorA - the first iterator to compare\n * @param iteratorB - the second iterator to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nfunction compareIterators<T, TReturn extends T = T>(\n\titeratorA: Iterator<T, TReturn>,\n\titeratorB: Iterator<T, TReturn>,\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\tlet a: IteratorResult<T, TReturn>;\n\tlet b: IteratorResult<T, TReturn>;\n\tfor (\n\t\ta = iteratorA.next(), b = iteratorB.next(); // Given two iterators...\n\t\ta.done !== true && b.done !== true; // ...while both have elements remaining...\n\t\ta = iteratorA.next(), b = iteratorB.next() // ...take one element at a time from each...\n\t) {\n\t\t// ...and ensure that their elements are equivalent\n\t\tif (!elementComparator(a.value, b.value)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// If one iterator is done, but not the other, then they are not equivalent\n\treturn a.done === b.done;\n}\n\n/**\n * Compare two arrays and return true if their elements are equivalent and in the same order.\n * @param arrayA - the first array to compare\n * @param arrayB - the second array to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareArrays<T>(\n\tarrayA: readonly T[],\n\tarrayB: readonly T[],\n\telementComparator: (a: T, b: T) => boolean = Object.is\n): boolean {\n\tif (arrayA.length !== arrayB.length) {\n\t\treturn false;\n\t}\n\n\tfor (let i = 0; i < arrayA.length; i++) {\n\t\tif (!elementComparator(arrayA[i], arrayB[i])) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Compare two maps and return true if their contents are equivalent.\n * @param mapA - the first array to compare\n * @param mapB - the second array to compare\n * @param elementComparator - the function used to check if two `T`s are equivalent.\n * Defaults to `Object.is()` equality (a shallow compare)\n */\nexport function compareMaps<K, V>(\n\tmapA: ReadonlyMap<K, V>,\n\tmapB: ReadonlyMap<K, V>,\n\telementComparator: (a: V, b: V) => boolean = Object.is\n): boolean {\n\tif (mapA.size !== mapB.size) {\n\t\treturn false;\n\t}\n\n\tfor (const [keyA, valueA] of mapA) {\n\t\tconst valueB = mapB.get(keyA);\n\t\tif (valueB === undefined || !elementComparator(valueA, valueB)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\n/**\n * Retrieve a value from a map with the given key, or create a new entry if the key is not in the map.\n * @param map - the map to query/update\n * @param key - the key to lookup in the map\n * @param defaultValue - a function which returns a default value. This is called and used to set an initial value for the given key in the map if none exists\n * @returns either the existing value for the given key, or the newly-created value (the result of `defaultValue`)\n */\nexport function getOrCreate<K, V>(map: Map<K, V>, key: K, defaultValue: (key: K) => V): V {\n\tlet value = map.get(key);\n\tif (value === undefined) {\n\t\tvalue = defaultValue(key);\n\t\tmap.set(key, value);\n\t}\n\treturn value;\n}\n\n/**\n * Function which does nothing (no-ops).\n */\nexport function noop(): void {\n\t// noop\n}\n\n/**\n * Function which returns its input\n */\nexport function identity<T>(t: T): T {\n\treturn t;\n}\n\n/**\n * Copies a property in such a way that it is only set on `destination` if it is present on `source`.\n * This avoids having explicit undefined values under properties that would cause `Object.hasOwnProperty` to return true.\n */\nexport function copyPropertyIfDefined<TSrc, TDst>(source: TSrc, destination: TDst, property: keyof TSrc): void {\n\tconst value = source[property];\n\tif (value !== undefined) {\n\t\t(destination as any)[property] = value;\n\t}\n}\n\n/**\n * Sets a property in such a way that it is only set on `destination` if the provided value is not undefined.\n * This avoids having explicit undefined values under properties that would cause `Object.hasOwnProperty` to return true.\n */\nexport function setPropertyIfDefined<TDst, P extends keyof TDst>(\n\tvalue: TDst[P] | undefined,\n\tdestination: TDst,\n\tproperty: P\n): void {\n\tif (value !== undefined) {\n\t\tdestination[property] = value;\n\t}\n}\n\n/**\n * ```\n * function (thing: ObjectWithMaybeFoo) {\n * \t const x: MyActualType = {\n * \t bar: 3\n * };\n * \t\tx.foo = 3;\n *\n * \t copyPropertyIfDefined(thing, x, 'foo');\n * }\n * ```\n * @returns\n */\n\nfunction breakOnDifference(): { break: boolean } {\n\treturn { break: true };\n}\n\n/**\n * Helper that returns whether two b-trees are equal.\n * Accelerated when large portions of the tree are shared between the two.\n */\nexport function compareBtrees<K, V>(treeA: BTree<K, V>, treeB: BTree<K, V>, compare: (valA: V, valB: V) => boolean) {\n\tconst diff = treeA.diffAgainst(treeB, breakOnDifference, breakOnDifference, (_, valA, valB) => {\n\t\tif (!compare(valA, valB)) {\n\t\t\treturn { break: true };\n\t\t}\n\t\treturn undefined;\n\t});\n\n\treturn diff === undefined;\n}\n\nexport function backmap<K, V>(forwardmap: Map<V, K>): Map<K, V> {\n\treturn new Map(map(forwardmap, ([key, value]) => [value, key]));\n}\n\n/**\n * A developer facing (non-localized) error message.\n * TODO: better error system.\n */\nexport type ErrorString = string;\n\n/**\n * Discriminated union instance that wraps either a result of type `TOk` or an error of type `TError`.\n */\nexport type Result<TOk, TError> = Result.Ok<TOk> | Result.Error<TError>;\n\nexport namespace Result {\n\t/**\n\t * Factory function for making a successful Result.\n\t * @param result - The result to wrap in the Result.\n\t */\n\texport function ok<TOk>(result: TOk): Ok<TOk> {\n\t\treturn { type: ResultType.Ok, result };\n\t}\n\t/**\n\t * Factory function for making a unsuccessful Result.\n\t * @param error - The error to wrap in the Result.\n\t */\n\texport function error<TError>(error: TError): Error<TError> {\n\t\treturn { type: ResultType.Error, error };\n\t}\n\t/**\n\t * Type guard for successful Result.\n\t * @returns True if `result` is successful.\n\t */\n\texport function isOk<TOk, TError>(result: Result<TOk, TError>): result is Ok<TOk> {\n\t\treturn result.type === ResultType.Ok;\n\t}\n\t/**\n\t * Type guard for unsuccessful Result.\n\t * @returns True if `result` is unsuccessful.\n\t */\n\texport function isError<TOk, TError>(result: Result<TOk, TError>): result is Error<TError> {\n\t\treturn result.type === ResultType.Error;\n\t}\n\t/**\n\t * Maps the given result with the given function when the result is ok.\n\t * @param result - The result to map.\n\t * @param map - The function to apply to derive the new result.\n\t * @returns The given result if it is not ok, the mapped result otherwise.\n\t */\n\texport function mapOk<TOkIn, TOkOut, TError>(\n\t\tresult: Result<TOkIn, TError>,\n\t\tmap: (ok: TOkIn) => TOkOut\n\t): Result<TOkOut, TError> {\n\t\treturn isOk(result) ? ok(map(result.result)) : result;\n\t}\n\t/**\n\t * Maps the given result with the given function when the result is an error.\n\t * @param result - The result to map.\n\t * @param map - The function to apply to derive the new error.\n\t * @returns The given result if it is ok, the mapped result otherwise.\n\t */\n\texport function mapError<TOk, TErrorIn, TErrorOut>(\n\t\tresult: Result<TOk, TErrorIn>,\n\t\tmap: (error: TErrorIn) => TErrorOut\n\t): Result<TOk, TErrorOut> {\n\t\treturn isError(result) ? error(map(result.error)) : result;\n\t}\n\t/**\n\t * Tag value use to differentiate the members of the `Result` discriminated union.\n\t */\n\texport enum ResultType {\n\t\t/** Signals a successful result. */\n\t\tOk,\n\t\t/** Signals an unsuccessful result. */\n\t\tError,\n\t}\n\t/**\n\t * Wraps a result of type `TOk`.\n\t */\n\texport interface Ok<TOk> {\n\t\treadonly type: ResultType.Ok;\n\t\treadonly result: TOk;\n\t}\n\t/**\n\t * Wraps an error of type `TError`.\n\t */\n\texport interface Error<TError> {\n\t\treadonly type: ResultType.Error;\n\t\treadonly error: TError;\n\t}\n}\n\n/** Type that removes `readonly` from fields. */\nexport type Mutable<T> = { -readonly [P in keyof T]: T[P] };\n\n/** Type that recursively removes `readonly` from fields. */\nexport type RecursiveMutable<T> = {\n\t-readonly [K in keyof T]: RecursiveMutable<T[K]>;\n};\n\n/** Type that produces a writeable map from a readonly map. */\nexport type MutableMap<T extends ReadonlyMap<unknown, unknown>> = T extends ReadonlyMap<infer K, infer V>\n\t? Map<K, V>\n\t: never;\n\n/** Type that includes the property K: V on T */\nexport type With<T, K extends keyof never, V> = T & { [key in K]: V };\n\n/**\n * A readonly `Map` which is known to contain a value for every possible key\n */\nexport interface ClosedMap<K, V> extends Omit<Map<K, V>, 'delete' | 'clear'> {\n\tget(key: K): V;\n}\n\n/**\n * Change the given property Prop of type T to have a type of TPropNew\n */\nexport type ChangePropType<T, Prop extends keyof T, TPropNew> = Omit<T, Prop> & { [_ in Prop]: TPropNew };\n\n// eslint-disable-next-line @rushstack/no-new-null\ntype Primitive = string | number | bigint | boolean | null | symbol | undefined;\n\n/**\n * Recursively replace all properties with type assignable to type TReplace in T with properties of type TWith.\n */\nexport type ReplaceRecursive<T, TReplace, TWith> = T extends TReplace\n\t? TWith\n\t: T extends Primitive\n\t? T\n\t: {\n\t\t\t[P in keyof T]: ReplaceRecursive<T[P], TReplace, TWith>;\n\t };\n\n/** A union type of the first `N` positive integers */\nexport type TakeWholeNumbers<N extends number, A extends never[] = []> = N extends A['length']\n\t? never\n\t: A['length'] | TakeWholeNumbers<N, [never, ...A]>;\n/** Returns a tuple type with exactly `Length` elements of type `T` */\nexport type ArrayOfLength<T, Length extends number, A extends T[] = []> = Length extends A['length']\n\t? A\n\t: ArrayOfLength<T, Length, [T, ...A]>;\n/**\n * Fails if `array` does not have exactly `length` elements\n */\nexport function hasExactlyLength<T, Len extends TakeWholeNumbers<16>>(\n\tarray: readonly T[],\n\tlength: Len\n): array is ArrayOfLength<T, Len> {\n\treturn array.length === length;\n}\n/**\n * Fails if `array` does not have at least `length` elements\n */\nexport function hasLength<T, Len extends TakeWholeNumbers<16>>(\n\tarray: readonly T[],\n\tlength: Len\n): array is [...ArrayOfLength<T, Len>, ...T[]] {\n\treturn array.length >= length;\n}\n"]}
package/dist/EditLog.js CHANGED
@@ -88,7 +88,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
88
88
  this.maximumEvictableIndex = this.indexOfFirstEditInSession - 1;
89
89
  this.sequencedEditIds.forEach((id, index) => {
90
90
  const encounteredEditId = this.allEditIds.get(id);
91
- Common_1.assert(encounteredEditId === undefined, 'Duplicate acked edit.');
91
+ (0, Common_1.assert)(encounteredEditId === undefined, 'Duplicate acked edit.');
92
92
  this.allEditIds.set(id, { isLocal: false, index });
93
93
  });
94
94
  }
@@ -146,8 +146,9 @@ class EditLog extends common_utils_1.TypedEventEmitter {
146
146
  * @returns true iff the edit is contained in this 'EditLog' and it is a local edit (not sequenced).
147
147
  */
148
148
  isLocalEdit(editId) {
149
+ var _a;
149
150
  const entry = this.allEditIds.get(editId);
150
- return entry !== undefined && entry.isLocal;
151
+ return (_a = entry === null || entry === void 0 ? void 0 : entry.isLocal) !== null && _a !== void 0 ? _a : false;
151
152
  }
152
153
  /**
153
154
  * @returns true iff the revision is a sequenced revision (not local).
@@ -164,8 +165,8 @@ class EditLog extends common_utils_1.TypedEventEmitter {
164
165
  return undefined;
165
166
  }
166
167
  if (orderedEdit.isLocal) {
167
- const firstLocal = Common_1.assertNotUndefined(this.allEditIds.get(this.localEdits[0].id));
168
- Common_1.assert(firstLocal.isLocal);
168
+ const firstLocal = (0, Common_1.assertNotUndefined)(this.allEditIds.get(this.localEdits[0].id));
169
+ (0, Common_1.assert)(firstLocal.isLocal);
169
170
  return this.numberOfSequencedEdits + orderedEdit.localSequence - firstLocal.localSequence;
170
171
  }
171
172
  return orderedEdit.index;
@@ -174,14 +175,14 @@ class EditLog extends common_utils_1.TypedEventEmitter {
174
175
  * @returns Edit metadata for the edit with the given `editId`.
175
176
  */
176
177
  getOrderedEditId(editId) {
177
- return Common_1.assertNotUndefined(this.allEditIds.get(editId), 'All edits should exist in this map');
178
+ return (0, Common_1.assertNotUndefined)(this.allEditIds.get(editId), 'All edits should exist in this map');
178
179
  }
179
180
  /**
180
181
  * {@inheritDoc OrderedEditSet.getIndexOfId}
181
182
  */
182
183
  getIndexOfId(editId) {
183
184
  var _a;
184
- return (_a = this.tryGetIndexOfId(editId)) !== null && _a !== void 0 ? _a : Common_1.fail('edit not found');
185
+ return (_a = this.tryGetIndexOfId(editId)) !== null && _a !== void 0 ? _a : (0, Common_1.fail)('edit not found');
185
186
  }
186
187
  /**
187
188
  * {@inheritDoc OrderedEditSet.getIdAtIndex}
@@ -197,17 +198,17 @@ class EditLog extends common_utils_1.TypedEventEmitter {
197
198
  */
198
199
  async getEditAtIndex(index) {
199
200
  if (index < this.numberOfSequencedEdits) {
200
- const [startRevision, editChunk] = Common_1.assertNotUndefined(this.editChunks.getPairOrNextLower(index));
201
+ const [startRevision, editChunk] = (0, Common_1.assertNotUndefined)(this.editChunks.getPairOrNextLower(index));
201
202
  const { handle, edits } = editChunk;
202
203
  if (edits === undefined) {
203
- Common_1.assert(handle !== undefined, 'An edit chunk should include at least a handle or edits.');
204
+ (0, Common_1.assert)(handle !== undefined, 'An edit chunk should include at least a handle or edits.');
204
205
  const edits = await handle.get();
205
206
  // Make sure the loaded edit chunk is the correct size. If a higher starting revison is set, the length is the difference of both.
206
207
  // Otherwise, it means that there are no sequenced edits in memory so the length is the difference of the number of
207
208
  // sequenced edits and the starting revision.
208
209
  const nextKey = this.editChunks.nextHigherKey(index);
209
210
  const expectedEditLength = (nextKey === undefined ? this.numberOfSequencedEdits : nextKey) - startRevision;
210
- Common_1.assert(edits.length === expectedEditLength, 'The chunk does not contain the correct number of edits.');
211
+ (0, Common_1.assert)(edits.length === expectedEditLength, 'The chunk does not contain the correct number of edits.');
211
212
  editChunk.edits = edits;
212
213
  this.addKeyToCache(startRevision);
213
214
  return joinEditAndId(this.getIdAtIndex(index), edits[index - startRevision]);
@@ -220,13 +221,13 @@ class EditLog extends common_utils_1.TypedEventEmitter {
220
221
  * {@inheritDoc OrderedEditSet.getEditInSessionAtIndex}
221
222
  */
222
223
  getEditInSessionAtIndex(index) {
223
- Common_1.assert(index > this.maximumEvictableIndex, 'Edit to retrieve must have been added to the log during the current session.');
224
+ (0, Common_1.assert)(index > this.maximumEvictableIndex, 'Edit to retrieve must have been added to the log during the current session.');
224
225
  if (index < this.numberOfSequencedEdits) {
225
- const [startRevision, editChunk] = Common_1.assertNotUndefined(this.editChunks.getPairOrNextLower(index));
226
+ const [startRevision, editChunk] = (0, Common_1.assertNotUndefined)(this.editChunks.getPairOrNextLower(index));
226
227
  const { edits } = editChunk;
227
- return joinEditAndId(this.getIdAtIndex(index), Common_1.assertNotUndefined(edits, 'Edits should not have been evicted.')[index - startRevision]);
228
+ return joinEditAndId(this.getIdAtIndex(index), (0, Common_1.assertNotUndefined)(edits, 'Edits should not have been evicted.')[index - startRevision]);
228
229
  }
229
- Common_1.assert(index - this.numberOfSequencedEdits < this.localEdits.length, 'Edit to retrieve must be in the log.');
230
+ (0, Common_1.assert)(index - this.numberOfSequencedEdits < this.localEdits.length, 'Edit to retrieve must be in the log.');
230
231
  return this.localEdits[index - this.numberOfSequencedEdits];
231
232
  }
232
233
  /**
@@ -251,7 +252,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
251
252
  }
252
253
  for (const [startRevision, chunk] of this.editChunks.entries(undefined, [])) {
253
254
  if (chunk.handle === undefined) {
254
- const edits = Common_1.assertNotUndefined(chunk.edits);
255
+ const edits = (0, Common_1.assertNotUndefined)(chunk.edits);
255
256
  // If there is no handle, the chunk should either not be the last chunk or should be full if it is.
256
257
  if (maxStartRevision !== startRevision || edits.length >= this.editsPerChunk) {
257
258
  yield [startRevision, edits];
@@ -266,7 +267,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
266
267
  var _a;
267
268
  const chunk = this.editChunks.get(startRevision);
268
269
  if (chunk !== undefined) {
269
- Common_1.assertNotUndefined(chunk.edits, 'A chunk handle op should not be received before the edit ops it corresponds to.');
270
+ (0, Common_1.assertNotUndefined)(chunk.edits, 'A chunk handle op should not be received before the edit ops it corresponds to.');
270
271
  chunk.handle = chunkHandle;
271
272
  this.addKeyToCache(startRevision);
272
273
  }
@@ -305,7 +306,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
305
306
  */
306
307
  addSequencedEditInternal(edit, info, minSequenceNumber = 0) {
307
308
  const { id, editWithoutId } = separateEditAndId(edit);
308
- Common_1.assert(minSequenceNumber >= this.minSequenceNumber, 'Sequenced edits should carry a monotonically increasing min number');
309
+ (0, Common_1.assert)(minSequenceNumber >= this.minSequenceNumber, 'Sequenced edits should carry a monotonically increasing min number');
309
310
  // The new minSequenceNumber indicates that no future edit will require information from edits with a smaller or equal seq number
310
311
  // for its resolution.
311
312
  this._minSequenceNumber = minSequenceNumber;
@@ -327,10 +328,10 @@ class EditLog extends common_utils_1.TypedEventEmitter {
327
328
  const encounteredEditId = this.allEditIds.get(id);
328
329
  if (encounteredEditId !== undefined) {
329
330
  // New edit already exits: it must have been a local edit.
330
- Common_1.assert(encounteredEditId.isLocal, 'Duplicate acked edit.');
331
+ (0, Common_1.assert)(encounteredEditId.isLocal, 'Duplicate acked edit.');
331
332
  // Remove it from localEdits. Due to ordering requirements, it must be first.
332
- const oldLocalEditId = Common_1.assertNotUndefined(this.localEdits.shift(), 'Local edit should exist').id;
333
- Common_1.assert(oldLocalEditId === id, 'Causal ordering should be upheld');
333
+ const oldLocalEditId = (0, Common_1.assertNotUndefined)(this.localEdits.shift(), 'Local edit should exist').id;
334
+ (0, Common_1.assert)(oldLocalEditId === id, 'Causal ordering should be upheld');
334
335
  }
335
336
  // The starting revision for a newly created chunk.
336
337
  const startRevision = this.numberOfSequencedEdits;
@@ -348,7 +349,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
348
349
  lastEditChunk.push(editWithoutId);
349
350
  }
350
351
  else {
351
- Common_1.assert(handle !== undefined || lastEditChunk !== undefined, 'An edit chunk must have either a handle or a list of edits.');
352
+ (0, Common_1.assert)(handle !== undefined || lastEditChunk !== undefined, 'An edit chunk must have either a handle or a list of edits.');
352
353
  this.editChunks.set(startRevision, { edits });
353
354
  }
354
355
  }
@@ -391,7 +392,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
391
392
  equals(other) {
392
393
  // TODO #45414: We should also be deep comparing the list of changes in the edit. This is not straightforward.
393
394
  // We can use our edit validation code when we write it since it will need to do deep walks of the changes.
394
- return Common_1.compareArrays(this.editIds, other.editIds);
395
+ return (0, Common_1.compareArrays)(this.editIds, other.editIds);
395
396
  }
396
397
  getEditLogSummary(compressEdit) {
397
398
  if (compressEdit !== undefined) {
@@ -400,7 +401,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
400
401
  var _a, _b;
401
402
  return ({
402
403
  startRevision,
403
- chunk: (_b = (_a = handle === null || handle === void 0 ? void 0 : handle.baseHandle) !== null && _a !== void 0 ? _a : edits === null || edits === void 0 ? void 0 : edits.map((edit) => compressEdit(edit))) !== null && _b !== void 0 ? _b : Common_1.fail('An edit chunk must have either a handle or a list of edits.'),
404
+ chunk: (_b = (_a = handle === null || handle === void 0 ? void 0 : handle.baseHandle) !== null && _a !== void 0 ? _a : edits === null || edits === void 0 ? void 0 : edits.map((edit) => compressEdit(edit))) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('An edit chunk must have either a handle or a list of edits.'),
404
405
  });
405
406
  }),
406
407
  editIds: this.sequencedEditIds,
@@ -412,7 +413,7 @@ class EditLog extends common_utils_1.TypedEventEmitter {
412
413
  var _a, _b;
413
414
  return ({
414
415
  startRevision,
415
- chunk: (_b = (_a = handle === null || handle === void 0 ? void 0 : handle.baseHandle) !== null && _a !== void 0 ? _a : edits) !== null && _b !== void 0 ? _b : Common_1.fail('An edit chunk must have either a handle or a list of edits.'),
416
+ chunk: (_b = (_a = handle === null || handle === void 0 ? void 0 : handle.baseHandle) !== null && _a !== void 0 ? _a : edits) !== null && _b !== void 0 ? _b : (0, Common_1.fail)('An edit chunk must have either a handle or a list of edits.'),
416
417
  });
417
418
  }),
418
419
  editIds: this.sequencedEditIds,
@@ -429,8 +430,8 @@ class EditLog extends common_utils_1.TypedEventEmitter {
429
430
  this.loadedChunkCache.push(newKey);
430
431
  // If the cache is out of space, evict the oldest index in the cache.
431
432
  if (this.loadedChunkCache.length > loadedChunkCacheSize) {
432
- const indexToEvict = Common_1.assertNotUndefined(this.loadedChunkCache.shift());
433
- const chunkToEvict = Common_1.assertNotUndefined(this.editChunks.get(indexToEvict), 'Chunk start revision added to cache should exist in the edit log.');
433
+ const indexToEvict = (0, Common_1.assertNotUndefined)(this.loadedChunkCache.shift());
434
+ const chunkToEvict = (0, Common_1.assertNotUndefined)(this.editChunks.get(indexToEvict), 'Chunk start revision added to cache should exist in the edit log.');
434
435
  chunkToEvict.edits = undefined;
435
436
  }
436
437
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EditLog.js","sourceRoot":"","sources":["../src/EditLog.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { TypedEventEmitter } from '@fluidframework/common-utils';\nimport type { IEvent, ITelemetryLogger } from '@fluidframework/common-definitions';\nimport { assert, assertNotUndefined, compareArrays, compareFiniteNumbers, fail } from './Common';\nimport type { EditId } from './Identifiers';\nimport type { StringInterner } from './StringInterner';\nimport { Edit, EditLogSummary, editsPerChunk, EditWithoutId, FluidEditHandle } from './persisted-types';\nimport { SharedTreeDiagnosticEvent } from './EventTypes';\nimport type { ChangeCompressor } from './ChangeCompression';\n\n/**\n * An ordered set of Edits associated with a SharedTree.\n * Supports fast lookup of edits by ID and enforces idempotence.\n * Edits are virtualized, however, edits added during the current session are guaranteed to be available\n * synchronously.\n * @public\n * @sealed\n */\nexport interface OrderedEditSet<TChange = unknown> {\n\t/**\n\t * The length of this `OrderedEditSet`.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * The edit IDs of all edits in the log.\n\t */\n\treadonly editIds: readonly EditId[];\n\n\t/**\n\t * @returns the index of the edit with the given editId within this `OrderedEditSet`.\n\t */\n\tgetIndexOfId(editId: EditId): number;\n\n\t/**\n\t * @returns the id of the edit at the given index within this 'OrderedEditSet'.\n\t */\n\tgetIdAtIndex(index: number): EditId;\n\n\t/**\n\t * @returns the index of the edit with the given editId within this `OrderedEditSet`, or `undefined` if no such edit exists.\n\t */\n\ttryGetIndexOfId(editId: EditId): number | undefined;\n\n\t/**\n\t * @returns the edit at the given index within this `OrderedEditSet`.\n\t */\n\tgetEditAtIndex(index: number): Promise<Edit<TChange>>;\n\n\t/**\n\t * @returns the edit at the given index. Must have been added to the log during the current session.\n\t */\n\tgetEditInSessionAtIndex(index: number): Edit<TChange>;\n\n\t/**\n\t * @returns the Edit associated with the EditId or undefined if there is no such edit in the set.\n\t */\n\ttryGetEdit(editId: EditId): Promise<Edit<TChange> | undefined>;\n}\n\n/**\n * Server-provided metadata for edits that have been sequenced.\n */\nexport interface EditSequencingInfo {\n\t/**\n\t * The server-assigned sequence number of the op.\n\t */\n\treadonly sequenceNumber: number;\n\t/**\n\t * Last known sequenced edit at the time this op was issued.\n\t */\n\treadonly referenceSequenceNumber: number;\n}\n\n/**\n * Server-provided metadata for edits that have been sequenced.\n */\nexport interface MessageSequencingInfo extends EditSequencingInfo {\n\t/**\n\t * Last sequenced edit that all clients are guaranteed to be aware of.\n\t * If not specified, then some clients have not seen any edits yet.\n\t */\n\treadonly minimumSequenceNumber?: number;\n}\n\n/**\n * Metadata for a sequenced edit.\n */\nexport interface SequencedOrderedEditId {\n\treadonly isLocal: false;\n\treadonly index: number;\n\t/**\n\t * Information about the edit's relationship to other sequenced edits.\n\t * Undefined iff the edit was loaded from a summary.\n\t */\n\treadonly sequenceInfo?: EditSequencingInfo;\n}\n\n/**\n * Metadata for a local edit.\n */\nexport interface LocalOrderedEditId {\n\treadonly isLocal: true;\n\treadonly localSequence: number;\n}\n\n/**\n * Metadata for an edit.\n */\nexport type OrderedEditId = SequencedOrderedEditId | LocalOrderedEditId;\n\n/**\n * Compressor+interner pair used for encoding an {@link EditLog} into a summary.\n * @internal\n */\nexport interface EditLogEncoder {\n\tcompressor: ChangeCompressor;\n\tinterner: StringInterner;\n}\n\n/**\n * A sequence of edits that may or may not need to be downloaded into the EditLog from an external service\n */\nexport interface EditChunk<TChange> {\n\thandle?: EditHandle<TChange>;\n\tedits?: EditWithoutId<TChange>[];\n}\n\n/**\n * EditHandles are used to load edit chunks stored outside of the EditLog.\n * This is typically implemented by a wrapper around an IFluidHandle<ArrayBufferLike>.\n * @public\n */\nexport interface EditHandle<TChange> {\n\treadonly get: () => Promise<EditWithoutId<TChange>[]>;\n\treadonly baseHandle: FluidEditHandle;\n}\n\n/**\n * Returns an object that separates an Edit into two fields, id and editWithoutId.\n */\nexport function separateEditAndId<TChange>(edit: Edit<TChange>): {\n\tid: EditId;\n\teditWithoutId: EditWithoutId<TChange>;\n} {\n\tconst editWithoutId = { ...edit, id: undefined };\n\tdelete editWithoutId.id;\n\treturn { id: edit.id, editWithoutId };\n}\n\nfunction joinEditAndId<TChange>(id: EditId, edit: EditWithoutId<TChange>): Edit<TChange> {\n\treturn { id, ...edit };\n}\n\n/**\n * @param summary - The edit log summary to parse.\n * @returns the number of handles saved to the provided edit log summary.\n */\nexport function getNumberOfHandlesFromEditLogSummary(summary: EditLogSummary<unknown, unknown>): number {\n\tconst { editChunks } = summary;\n\n\tlet numberOfHandles = 0;\n\teditChunks.forEach(({ chunk }) => {\n\t\tif (!Array.isArray(chunk)) {\n\t\t\tnumberOfHandles++;\n\t\t}\n\t});\n\n\treturn numberOfHandles;\n}\n\n/**\n * The number of blobs to be loaded in memory at any time.\n * TODO:#49901: Change cache size once the virtualized history summary format is being written.\n * \t\t This is so the summarizer doesn't have to reload every edit to generate summaries.\n * */\nconst loadedChunkCacheSize = Number.POSITIVE_INFINITY;\n\n/**\n * Event fired when an edit is added to an `EditLog`.\n * @param edit - The edit that was added to the log\n * @param isLocal - true iff this edit was generated locally\n */\nexport type EditAddedHandler<TChange> = (edit: Edit<TChange>, isLocal: boolean, wasLocal: boolean) => void;\n\n/**\n * Events which may be emitted by `EditLog`.\n * @public\n */\nexport interface IEditLogEvents extends IEvent {\n\t(event: 'unexpectedHistoryChunk', listener: () => void);\n}\n\n/**\n * The edit history log for SharedTree.\n * Contains only completed edits (no in-progress edits).\n * Ordered first by locality (acked or local), then by time of insertion.\n * May not contain more than one edit with the same ID.\n * @sealed\n */\nexport class EditLog<TChange = unknown> extends TypedEventEmitter<IEditLogEvents> implements OrderedEditSet<TChange> {\n\tprivate localEditSequence = 0;\n\tprivate _minSequenceNumber = 0;\n\n\tprivate readonly sequencedEditIds: EditId[];\n\tprivate readonly editChunks: BTree<number, EditChunk<TChange>>;\n\tprivate readonly localEdits: Edit<TChange>[] = [];\n\tprivate readonly loadedChunkCache: number[] = [];\n\tprivate readonly indexOfFirstEditInSession: number;\n\tprivate readonly maximumEvictableIndex: number;\n\n\tprivate readonly allEditIds: Map<EditId, OrderedEditId> = new Map();\n\tprivate readonly _editAddedHandlers: Set<EditAddedHandler<TChange>> = new Set();\n\n\tprivate readonly logger?: ITelemetryLogger;\n\n\t/**\n\t * The number of edits associated with each blob.\n\t */\n\tpublic readonly editsPerChunk: number;\n\n\t/**\n\t * @returns The index of the earliest edit available through `getEditInSessionAtIndex`.\n\t */\n\tpublic get earliestAvailableEditIndex(): number {\n\t\treturn this.maximumEvictableIndex + 1;\n\t}\n\n\t/**\n\t * @returns The sequence number of the latest edit known by all nodes.\n\t */\n\tpublic get minSequenceNumber(): number {\n\t\treturn this._minSequenceNumber;\n\t}\n\n\t/**\n\t * Construct an `EditLog` using the given options.\n\t * @param summary - An edit log summary used to populate the edit log.\n\t * @param logger - An optional logger to record telemetry/errors\n\t */\n\tpublic constructor(\n\t\tsummary: EditLogSummary<TChange, EditHandle<TChange>> = { editIds: [], editChunks: [] },\n\t\tlogger?: ITelemetryLogger,\n\t\teditAddedHandlers: readonly EditAddedHandler<TChange>[] = [],\n\t\tindexOfFirstEditInSession = summary.editIds.length\n\t) {\n\t\tsuper();\n\t\tconst { editChunks, editIds } = summary;\n\t\tthis.logger = logger;\n\t\tthis.editsPerChunk = editsPerChunk;\n\n\t\tfor (const handler of editAddedHandlers) {\n\t\t\tthis.registerEditAddedHandler(handler);\n\t\t}\n\n\t\tthis.editChunks = new BTree<number, EditChunk<TChange>>(undefined, compareFiniteNumbers);\n\n\t\teditChunks.forEach((editChunkOrHandle) => {\n\t\t\tconst { startRevision, chunk } = editChunkOrHandle;\n\n\t\t\tif (isEditHandle(chunk)) {\n\t\t\t\tthis.editChunks.set(startRevision, { handle: chunk });\n\t\t\t} else {\n\t\t\t\tthis.editChunks.set(startRevision, { edits: chunk as EditWithoutId<TChange>[] });\n\t\t\t}\n\t\t});\n\n\t\tthis.sequencedEditIds = editIds.slice();\n\n\t\tthis.indexOfFirstEditInSession = indexOfFirstEditInSession;\n\t\tthis.maximumEvictableIndex = this.indexOfFirstEditInSession - 1;\n\n\t\tthis.sequencedEditIds.forEach((id, index) => {\n\t\t\tconst encounteredEditId = this.allEditIds.get(id);\n\t\t\tassert(encounteredEditId === undefined, 'Duplicate acked edit.');\n\t\t\tthis.allEditIds.set(id, { isLocal: false, index });\n\t\t});\n\t}\n\n\t/**\n\t * Registers a handler for when an edit is added to this `EditLog`.\n\t * @returns A callback which can be invoked to unregister this handler.\n\t */\n\tpublic registerEditAddedHandler(handler: EditAddedHandler<TChange>): () => void {\n\t\tthis._editAddedHandlers.add(handler);\n\t\treturn () => this._editAddedHandlers.delete(handler);\n\t}\n\n\t/**\n\t * @returns the `EditAddedHandler`s registered on this `EditLog`.\n\t */\n\tpublic get editAddedHandlers(): readonly EditAddedHandler<TChange>[] {\n\t\treturn Array.from(this._editAddedHandlers);\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.length}\n\t */\n\tpublic get length(): number {\n\t\treturn this.numberOfSequencedEdits + this.numberOfLocalEdits;\n\t}\n\n\t/**\n\t * The number of sequenced (acked) edits in the log.\n\t */\n\tpublic get numberOfSequencedEdits(): number {\n\t\treturn this.sequencedEditIds.length;\n\t}\n\n\t/**\n\t * The number of local (unacked) edits in the log.\n\t */\n\tpublic get numberOfLocalEdits(): number {\n\t\treturn this.localEdits.length;\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.editIds}\n\t */\n\tpublic get editIds(): EditId[] {\n\t\treturn this.sequencedEditIds.concat(this.localEdits.map(({ id }) => id));\n\t}\n\n\t/**\n\t * @returns true iff the edit is contained in this 'EditLog' and it is a local edit (not sequenced).\n\t */\n\tpublic isLocalEdit(editId: EditId): boolean {\n\t\tconst entry = this.allEditIds.get(editId);\n\t\treturn entry !== undefined && entry.isLocal;\n\t}\n\n\t/**\n\t * @returns true iff the revision is a sequenced revision (not local).\n\t */\n\tpublic isSequencedRevision(revision: number): boolean {\n\t\treturn revision <= this.sequencedEditIds.length;\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.tryGetIndexOfId}\n\t */\n\tpublic tryGetIndexOfId(editId: EditId): number | undefined {\n\t\tconst orderedEdit = this.allEditIds.get(editId);\n\t\tif (orderedEdit === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (orderedEdit.isLocal) {\n\t\t\tconst firstLocal = assertNotUndefined(this.allEditIds.get(this.localEdits[0].id));\n\t\t\tassert(firstLocal.isLocal);\n\t\t\treturn this.numberOfSequencedEdits + orderedEdit.localSequence - firstLocal.localSequence;\n\t\t}\n\t\treturn orderedEdit.index;\n\t}\n\n\t/**\n\t * @returns Edit metadata for the edit with the given `editId`.\n\t */\n\tpublic getOrderedEditId(editId: EditId): OrderedEditId {\n\t\treturn assertNotUndefined(this.allEditIds.get(editId), 'All edits should exist in this map');\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getIndexOfId}\n\t */\n\tpublic getIndexOfId(editId: EditId): number {\n\t\treturn this.tryGetIndexOfId(editId) ?? fail('edit not found');\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getIdAtIndex}\n\t */\n\tpublic getIdAtIndex(index: number): EditId {\n\t\tif (this.numberOfSequencedEdits <= index) {\n\t\t\treturn this.localEdits[index - this.numberOfSequencedEdits].id;\n\t\t}\n\n\t\treturn this.sequencedEditIds[index];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getEditAtIndex}\n\t */\n\tpublic async getEditAtIndex(index: number): Promise<Edit<TChange>> {\n\t\tif (index < this.numberOfSequencedEdits) {\n\t\t\tconst [startRevision, editChunk] = assertNotUndefined(this.editChunks.getPairOrNextLower(index));\n\t\t\tconst { handle, edits } = editChunk;\n\n\t\t\tif (edits === undefined) {\n\t\t\t\tassert(handle !== undefined, 'An edit chunk should include at least a handle or edits.');\n\t\t\t\tconst edits = await handle.get();\n\n\t\t\t\t// Make sure the loaded edit chunk is the correct size. If a higher starting revison is set, the length is the difference of both.\n\t\t\t\t// Otherwise, it means that there are no sequenced edits in memory so the length is the difference of the number of\n\t\t\t\t// sequenced edits and the starting revision.\n\t\t\t\tconst nextKey = this.editChunks.nextHigherKey(index);\n\t\t\t\tconst expectedEditLength =\n\t\t\t\t\t(nextKey === undefined ? this.numberOfSequencedEdits : nextKey) - startRevision;\n\t\t\t\tassert(edits.length === expectedEditLength, 'The chunk does not contain the correct number of edits.');\n\n\t\t\t\teditChunk.edits = edits;\n\n\t\t\t\tthis.addKeyToCache(startRevision);\n\t\t\t\treturn joinEditAndId(this.getIdAtIndex(index), edits[index - startRevision]);\n\t\t\t}\n\n\t\t\treturn joinEditAndId(this.getIdAtIndex(index), edits[index - startRevision]);\n\t\t}\n\n\t\treturn this.localEdits[index - this.numberOfSequencedEdits];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getEditInSessionAtIndex}\n\t */\n\tpublic getEditInSessionAtIndex(index: number): Edit<TChange> {\n\t\tassert(\n\t\t\tindex > this.maximumEvictableIndex,\n\t\t\t'Edit to retrieve must have been added to the log during the current session.'\n\t\t);\n\n\t\tif (index < this.numberOfSequencedEdits) {\n\t\t\tconst [startRevision, editChunk] = assertNotUndefined(this.editChunks.getPairOrNextLower(index));\n\t\t\tconst { edits } = editChunk;\n\n\t\t\treturn joinEditAndId(\n\t\t\t\tthis.getIdAtIndex(index),\n\t\t\t\tassertNotUndefined(edits, 'Edits should not have been evicted.')[index - startRevision]\n\t\t\t);\n\t\t}\n\n\t\tassert(index - this.numberOfSequencedEdits < this.localEdits.length, 'Edit to retrieve must be in the log.');\n\t\treturn this.localEdits[index - this.numberOfSequencedEdits];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.tryGetEdit}\n\t */\n\tpublic async tryGetEdit(editId: EditId): Promise<Edit<TChange> | undefined> {\n\t\ttry {\n\t\t\tconst index = this.getIndexOfId(editId);\n\t\t\treturn await this.getEditAtIndex(index);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t/**\n\t * @returns The edits of edit chunks that do not have associated edit handles, does not include the last edit chunk if it is not full.\n\t */\n\tpublic *getEditChunksReadyForUpload(): Iterable<[number, readonly EditWithoutId<TChange>[]]> {\n\t\tconst maxStartRevision = this.editChunks.maxKey();\n\n\t\tif (maxStartRevision === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const [startRevision, chunk] of this.editChunks.entries(undefined, [])) {\n\t\t\tif (chunk.handle === undefined) {\n\t\t\t\tconst edits = assertNotUndefined(chunk.edits);\n\n\t\t\t\t// If there is no handle, the chunk should either not be the last chunk or should be full if it is.\n\t\t\t\tif (maxStartRevision !== startRevision || edits.length >= this.editsPerChunk) {\n\t\t\t\t\tyield [startRevision, edits];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Assigns provided handles to edit chunks based on chunk index specified.\n\t */\n\tpublic processEditChunkHandle(chunkHandle: EditHandle<TChange>, startRevision: number): void {\n\t\tconst chunk = this.editChunks.get(startRevision);\n\t\tif (chunk !== undefined) {\n\t\t\tassertNotUndefined(\n\t\t\t\tchunk.edits,\n\t\t\t\t'A chunk handle op should not be received before the edit ops it corresponds to.'\n\t\t\t);\n\t\t\tchunk.handle = chunkHandle;\n\t\t\tthis.addKeyToCache(startRevision);\n\t\t} else {\n\t\t\tthis.logger?.sendErrorEvent({ eventName: 'UnexpectedHistoryChunk' });\n\t\t\tthis.emit(SharedTreeDiagnosticEvent.UnexpectedHistoryChunk);\n\t\t}\n\t}\n\n\t/**\n\t * Sequences all local edits.\n\t */\n\tpublic sequenceLocalEdits(): void {\n\t\tthis.localEdits.slice().forEach((edit) => this.addSequencedEditInternal(edit));\n\t}\n\n\t/**\n\t * Adds a sequenced (non-local) edit to the edit log.\n\t * If the id of the supplied edit matches a local edit already present in the log, the local edit will be replaced.\n\t *\n\t */\n\tpublic addSequencedEdit(edit: Edit<TChange>, message: MessageSequencingInfo): void {\n\t\tthis.addSequencedEditInternal(edit, message, message.minimumSequenceNumber);\n\t}\n\n\t/**\n\t * Returns all local edits from this EditLog\n\t * This is useful for op format upgrades, which might warrant re-submission of these ops using the new format.\n\t * See the breaking change documentation for more information.\n\t */\n\tpublic *getLocalEdits(): Iterable<Edit<TChange>> {\n\t\tfor (const edit of this.localEdits) {\n\t\t\tyield edit;\n\t\t}\n\t}\n\n\t/**\n\t * Adds a sequenced (non-local) edit to the edit log.\n\t * If the id of the supplied edit matches a local edit already present in the log, the local edit will be replaced.\n\t */\n\tprivate addSequencedEditInternal(\n\t\tedit: Edit<TChange>,\n\t\tinfo?: EditSequencingInfo,\n\t\tminSequenceNumber: number = 0\n\t): void {\n\t\tconst { id, editWithoutId } = separateEditAndId(edit);\n\n\t\tassert(\n\t\t\tminSequenceNumber >= this.minSequenceNumber,\n\t\t\t'Sequenced edits should carry a monotonically increasing min number'\n\t\t);\n\t\t// The new minSequenceNumber indicates that no future edit will require information from edits with a smaller or equal seq number\n\t\t// for its resolution.\n\t\tthis._minSequenceNumber = minSequenceNumber;\n\t\t// TODO:#57176: Increment maximumEvictableIndex to reflect the fact we can now evict edits with a sequenceNumber lower or equal to\n\t\t// it. Note that this will change the meaning of our 'InSession' APIs so we should make sure to rename them at the same time.\n\t\t// The code might look like this:\n\t\t// while (this.maximumEvictableIndex + 1 < this.indexOfFirstEditInSession) {\n\t\t// \tconst nextEdit = this.getEditInSessionAtIndex(this.maximumEvictableIndex + 1);\n\t\t// \tconst nextEditInfo = this.getOrderedEditId(nextEdit.id) as SequencedOrderedEditId;\n\t\t// \tif (\n\t\t// \t\tnextEditInfo.sequenceInfo !== undefined &&\n\t\t// \t\tnextEditInfo.sequenceInfo.sequenceNumber > minSequenceNumber\n\t\t// \t) {\n\t\t// \t\tbreak;\n\t\t// \t}\n\t\t// \t++this.maximumEvictableIndex;\n\t\t// }\n\n\t\t// Remove the edit from local edits if it exists.\n\t\tconst encounteredEditId = this.allEditIds.get(id);\n\t\tif (encounteredEditId !== undefined) {\n\t\t\t// New edit already exits: it must have been a local edit.\n\t\t\tassert(encounteredEditId.isLocal, 'Duplicate acked edit.');\n\t\t\t// Remove it from localEdits. Due to ordering requirements, it must be first.\n\t\t\tconst oldLocalEditId = assertNotUndefined(this.localEdits.shift(), 'Local edit should exist').id;\n\t\t\tassert(oldLocalEditId === id, 'Causal ordering should be upheld');\n\t\t}\n\n\t\t// The starting revision for a newly created chunk.\n\t\tconst startRevision = this.numberOfSequencedEdits;\n\t\t// The initial edits for a newly created chunk.\n\t\tconst edits: EditWithoutId<TChange>[] = [editWithoutId];\n\n\t\tconst lastPair = this.editChunks.nextLowerPair(undefined);\n\t\tif (lastPair === undefined) {\n\t\t\tthis.editChunks.set(startRevision, { edits });\n\t\t} else {\n\t\t\t// Add to the last edit chunk if it has room and hasn't already been uploaded, otherwise create a new chunk.\n\t\t\t// If the chunk has a corresponding handle, create a new chunk.\n\t\t\tconst { edits: lastEditChunk, handle } = lastPair[1];\n\t\t\tif (handle === undefined && lastEditChunk !== undefined && lastEditChunk.length < this.editsPerChunk) {\n\t\t\t\tlastEditChunk.push(editWithoutId);\n\t\t\t} else {\n\t\t\t\tassert(\n\t\t\t\t\thandle !== undefined || lastEditChunk !== undefined,\n\t\t\t\t\t'An edit chunk must have either a handle or a list of edits.'\n\t\t\t\t);\n\t\t\t\tthis.editChunks.set(startRevision, { edits });\n\t\t\t}\n\t\t}\n\n\t\tthis.sequencedEditIds.push(id);\n\t\tconst sequencedEditId: SequencedOrderedEditId = {\n\t\t\tindex: this.numberOfSequencedEdits - 1,\n\t\t\tisLocal: false,\n\t\t\tsequenceInfo: info,\n\t\t};\n\t\tthis.allEditIds.set(id, sequencedEditId);\n\t\tthis.emitAdd(edit, false, encounteredEditId !== undefined);\n\t}\n\n\t/**\n\t * @returns The last edit chunk i.e. the chunk which the most recent sequenced edits have been placed into, as well as its starting revision.\n\t * Returns undefined iff there are no sequenced edits.\n\t * When defined, this chunk is guaranteed to contain at least one edit\n\t * (though it may be necessary to load the chunk via its handle to use it)\n\t */\n\tpublic getLastEditChunk(): [startRevision: number, edits: EditChunk<TChange>] | undefined {\n\t\treturn this.editChunks.nextLowerPair(undefined);\n\t}\n\n\t/**\n\t * Adds a non-sequenced (local) edit to the edit log.\n\t * Duplicate edits are ignored.\n\t */\n\tpublic addLocalEdit(edit: Edit<TChange>): void {\n\t\tthis.localEdits.push(edit);\n\t\tconst localEditId: LocalOrderedEditId = { localSequence: this.localEditSequence++, isLocal: true };\n\t\tthis.allEditIds.set(edit.id, localEditId);\n\t\tthis.emitAdd(edit, true, false);\n\t}\n\n\tprivate emitAdd(editAdded: Edit<TChange>, isLocal: boolean, wasLocal: boolean): void {\n\t\tfor (const handler of this._editAddedHandlers) {\n\t\t\thandler(editAdded, isLocal, wasLocal);\n\t\t}\n\t}\n\n\t/**\n\t * @returns true iff this `EditLog` and `other` are equivalent, regardless of locality.\n\t */\n\tpublic equals<TOtherChangeTypesInternal>(other: EditLog<TOtherChangeTypesInternal>): boolean {\n\t\t// TODO #45414: We should also be deep comparing the list of changes in the edit. This is not straightforward.\n\t\t// We can use our edit validation code when we write it since it will need to do deep walks of the changes.\n\t\treturn compareArrays(this.editIds, other.editIds);\n\t}\n\n\t/**\n\t * @returns the summary of this `OrderedEditSet` that can be used to reconstruct the edit set.\n\t * @internal\n\t */\n\tpublic getEditLogSummary(): EditLogSummary<TChange, FluidEditHandle>;\n\t/**\n\t * @param compressEdit - a function which compresses edits\n\t * @returns the summary of this `OrderedEditSet` that can be used to reconstruct the edit set.\n\t * @internal\n\t */\n\tpublic getEditLogSummary<TCompressedChange>(\n\t\tcompressEdit: (edit: Pick<Edit<TChange>, 'changes'>) => Pick<Edit<TCompressedChange>, 'changes'>\n\t): EditLogSummary<TCompressedChange, FluidEditHandle>;\n\tpublic getEditLogSummary<TCompressedChange>(\n\t\tcompressEdit?: (edit: Pick<Edit<TChange>, 'changes'>) => Pick<Edit<TCompressedChange>, 'changes'>\n\t): EditLogSummary<TChange, FluidEditHandle> | EditLogSummary<TCompressedChange, FluidEditHandle> {\n\t\tif (compressEdit !== undefined) {\n\t\t\treturn {\n\t\t\t\teditChunks: this.editChunks.toArray().map(([startRevision, { handle, edits }]) => ({\n\t\t\t\t\tstartRevision,\n\t\t\t\t\tchunk:\n\t\t\t\t\t\thandle?.baseHandle ??\n\t\t\t\t\t\tedits?.map((edit) => compressEdit(edit)) ??\n\t\t\t\t\t\tfail('An edit chunk must have either a handle or a list of edits.'),\n\t\t\t\t})),\n\t\t\t\teditIds: this.sequencedEditIds,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\teditChunks: this.editChunks.toArray().map(([startRevision, { handle, edits }]) => ({\n\t\t\t\t\tstartRevision,\n\t\t\t\t\tchunk:\n\t\t\t\t\t\thandle?.baseHandle ??\n\t\t\t\t\t\tedits ??\n\t\t\t\t\t\tfail('An edit chunk must have either a handle or a list of edits.'),\n\t\t\t\t})),\n\t\t\t\teditIds: this.sequencedEditIds,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate addKeyToCache(newKey: number): void {\n\t\t// Indices are only added to the cache if they are not higher than the maximum evicted index.\n\t\tif (newKey <= this.maximumEvictableIndex) {\n\t\t\t// If the new index is already in the cache, remove it first to update its last usage.\n\t\t\tif (newKey in this.loadedChunkCache) {\n\t\t\t\tthis.loadedChunkCache.splice(this.loadedChunkCache.indexOf(newKey), 1);\n\t\t\t}\n\n\t\t\tthis.loadedChunkCache.push(newKey);\n\n\t\t\t// If the cache is out of space, evict the oldest index in the cache.\n\t\t\tif (this.loadedChunkCache.length > loadedChunkCacheSize) {\n\t\t\t\tconst indexToEvict = assertNotUndefined(this.loadedChunkCache.shift());\n\t\t\t\tconst chunkToEvict = assertNotUndefined(\n\t\t\t\t\tthis.editChunks.get(indexToEvict),\n\t\t\t\t\t'Chunk start revision added to cache should exist in the edit log.'\n\t\t\t\t);\n\t\t\t\tchunkToEvict.edits = undefined;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction isEditHandle<TChange>(\n\tchunk: EditHandle<TChange> | readonly EditWithoutId<unknown>[]\n): chunk is EditHandle<TChange> {\n\treturn !Array.isArray(chunk);\n}\n"]}
1
+ {"version":3,"file":"EditLog.js","sourceRoot":"","sources":["../src/EditLog.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport BTree from 'sorted-btree';\nimport { TypedEventEmitter } from '@fluidframework/common-utils';\nimport type { IEvent, ITelemetryLogger } from '@fluidframework/common-definitions';\nimport { assert, assertNotUndefined, compareArrays, compareFiniteNumbers, fail } from './Common';\nimport type { EditId } from './Identifiers';\nimport type { StringInterner } from './StringInterner';\nimport { Edit, EditLogSummary, editsPerChunk, EditWithoutId, FluidEditHandle } from './persisted-types';\nimport { SharedTreeDiagnosticEvent } from './EventTypes';\nimport type { ChangeCompressor } from './ChangeCompression';\n\n/**\n * An ordered set of Edits associated with a SharedTree.\n * Supports fast lookup of edits by ID and enforces idempotence.\n * Edits are virtualized, however, edits added during the current session are guaranteed to be available\n * synchronously.\n * @public\n * @sealed\n */\nexport interface OrderedEditSet<TChange = unknown> {\n\t/**\n\t * The length of this `OrderedEditSet`.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * The edit IDs of all edits in the log.\n\t */\n\treadonly editIds: readonly EditId[];\n\n\t/**\n\t * @returns the index of the edit with the given editId within this `OrderedEditSet`.\n\t */\n\tgetIndexOfId(editId: EditId): number;\n\n\t/**\n\t * @returns the id of the edit at the given index within this 'OrderedEditSet'.\n\t */\n\tgetIdAtIndex(index: number): EditId;\n\n\t/**\n\t * @returns the index of the edit with the given editId within this `OrderedEditSet`, or `undefined` if no such edit exists.\n\t */\n\ttryGetIndexOfId(editId: EditId): number | undefined;\n\n\t/**\n\t * @returns the edit at the given index within this `OrderedEditSet`.\n\t */\n\tgetEditAtIndex(index: number): Promise<Edit<TChange>>;\n\n\t/**\n\t * @returns the edit at the given index. Must have been added to the log during the current session.\n\t */\n\tgetEditInSessionAtIndex(index: number): Edit<TChange>;\n\n\t/**\n\t * @returns the Edit associated with the EditId or undefined if there is no such edit in the set.\n\t */\n\ttryGetEdit(editId: EditId): Promise<Edit<TChange> | undefined>;\n}\n\n/**\n * Server-provided metadata for edits that have been sequenced.\n */\nexport interface EditSequencingInfo {\n\t/**\n\t * The server-assigned sequence number of the op.\n\t */\n\treadonly sequenceNumber: number;\n\t/**\n\t * Last known sequenced edit at the time this op was issued.\n\t */\n\treadonly referenceSequenceNumber: number;\n}\n\n/**\n * Server-provided metadata for edits that have been sequenced.\n */\nexport interface MessageSequencingInfo extends EditSequencingInfo {\n\t/**\n\t * Last sequenced edit that all clients are guaranteed to be aware of.\n\t * If not specified, then some clients have not seen any edits yet.\n\t */\n\treadonly minimumSequenceNumber?: number;\n}\n\n/**\n * Metadata for a sequenced edit.\n */\nexport interface SequencedOrderedEditId {\n\treadonly isLocal: false;\n\treadonly index: number;\n\t/**\n\t * Information about the edit's relationship to other sequenced edits.\n\t * Undefined iff the edit was loaded from a summary.\n\t */\n\treadonly sequenceInfo?: EditSequencingInfo;\n}\n\n/**\n * Metadata for a local edit.\n */\nexport interface LocalOrderedEditId {\n\treadonly isLocal: true;\n\treadonly localSequence: number;\n}\n\n/**\n * Metadata for an edit.\n */\nexport type OrderedEditId = SequencedOrderedEditId | LocalOrderedEditId;\n\n/**\n * Compressor+interner pair used for encoding an {@link EditLog} into a summary.\n * @internal\n */\nexport interface EditLogEncoder {\n\tcompressor: ChangeCompressor;\n\tinterner: StringInterner;\n}\n\n/**\n * A sequence of edits that may or may not need to be downloaded into the EditLog from an external service\n */\nexport interface EditChunk<TChange> {\n\thandle?: EditHandle<TChange>;\n\tedits?: EditWithoutId<TChange>[];\n}\n\n/**\n * EditHandles are used to load edit chunks stored outside of the EditLog.\n * This is typically implemented by a wrapper around an IFluidHandle<ArrayBufferLike>.\n * @public\n */\nexport interface EditHandle<TChange> {\n\treadonly get: () => Promise<EditWithoutId<TChange>[]>;\n\treadonly baseHandle: FluidEditHandle;\n}\n\n/**\n * Returns an object that separates an Edit into two fields, id and editWithoutId.\n */\nexport function separateEditAndId<TChange>(edit: Edit<TChange>): {\n\tid: EditId;\n\teditWithoutId: EditWithoutId<TChange>;\n} {\n\tconst editWithoutId = { ...edit, id: undefined };\n\tdelete editWithoutId.id;\n\treturn { id: edit.id, editWithoutId };\n}\n\nfunction joinEditAndId<TChange>(id: EditId, edit: EditWithoutId<TChange>): Edit<TChange> {\n\treturn { id, ...edit };\n}\n\n/**\n * @param summary - The edit log summary to parse.\n * @returns the number of handles saved to the provided edit log summary.\n */\nexport function getNumberOfHandlesFromEditLogSummary(summary: EditLogSummary<unknown, unknown>): number {\n\tconst { editChunks } = summary;\n\n\tlet numberOfHandles = 0;\n\teditChunks.forEach(({ chunk }) => {\n\t\tif (!Array.isArray(chunk)) {\n\t\t\tnumberOfHandles++;\n\t\t}\n\t});\n\n\treturn numberOfHandles;\n}\n\n/**\n * The number of blobs to be loaded in memory at any time.\n * TODO:#49901: Change cache size once the virtualized history summary format is being written.\n * \t\t This is so the summarizer doesn't have to reload every edit to generate summaries.\n * */\nconst loadedChunkCacheSize = Number.POSITIVE_INFINITY;\n\n/**\n * Event fired when an edit is added to an `EditLog`.\n * @param edit - The edit that was added to the log\n * @param isLocal - true iff this edit was generated locally\n */\nexport type EditAddedHandler<TChange> = (edit: Edit<TChange>, isLocal: boolean, wasLocal: boolean) => void;\n\n/**\n * Events which may be emitted by `EditLog`.\n * @public\n */\nexport interface IEditLogEvents extends IEvent {\n\t(event: 'unexpectedHistoryChunk', listener: () => void);\n}\n\n/**\n * The edit history log for SharedTree.\n * Contains only completed edits (no in-progress edits).\n * Ordered first by locality (acked or local), then by time of insertion.\n * May not contain more than one edit with the same ID.\n * @sealed\n */\nexport class EditLog<TChange = unknown> extends TypedEventEmitter<IEditLogEvents> implements OrderedEditSet<TChange> {\n\tprivate localEditSequence = 0;\n\tprivate _minSequenceNumber = 0;\n\n\tprivate readonly sequencedEditIds: EditId[];\n\tprivate readonly editChunks: BTree<number, EditChunk<TChange>>;\n\tprivate readonly localEdits: Edit<TChange>[] = [];\n\tprivate readonly loadedChunkCache: number[] = [];\n\tprivate readonly indexOfFirstEditInSession: number;\n\tprivate readonly maximumEvictableIndex: number;\n\n\tprivate readonly allEditIds: Map<EditId, OrderedEditId> = new Map();\n\tprivate readonly _editAddedHandlers: Set<EditAddedHandler<TChange>> = new Set();\n\n\tprivate readonly logger?: ITelemetryLogger;\n\n\t/**\n\t * The number of edits associated with each blob.\n\t */\n\tpublic readonly editsPerChunk: number;\n\n\t/**\n\t * @returns The index of the earliest edit available through `getEditInSessionAtIndex`.\n\t */\n\tpublic get earliestAvailableEditIndex(): number {\n\t\treturn this.maximumEvictableIndex + 1;\n\t}\n\n\t/**\n\t * @returns The sequence number of the latest edit known by all nodes.\n\t */\n\tpublic get minSequenceNumber(): number {\n\t\treturn this._minSequenceNumber;\n\t}\n\n\t/**\n\t * Construct an `EditLog` using the given options.\n\t * @param summary - An edit log summary used to populate the edit log.\n\t * @param logger - An optional logger to record telemetry/errors\n\t */\n\tpublic constructor(\n\t\tsummary: EditLogSummary<TChange, EditHandle<TChange>> = { editIds: [], editChunks: [] },\n\t\tlogger?: ITelemetryLogger,\n\t\teditAddedHandlers: readonly EditAddedHandler<TChange>[] = [],\n\t\tindexOfFirstEditInSession = summary.editIds.length\n\t) {\n\t\tsuper();\n\t\tconst { editChunks, editIds } = summary;\n\t\tthis.logger = logger;\n\t\tthis.editsPerChunk = editsPerChunk;\n\n\t\tfor (const handler of editAddedHandlers) {\n\t\t\tthis.registerEditAddedHandler(handler);\n\t\t}\n\n\t\tthis.editChunks = new BTree<number, EditChunk<TChange>>(undefined, compareFiniteNumbers);\n\n\t\teditChunks.forEach((editChunkOrHandle) => {\n\t\t\tconst { startRevision, chunk } = editChunkOrHandle;\n\n\t\t\tif (isEditHandle(chunk)) {\n\t\t\t\tthis.editChunks.set(startRevision, { handle: chunk });\n\t\t\t} else {\n\t\t\t\tthis.editChunks.set(startRevision, { edits: chunk as EditWithoutId<TChange>[] });\n\t\t\t}\n\t\t});\n\n\t\tthis.sequencedEditIds = editIds.slice();\n\n\t\tthis.indexOfFirstEditInSession = indexOfFirstEditInSession;\n\t\tthis.maximumEvictableIndex = this.indexOfFirstEditInSession - 1;\n\n\t\tthis.sequencedEditIds.forEach((id, index) => {\n\t\t\tconst encounteredEditId = this.allEditIds.get(id);\n\t\t\tassert(encounteredEditId === undefined, 'Duplicate acked edit.');\n\t\t\tthis.allEditIds.set(id, { isLocal: false, index });\n\t\t});\n\t}\n\n\t/**\n\t * Registers a handler for when an edit is added to this `EditLog`.\n\t * @returns A callback which can be invoked to unregister this handler.\n\t */\n\tpublic registerEditAddedHandler(handler: EditAddedHandler<TChange>): () => void {\n\t\tthis._editAddedHandlers.add(handler);\n\t\treturn () => this._editAddedHandlers.delete(handler);\n\t}\n\n\t/**\n\t * @returns the `EditAddedHandler`s registered on this `EditLog`.\n\t */\n\tpublic get editAddedHandlers(): readonly EditAddedHandler<TChange>[] {\n\t\treturn Array.from(this._editAddedHandlers);\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.length}\n\t */\n\tpublic get length(): number {\n\t\treturn this.numberOfSequencedEdits + this.numberOfLocalEdits;\n\t}\n\n\t/**\n\t * The number of sequenced (acked) edits in the log.\n\t */\n\tpublic get numberOfSequencedEdits(): number {\n\t\treturn this.sequencedEditIds.length;\n\t}\n\n\t/**\n\t * The number of local (unacked) edits in the log.\n\t */\n\tpublic get numberOfLocalEdits(): number {\n\t\treturn this.localEdits.length;\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.editIds}\n\t */\n\tpublic get editIds(): EditId[] {\n\t\treturn this.sequencedEditIds.concat(this.localEdits.map(({ id }) => id));\n\t}\n\n\t/**\n\t * @returns true iff the edit is contained in this 'EditLog' and it is a local edit (not sequenced).\n\t */\n\tpublic isLocalEdit(editId: EditId): boolean {\n\t\tconst entry = this.allEditIds.get(editId);\n\t\treturn entry?.isLocal ?? false;\n\t}\n\n\t/**\n\t * @returns true iff the revision is a sequenced revision (not local).\n\t */\n\tpublic isSequencedRevision(revision: number): boolean {\n\t\treturn revision <= this.sequencedEditIds.length;\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.tryGetIndexOfId}\n\t */\n\tpublic tryGetIndexOfId(editId: EditId): number | undefined {\n\t\tconst orderedEdit = this.allEditIds.get(editId);\n\t\tif (orderedEdit === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (orderedEdit.isLocal) {\n\t\t\tconst firstLocal = assertNotUndefined(this.allEditIds.get(this.localEdits[0].id));\n\t\t\tassert(firstLocal.isLocal);\n\t\t\treturn this.numberOfSequencedEdits + orderedEdit.localSequence - firstLocal.localSequence;\n\t\t}\n\t\treturn orderedEdit.index;\n\t}\n\n\t/**\n\t * @returns Edit metadata for the edit with the given `editId`.\n\t */\n\tpublic getOrderedEditId(editId: EditId): OrderedEditId {\n\t\treturn assertNotUndefined(this.allEditIds.get(editId), 'All edits should exist in this map');\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getIndexOfId}\n\t */\n\tpublic getIndexOfId(editId: EditId): number {\n\t\treturn this.tryGetIndexOfId(editId) ?? fail('edit not found');\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getIdAtIndex}\n\t */\n\tpublic getIdAtIndex(index: number): EditId {\n\t\tif (this.numberOfSequencedEdits <= index) {\n\t\t\treturn this.localEdits[index - this.numberOfSequencedEdits].id;\n\t\t}\n\n\t\treturn this.sequencedEditIds[index];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getEditAtIndex}\n\t */\n\tpublic async getEditAtIndex(index: number): Promise<Edit<TChange>> {\n\t\tif (index < this.numberOfSequencedEdits) {\n\t\t\tconst [startRevision, editChunk] = assertNotUndefined(this.editChunks.getPairOrNextLower(index));\n\t\t\tconst { handle, edits } = editChunk;\n\n\t\t\tif (edits === undefined) {\n\t\t\t\tassert(handle !== undefined, 'An edit chunk should include at least a handle or edits.');\n\t\t\t\tconst edits = await handle.get();\n\n\t\t\t\t// Make sure the loaded edit chunk is the correct size. If a higher starting revison is set, the length is the difference of both.\n\t\t\t\t// Otherwise, it means that there are no sequenced edits in memory so the length is the difference of the number of\n\t\t\t\t// sequenced edits and the starting revision.\n\t\t\t\tconst nextKey = this.editChunks.nextHigherKey(index);\n\t\t\t\tconst expectedEditLength =\n\t\t\t\t\t(nextKey === undefined ? this.numberOfSequencedEdits : nextKey) - startRevision;\n\t\t\t\tassert(edits.length === expectedEditLength, 'The chunk does not contain the correct number of edits.');\n\n\t\t\t\teditChunk.edits = edits;\n\n\t\t\t\tthis.addKeyToCache(startRevision);\n\t\t\t\treturn joinEditAndId(this.getIdAtIndex(index), edits[index - startRevision]);\n\t\t\t}\n\n\t\t\treturn joinEditAndId(this.getIdAtIndex(index), edits[index - startRevision]);\n\t\t}\n\n\t\treturn this.localEdits[index - this.numberOfSequencedEdits];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.getEditInSessionAtIndex}\n\t */\n\tpublic getEditInSessionAtIndex(index: number): Edit<TChange> {\n\t\tassert(\n\t\t\tindex > this.maximumEvictableIndex,\n\t\t\t'Edit to retrieve must have been added to the log during the current session.'\n\t\t);\n\n\t\tif (index < this.numberOfSequencedEdits) {\n\t\t\tconst [startRevision, editChunk] = assertNotUndefined(this.editChunks.getPairOrNextLower(index));\n\t\t\tconst { edits } = editChunk;\n\n\t\t\treturn joinEditAndId(\n\t\t\t\tthis.getIdAtIndex(index),\n\t\t\t\tassertNotUndefined(edits, 'Edits should not have been evicted.')[index - startRevision]\n\t\t\t);\n\t\t}\n\n\t\tassert(index - this.numberOfSequencedEdits < this.localEdits.length, 'Edit to retrieve must be in the log.');\n\t\treturn this.localEdits[index - this.numberOfSequencedEdits];\n\t}\n\n\t/**\n\t * {@inheritDoc OrderedEditSet.tryGetEdit}\n\t */\n\tpublic async tryGetEdit(editId: EditId): Promise<Edit<TChange> | undefined> {\n\t\ttry {\n\t\t\tconst index = this.getIndexOfId(editId);\n\t\t\treturn await this.getEditAtIndex(index);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\t/**\n\t * @returns The edits of edit chunks that do not have associated edit handles, does not include the last edit chunk if it is not full.\n\t */\n\tpublic *getEditChunksReadyForUpload(): Iterable<[number, readonly EditWithoutId<TChange>[]]> {\n\t\tconst maxStartRevision = this.editChunks.maxKey();\n\n\t\tif (maxStartRevision === undefined) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor (const [startRevision, chunk] of this.editChunks.entries(undefined, [])) {\n\t\t\tif (chunk.handle === undefined) {\n\t\t\t\tconst edits = assertNotUndefined(chunk.edits);\n\n\t\t\t\t// If there is no handle, the chunk should either not be the last chunk or should be full if it is.\n\t\t\t\tif (maxStartRevision !== startRevision || edits.length >= this.editsPerChunk) {\n\t\t\t\t\tyield [startRevision, edits];\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Assigns provided handles to edit chunks based on chunk index specified.\n\t */\n\tpublic processEditChunkHandle(chunkHandle: EditHandle<TChange>, startRevision: number): void {\n\t\tconst chunk = this.editChunks.get(startRevision);\n\t\tif (chunk !== undefined) {\n\t\t\tassertNotUndefined(\n\t\t\t\tchunk.edits,\n\t\t\t\t'A chunk handle op should not be received before the edit ops it corresponds to.'\n\t\t\t);\n\t\t\tchunk.handle = chunkHandle;\n\t\t\tthis.addKeyToCache(startRevision);\n\t\t} else {\n\t\t\tthis.logger?.sendErrorEvent({ eventName: 'UnexpectedHistoryChunk' });\n\t\t\tthis.emit(SharedTreeDiagnosticEvent.UnexpectedHistoryChunk);\n\t\t}\n\t}\n\n\t/**\n\t * Sequences all local edits.\n\t */\n\tpublic sequenceLocalEdits(): void {\n\t\tthis.localEdits.slice().forEach((edit) => this.addSequencedEditInternal(edit));\n\t}\n\n\t/**\n\t * Adds a sequenced (non-local) edit to the edit log.\n\t * If the id of the supplied edit matches a local edit already present in the log, the local edit will be replaced.\n\t *\n\t */\n\tpublic addSequencedEdit(edit: Edit<TChange>, message: MessageSequencingInfo): void {\n\t\tthis.addSequencedEditInternal(edit, message, message.minimumSequenceNumber);\n\t}\n\n\t/**\n\t * Returns all local edits from this EditLog\n\t * This is useful for op format upgrades, which might warrant re-submission of these ops using the new format.\n\t * See the breaking change documentation for more information.\n\t */\n\tpublic *getLocalEdits(): Iterable<Edit<TChange>> {\n\t\tfor (const edit of this.localEdits) {\n\t\t\tyield edit;\n\t\t}\n\t}\n\n\t/**\n\t * Adds a sequenced (non-local) edit to the edit log.\n\t * If the id of the supplied edit matches a local edit already present in the log, the local edit will be replaced.\n\t */\n\tprivate addSequencedEditInternal(\n\t\tedit: Edit<TChange>,\n\t\tinfo?: EditSequencingInfo,\n\t\tminSequenceNumber: number = 0\n\t): void {\n\t\tconst { id, editWithoutId } = separateEditAndId(edit);\n\n\t\tassert(\n\t\t\tminSequenceNumber >= this.minSequenceNumber,\n\t\t\t'Sequenced edits should carry a monotonically increasing min number'\n\t\t);\n\t\t// The new minSequenceNumber indicates that no future edit will require information from edits with a smaller or equal seq number\n\t\t// for its resolution.\n\t\tthis._minSequenceNumber = minSequenceNumber;\n\t\t// TODO:#57176: Increment maximumEvictableIndex to reflect the fact we can now evict edits with a sequenceNumber lower or equal to\n\t\t// it. Note that this will change the meaning of our 'InSession' APIs so we should make sure to rename them at the same time.\n\t\t// The code might look like this:\n\t\t// while (this.maximumEvictableIndex + 1 < this.indexOfFirstEditInSession) {\n\t\t// \tconst nextEdit = this.getEditInSessionAtIndex(this.maximumEvictableIndex + 1);\n\t\t// \tconst nextEditInfo = this.getOrderedEditId(nextEdit.id) as SequencedOrderedEditId;\n\t\t// \tif (\n\t\t// \t\tnextEditInfo.sequenceInfo !== undefined &&\n\t\t// \t\tnextEditInfo.sequenceInfo.sequenceNumber > minSequenceNumber\n\t\t// \t) {\n\t\t// \t\tbreak;\n\t\t// \t}\n\t\t// \t++this.maximumEvictableIndex;\n\t\t// }\n\n\t\t// Remove the edit from local edits if it exists.\n\t\tconst encounteredEditId = this.allEditIds.get(id);\n\t\tif (encounteredEditId !== undefined) {\n\t\t\t// New edit already exits: it must have been a local edit.\n\t\t\tassert(encounteredEditId.isLocal, 'Duplicate acked edit.');\n\t\t\t// Remove it from localEdits. Due to ordering requirements, it must be first.\n\t\t\tconst oldLocalEditId = assertNotUndefined(this.localEdits.shift(), 'Local edit should exist').id;\n\t\t\tassert(oldLocalEditId === id, 'Causal ordering should be upheld');\n\t\t}\n\n\t\t// The starting revision for a newly created chunk.\n\t\tconst startRevision = this.numberOfSequencedEdits;\n\t\t// The initial edits for a newly created chunk.\n\t\tconst edits: EditWithoutId<TChange>[] = [editWithoutId];\n\n\t\tconst lastPair = this.editChunks.nextLowerPair(undefined);\n\t\tif (lastPair === undefined) {\n\t\t\tthis.editChunks.set(startRevision, { edits });\n\t\t} else {\n\t\t\t// Add to the last edit chunk if it has room and hasn't already been uploaded, otherwise create a new chunk.\n\t\t\t// If the chunk has a corresponding handle, create a new chunk.\n\t\t\tconst { edits: lastEditChunk, handle } = lastPair[1];\n\t\t\tif (handle === undefined && lastEditChunk !== undefined && lastEditChunk.length < this.editsPerChunk) {\n\t\t\t\tlastEditChunk.push(editWithoutId);\n\t\t\t} else {\n\t\t\t\tassert(\n\t\t\t\t\thandle !== undefined || lastEditChunk !== undefined,\n\t\t\t\t\t'An edit chunk must have either a handle or a list of edits.'\n\t\t\t\t);\n\t\t\t\tthis.editChunks.set(startRevision, { edits });\n\t\t\t}\n\t\t}\n\n\t\tthis.sequencedEditIds.push(id);\n\t\tconst sequencedEditId: SequencedOrderedEditId = {\n\t\t\tindex: this.numberOfSequencedEdits - 1,\n\t\t\tisLocal: false,\n\t\t\tsequenceInfo: info,\n\t\t};\n\t\tthis.allEditIds.set(id, sequencedEditId);\n\t\tthis.emitAdd(edit, false, encounteredEditId !== undefined);\n\t}\n\n\t/**\n\t * @returns The last edit chunk i.e. the chunk which the most recent sequenced edits have been placed into, as well as its starting revision.\n\t * Returns undefined iff there are no sequenced edits.\n\t * When defined, this chunk is guaranteed to contain at least one edit\n\t * (though it may be necessary to load the chunk via its handle to use it)\n\t */\n\tpublic getLastEditChunk(): [startRevision: number, edits: EditChunk<TChange>] | undefined {\n\t\treturn this.editChunks.nextLowerPair(undefined);\n\t}\n\n\t/**\n\t * Adds a non-sequenced (local) edit to the edit log.\n\t * Duplicate edits are ignored.\n\t */\n\tpublic addLocalEdit(edit: Edit<TChange>): void {\n\t\tthis.localEdits.push(edit);\n\t\tconst localEditId: LocalOrderedEditId = { localSequence: this.localEditSequence++, isLocal: true };\n\t\tthis.allEditIds.set(edit.id, localEditId);\n\t\tthis.emitAdd(edit, true, false);\n\t}\n\n\tprivate emitAdd(editAdded: Edit<TChange>, isLocal: boolean, wasLocal: boolean): void {\n\t\tfor (const handler of this._editAddedHandlers) {\n\t\t\thandler(editAdded, isLocal, wasLocal);\n\t\t}\n\t}\n\n\t/**\n\t * @returns true iff this `EditLog` and `other` are equivalent, regardless of locality.\n\t */\n\tpublic equals<TOtherChangeTypesInternal>(other: EditLog<TOtherChangeTypesInternal>): boolean {\n\t\t// TODO #45414: We should also be deep comparing the list of changes in the edit. This is not straightforward.\n\t\t// We can use our edit validation code when we write it since it will need to do deep walks of the changes.\n\t\treturn compareArrays(this.editIds, other.editIds);\n\t}\n\n\t/**\n\t * @returns the summary of this `OrderedEditSet` that can be used to reconstruct the edit set.\n\t * @internal\n\t */\n\tpublic getEditLogSummary(): EditLogSummary<TChange, FluidEditHandle>;\n\t/**\n\t * @param compressEdit - a function which compresses edits\n\t * @returns the summary of this `OrderedEditSet` that can be used to reconstruct the edit set.\n\t * @internal\n\t */\n\tpublic getEditLogSummary<TCompressedChange>(\n\t\tcompressEdit: (edit: Pick<Edit<TChange>, 'changes'>) => Pick<Edit<TCompressedChange>, 'changes'>\n\t): EditLogSummary<TCompressedChange, FluidEditHandle>;\n\tpublic getEditLogSummary<TCompressedChange>(\n\t\tcompressEdit?: (edit: Pick<Edit<TChange>, 'changes'>) => Pick<Edit<TCompressedChange>, 'changes'>\n\t): EditLogSummary<TChange, FluidEditHandle> | EditLogSummary<TCompressedChange, FluidEditHandle> {\n\t\tif (compressEdit !== undefined) {\n\t\t\treturn {\n\t\t\t\teditChunks: this.editChunks.toArray().map(([startRevision, { handle, edits }]) => ({\n\t\t\t\t\tstartRevision,\n\t\t\t\t\tchunk:\n\t\t\t\t\t\thandle?.baseHandle ??\n\t\t\t\t\t\tedits?.map((edit) => compressEdit(edit)) ??\n\t\t\t\t\t\tfail('An edit chunk must have either a handle or a list of edits.'),\n\t\t\t\t})),\n\t\t\t\teditIds: this.sequencedEditIds,\n\t\t\t};\n\t\t} else {\n\t\t\treturn {\n\t\t\t\teditChunks: this.editChunks.toArray().map(([startRevision, { handle, edits }]) => ({\n\t\t\t\t\tstartRevision,\n\t\t\t\t\tchunk:\n\t\t\t\t\t\thandle?.baseHandle ??\n\t\t\t\t\t\tedits ??\n\t\t\t\t\t\tfail('An edit chunk must have either a handle or a list of edits.'),\n\t\t\t\t})),\n\t\t\t\teditIds: this.sequencedEditIds,\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate addKeyToCache(newKey: number): void {\n\t\t// Indices are only added to the cache if they are not higher than the maximum evicted index.\n\t\tif (newKey <= this.maximumEvictableIndex) {\n\t\t\t// If the new index is already in the cache, remove it first to update its last usage.\n\t\t\tif (newKey in this.loadedChunkCache) {\n\t\t\t\tthis.loadedChunkCache.splice(this.loadedChunkCache.indexOf(newKey), 1);\n\t\t\t}\n\n\t\t\tthis.loadedChunkCache.push(newKey);\n\n\t\t\t// If the cache is out of space, evict the oldest index in the cache.\n\t\t\tif (this.loadedChunkCache.length > loadedChunkCacheSize) {\n\t\t\t\tconst indexToEvict = assertNotUndefined(this.loadedChunkCache.shift());\n\t\t\t\tconst chunkToEvict = assertNotUndefined(\n\t\t\t\t\tthis.editChunks.get(indexToEvict),\n\t\t\t\t\t'Chunk start revision added to cache should exist in the edit log.'\n\t\t\t\t);\n\t\t\t\tchunkToEvict.edits = undefined;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction isEditHandle<TChange>(\n\tchunk: EditHandle<TChange> | readonly EditWithoutId<unknown>[]\n): chunk is EditHandle<TChange> {\n\treturn !Array.isArray(chunk);\n}\n"]}